From b30efdb4830a343517c557bf6a280c7e26ba9046 Mon Sep 17 00:00:00 2001 From: nihilist Date: Mon, 13 Jan 2025 08:54:31 +0100 Subject: [PATCH] option 6 almost completed --- README.md | 17 +++ scripts/darknet_exploration.py | 131 ++++++++++++------ .../banner.png | Bin 0 -> 14119 bytes .../blacklist.csv | 2 + .../sensitive.csv | 5 + .../unverified.csv | 3 + .../verified.csv | 1 + .../webring-participants.csv | 25 ++++ .../blacklist.csv | 5 + .../unverified.csv | 19 --- .../verified.csv | 10 ++ .../webring-participants.csv | 1 - 12 files changed, 155 insertions(+), 64 deletions(-) create mode 100644 www/participants/uptime.BACKUPjezfoltodf4jiyl6r56jnzintap5vyjlia7fkirfsnfizflqd.onion/banner.png create mode 100644 www/participants/uptime.BACKUPjezfoltodf4jiyl6r56jnzintap5vyjlia7fkirfsnfizflqd.onion/blacklist.csv create mode 100644 www/participants/uptime.BACKUPjezfoltodf4jiyl6r56jnzintap5vyjlia7fkirfsnfizflqd.onion/sensitive.csv create mode 100644 www/participants/uptime.BACKUPjezfoltodf4jiyl6r56jnzintap5vyjlia7fkirfsnfizflqd.onion/unverified.csv create mode 100644 www/participants/uptime.BACKUPjezfoltodf4jiyl6r56jnzintap5vyjlia7fkirfsnfizflqd.onion/verified.csv create mode 100644 www/participants/uptime.BACKUPjezfoltodf4jiyl6r56jnzintap5vyjlia7fkirfsnfizflqd.onion/webring-participants.csv diff --git a/README.md b/README.md index 44257f6..51aa2c3 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,22 @@ # [Darknet Onion Webring (WIP)](http://uptime.nowherejezfoltodf4jiyl6r56jnzintap5vyjlia7fkirfsnfizflqd.onion/) +``` +# Main features: +TODO: +-py : option 6) Trust/Untrust/Blacklist a webring participant +-py : option 7) Add/Remove words in the sensitive list (assigned to anon) +-py : option 8) Add/Remove words in the blacklist (assigned to anon) + +-php : make a search engine prompt that only accepts [a-zA-Z.://], it must refuse every other character +-php : if valid make it search your own verified.csv and unverified.csv files + +# secondary features: +-php : interactive search engine ? it displays as you type it ? +-py : option 9) cleanup all duplicates in your own unverified.csv and verified.csv +-py : option 10) perform sanity checks on all csv files (to mark them as sensitive or remove the ones that are blacklisted) + +``` + ![logo](./project.png) Darknet Onion Webring is powered by a Minimalistic Onion Hidden Service uptime checker, written in only PHP and Python, because javascript is NOT needed. diff --git a/scripts/darknet_exploration.py b/scripts/darknet_exploration.py index 4bcc19f..5030157 100644 --- a/scripts/darknet_exploration.py +++ b/scripts/darknet_exploration.py @@ -591,55 +591,98 @@ Maintenance: case "6": print("[+] Trust/UnTrust/Blacklist a webring participant (Potentially dangerous)") - # TODO list each webring participant in your webring-participants.csv file - # TODO ask the user to pick an index - # TODO once a valid index is picked, ask if the user wants to 1) trust the webring participant, or 2) untrust them, or 3) black list them - # if 1: - #ask the user if they want to proceed, as this is potentially risky if the webring participant tries to list malicious links in the future - #choice=input("You're about to trust another peer, this means that you're going to automatically trust all of the links they have in their verified.csv file! If this is a malicious peer, you're about to potentially trust malicious links, it is potentially risky! Do you want to continue ? (y/n)") - # if user wants to proceed, mark the "trusted" column as V + webringcsvfile=instancepath+'/'+'webring-participants.csv' + wdf = pd.read_csv(webringcsvfile) + # list each webring participant in your webring-participants.csv file + print(wdf[["URL","Trusted"]]) + # ask the user to pick an index + index="" + while (index not in wdf.index): + # prompt the user to ask for with row they want to move to verified.csv + index = int(input("What is the index of the webring participant that you want to edit ? (ex: 3) ")) + # once a valid index is picked, ask if the user wants to 1) trust the webring participant, or 2) untrust them, or 3) black list them + choice="" + while (choice not in ["1","2","3"]): + choice = input("Do you want to 1) Trust, 2) UnTrust, or 3) Blacklist the webring participant ?") + if choice == "1": + # trust the webring participant + # ask the user if they want to proceed, as this is potentially risky if the webring participant tries to list malicious links in the future + choice2=input("You're about to trust another peer, this means that you're going to automatically trust all of the links they have in their verified.csv file! If this is a malicious peer, you're about to potentially going to automatically trust malicious links, it is potentially risky! Do you want to continue ? (y/n)") + if choice2 == "y": + # if user wants to proceed, mark the "trusted" column as V + print("[+] Trusting webring participant", wdf.at[index,"URL"]) + wdf.at[index,"Trusted"]='✔️' + + else: + print("[-] not trusting webring participant, skipping.") + if choice == "2": + print("[+] UnTrusting webring participant", wdf.at[index,"URL"]) + wdf.at[index,"Trusted"]='' + # untrust the webring participant # if 2: mark the "trusted" column as empty - # if 3: - # TODO add it's URL to your own blacklist.csv - # TODO remove all of the entries that came from that participant (drop the lines in verified+unverified.csv that have that instance in the instance column) - # TODO remove it from your own webring-participants.csv - # TODO remove the entire directory in www/participants/INSTANCENAME + if choice == "3": + print("[+] Blacklisting webring participant", wdf.at[index,"URL"]) + # blacklist the webring participant + # add it's URL to your own blacklist.csv + instance2blacklist=wdf.at[index,"URL"] + newrow=[instance2blacklist] + print("[+] NEWROW=",newrow) + # (rest is automatic: status, score, instance is = '' because it is your own instance) + # check if the entry doesn't already exist in verified.csv and in unverified.csv + # if it doesnt exist, add it into unverified.csv + bldf.loc[-1] = newrow # adding a row + bldf.index = bldf.index + 1 # shifting index + bldf = bldf.sort_index() # sorting by index + print("[+] New row added! now writing the csv file:") + bldf.to_csv(blcsvfile, index=False) + # remove all of the entries that came from that participant (drop the lines in your own verified+unverified.csv that have that instance in the instance column) + #vdf + rows2delete= [] # it is an empty list at first + for i,j in vdf.iterrows(): + row=vdf.loc[i,:].values.tolist() + for k,l in bldf.iterrows(): + #print("[+] Blacklisted word=",k, bldf.at[k, 'blacklisted-words']) + blword=bldf.at[k, 'blacklisted-words'] + if any(blword in str(x) for x in row) == True: + #print("found blacklisted word! marking row for deletion") + if i not in rows2delete: + print("Marking row", i,"for deletion, as it matches with a blacklisted word") + rows2delete.append(i) #mark the row for deletion if not already done + for i in rows2delete: + row=vdf.loc[i,:].values.tolist() + print('[+] REMOVING ROW :',i,row) + vdf.drop(i, inplace= True) + vdf.to_csv(verifiedcsvfile, index=False) + print(vdf) + rows2delete= [] # it is an empty list at first + #uvdf + rows2delete= [] # it is an empty list at first + for i,j in uvdf.iterrows(): + row=uvdf.loc[i,:].values.tolist() + for k,l in bldf.iterrows(): + #print("[+] Blacklisted word=",k, bldf.at[k, 'blacklisted-words']) + blword=bldf.at[k, 'blacklisted-words'] + if any(blword in str(x) for x in row) == True: + #print("found blacklisted word! marking row for deletion") + if i not in rows2delete: + print("Marking row", i,"for deletion, as it matches with a blacklisted word") + rows2delete.append(i) #mark the row for deletion if not already done + for i in rows2delete: + row=uvdf.loc[i,:].values.tolist() + print('[+] REMOVING ROW :',i,row) + uvdf.drop(i, inplace= True) + uvdf.to_csv(unverifiedcsvfile, index=False) + print(uvdf) + rows2delete= [] # it is an empty list at first - - - - - - - - - # TODO ask if you want to trust or untrust a webring participant - # TODO print a warning to tell the user that you're about to trust all of the links that are trusted by another peer, if that peer is malicious they may start trusting links that you don't trust! proceed? (answer is y otherwise skip) - choice='' - if choice == "y": - # TODO list all of the webring participants in webring-participants.csv - print("Please choose a webring participant to trust:") - # TODO make the user choose a valid index - # TODO and write V into the "Trusted" column - # TODO for each row in the webring participant's verified.csv file, (use the url to check) - # TODO check if it already exists or not in your verified.csv file (if length of url to check is 0 then save and add new row, else ignore it) - # TODO write to csv - else: - print("Exiting.") - searchterm = input("What is the index of the entry that you want to trust ?") - - # TODO - print("[+] Untrust a webring participant (safer)") - print("Please choose a webring participant to untrust:") - # TODO list the webring participants in the webring-participants.csv file - # TODO make the user choose a valid index - # TODO and write "" into the "Trusted" column - - - + # TODO find all rows that match with the instance name in wdf aswell + wdf.drop(index, inplace= True) + wdf.to_csv(webringcsvfile, index=False) + print(wdf) + # TODO remove the entire directory in www/participants/INSTANCENAME diff --git a/www/participants/uptime.BACKUPjezfoltodf4jiyl6r56jnzintap5vyjlia7fkirfsnfizflqd.onion/banner.png b/www/participants/uptime.BACKUPjezfoltodf4jiyl6r56jnzintap5vyjlia7fkirfsnfizflqd.onion/banner.png new file mode 100644 index 0000000000000000000000000000000000000000..8e7af7380ab4bf22a26251b78949ea8efe89c0a6 GIT binary patch literal 14119 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 ZTzN}Ry>fC