From be2d110578da152038987edaab0d79eb4096d4b5 Mon Sep 17 00:00:00 2001 From: Tanaydin Sirin Date: Fri, 5 Apr 2019 15:38:57 +0200 Subject: [PATCH 1/2] Reformated files for python3, changed some function calls. --- detection.py | 146 +++++++++++++++++++++++++-------------------------- functions.py | 74 +++++++++++++------------- index.py | 20 +++---- 3 files changed, 120 insertions(+), 120 deletions(-) diff --git a/detection.py b/detection.py index eb28031..fdd8521 100644 --- a/detection.py +++ b/detection.py @@ -8,105 +8,105 @@ from functions import * result_count = 0 result_files = 0 + # Analyse the source code of a single page -def analysis(path,plain): - global result_files - result_files += 1 - with open(path, 'r') as content_file: +def analysis(path, plain): + global result_files + result_files += 1 + with open(path, 'r') as content_file: - # Clean source for a better detection - content = content_file.read() - content = clean_source_and_format(content) + # Clean source for a better detection + content = content_file.read() + content = clean_source_and_format(content) - # Hardcoded credentials (work as an exception, it's not function based) - credz = ['pass', 'secret', 'token', 'pwd'] - for credential in credz: + # Hardcoded credentials (work as an exception, it's not function based) + credz = ['pass', 'secret', 'token', 'pwd'] + for credential in credz: - content_pure = content.replace(' ','') - regex = re.compile("\$"+credential+".*?=[\"|'][^\$]+[\"|']", re.I) - matches = regex.findall(content_pure) + content_pure = content.replace(' ', '') + regex = re.compile("\$" + credential + ".*?=[\"|'][^\$]+[\"|']", re.I) + matches = regex.findall(content_pure) - # If we find a variable with a constant for a given indicator - for vuln_content in matches: - payload = ["","Hardcoded Credential",[]] + # If we find a variable with a constant for a given indicator + for vuln_content in matches: + payload = ["", "Hardcoded Credential", []] - # Get the line - line_vuln = -1 - splitted_content = content.split('\n') - for i in range(len( splitted_content )): - regex = re.compile("\$"+credential+".*?=", re.I) - matches = regex.findall(splitted_content[i]) - if len(matches) > 0: - line_vuln = i + # Get the line + line_vuln = -1 + splitted_content = content.split('\n') + for i in range(len(splitted_content)): + regex = re.compile("\$" + credential + ".*?=", re.I) + matches = regex.findall(splitted_content[i]) + if len(matches) > 0: + line_vuln = i - declaration_text = vuln_content - line_declaration = str(line_vuln) - occurence = 1 + declaration_text = vuln_content + line_declaration = str(line_vuln) + occurence = 1 - display(path, payload, vuln_content, line_vuln, declaration_text, line_declaration, vuln_content, occurence, plain) + display(path, payload, vuln_content, line_vuln, declaration_text, line_declaration, vuln_content, occurence, plain) + # Detection of RCE/SQLI/LFI/RFI/RFU/XSS/... + for payload in payloads: + regex = re.compile(payload[0] + regex_indicators) + matches = regex.findall(content) - # Detection of RCE/SQLI/LFI/RFI/RFU/XSS/... - for payload in payloads: - regex = re.compile(payload[0]+regex_indicators) - matches = regex.findall(content) + for vuln_content in matches: + occurence = 0 - for vuln_content in matches: - occurence = 0 + # Security hole detected, is it protected ? + if check_protection(payload[2], vuln_content) == False: + declaration_text, line_declaration = "", "" - # Security hole detected, is it protected ? - if check_protection(payload[2], vuln_content) == False: - declaration_text, line_declaration = "","" + # Managing multiple variable in a single line/function + sentence = "".join(vuln_content) + regax = re.compile(regex_indicators[2:-2]) + for vulnerable_var in regax.findall(sentence): + false_positive = False + occurence += 1 - # Managing multiple variable in a single line/function - sentence = "".join(vuln_content) - regax = re.compile(regex_indicators[2:-2]) - for vulnerable_var in regax.findall(sentence): - false_positive = False - occurence += 1 + # No declaration for $_GET, $_POST ... + if check_exception(vulnerable_var[1]) == False: + # Look for the declaration of $something = xxxxx + false_positive, declaration_text, line_declaration = check_declaration(content, vulnerable_var[1], path) - # No declaration for $_GET, $_POST ... - if check_exception(vulnerable_var[1]) == False: + # Set false positive if protection is in the variable's declaration + false_positive = false_positive or check_protection(payload[2], declaration_text) == True - # Look for the declaration of $something = xxxxx - false_positive, declaration_text, line_declaration = check_declaration(content, vulnerable_var[1], path) + # Display all the vuln + line_vuln = find_line_vuln(path, payload, vuln_content, content) - # Set false positive if protection is in the variable's declaration - false_positive = false_positive or check_protection(payload[2], declaration_text)==True + # Check for not $dest="constant"; $dest='cste'; $dest=XX; + if not "$_" in vulnerable_var[1]: + if not "$" in declaration_text.replace(vulnerable_var[1], ''): + false_positive = True - # Display all the vuln - line_vuln = find_line_vuln(path, payload, vuln_content, content) - - # Check for not $dest="constant"; $dest='cste'; $dest=XX; - if not "$_" in vulnerable_var[1]: - if not "$" in declaration_text.replace(vulnerable_var[1],''): - false_positive = True - - if not false_positive: - global result_count - result_count = result_count + 1 - display(path, payload, vuln_content, line_vuln, declaration_text, line_declaration, vulnerable_var[1], occurence, plain) + if not false_positive: + global result_count + result_count = result_count + 1 + display(path, payload, vuln_content, line_vuln, declaration_text, line_declaration, vulnerable_var[1], occurence, plain) # Run thru every files and subdirectories -def recursive(dir,progress,plain): +def recursive(dir, progress, plain): progress += 1 progress_indicator = '⬛' if plain: progress_indicator = "█" try: - for name in os.listdir(dir): + for name in os.listdir(dir): - print('\tAnalyzing : '+ progress_indicator * progress+'\r'), + print('\tAnalyzing : ' + progress_indicator * progress + '\r'), - # Targetting only PHP Files - if os.path.isfile(os.path.join(dir, name)): - if ".php" in os.path.join(dir, name): - analysis(dir+"/"+name,plain) - else : - recursive(dir+"/"+name, progress,plain) + # Targetting only PHP Files + if os.path.isfile(os.path.join(dir, name)): + if ".php" in os.path.join(dir, name): + analysis(dir + "/" + name, plain) + else: + recursive(dir + "/" + name, progress, plain) - except OSError, e: - print "Error 404 - Not Found, maybe you need more right ?"+" "*30 + except OSError as e: + print + "Error 404 - Not Found, maybe you need more right ?" + " " * 30 exit(-1) @@ -114,4 +114,4 @@ def recursive(dir,progress,plain): def scanresults(): global result_count global result_files - print ("Found {} vulnerabilities in {} files").format(result_count,result_files) + print("Found {} vulnerabilities in {} files".format(result_count, result_files)) diff --git a/functions.py b/functions.py index 13480f1..6abd67d 100644 --- a/functions.py +++ b/functions.py @@ -30,11 +30,11 @@ def display(path,payload,vulnerability,line,declaration_text,declaration_line, c # Final Display rows, columns = os.popen('stty size', 'r').read().split() - print "-" * (int(columns)-1) - print "Name \t{}".format(header) - print "-" * (int(columns)-1) - print "{}Line {} {}".format('' if plain else '\033[1m', '' if plain else '\033[0m', line) - print "{}Code {} {}".format('' if plain else '\033[1m', '' if plain else '\033[0m', vuln) + print("-" * (int(columns)-1)) + print("Name \t{}".format(header)) + print("-" * (int(columns)-1)) + print("{}Line {} {}".format('' if plain else '\033[1m', '' if plain else '\033[0m', line)) + print("{}Code {} {}".format('' if plain else '\033[1m', '' if plain else '\033[0m', vuln)) # Declared at line 1 : $dest = $_GET['who']; if not "$_" in colored: @@ -43,34 +43,34 @@ def display(path,payload,vulnerability,line,declaration_text,declaration_line, c declared = "Line n°{}{}{} : {}".format('' if plain else '\033[0;92m', declaration_line, '' if plain else '\033[0m', declaration_text) #declared = "Line n°\033[0;{}m{}\033[0m : {}".format('0' if plain else '92', declaration_line, declaration_text) - print "{}Declaration {} {}".format('' if plain else '\033[1m', '' if plain else '\033[0m', declared) + print("{}Declaration {} {}".format('' if plain else '\033[1m', '' if plain else '\033[0m', declared)) # Small delimiter - print "" + print("") # Find the line where the vulnerability is located def find_line_vuln(path,payload,vulnerability,content): - content = content.split('\n') - for i in range(len(content)): - if payload[0]+'('+vulnerability[0]+vulnerability[1]+vulnerability[2]+')' in content[i]: - return str(i-1) - return "-1" + content = content.split('\n') + for i in range(len(content)): + if payload[0]+'('+vulnerability[0]+vulnerability[1]+vulnerability[2]+')' in content[i]: + return str(i-1) + return "-1" # Find the line where the entry point is declared # TODO: should be an array of the declaration and modifications def find_line_declaration(declaration, content): - content = content.split('\n') - for i in range(len(content)): - if declaration in content[i]: - return str(i) - return "-1" + content = content.split('\n') + for i in range(len(content)): + if declaration in content[i]: + return str(i) + return "-1" # Format the source code in order to improve the detection def clean_source_and_format(content): # Clean up - replace tab by space - content = content.replace(" "," ") + content = content.replace(" "," ") # Quickfix to detect both echo("something") and echo "something" content = content.replace("echo ","echo(") @@ -99,37 +99,37 @@ def check_declaration(content, vuln, path): regex_declaration = re.compile("(include.*?|require.*?)\([\"\'](.*?)[\"\']\)") includes = regex_declaration.findall(content) - # Path is the path of the current scanned file, we can use it to compute the relative include + # Path is the path of the current scanned file, we can use it to compute the relative include for include in includes: - relative_include = os.path.dirname(path)+"/" - try: - path_include = relative_include + include[1] - with open(path_include, 'r') as f: - content = f.read() + content - except Exception as e: - return (False, "","") + relative_include = os.path.dirname(path)+"/" + try: + path_include = relative_include + include[1] + with open(path_include, 'r') as f: + content = f.read() + content + except Exception as e: + return (False, "","") - # Extract declaration - for ($something as $somethingelse) + # Extract declaration - for ($something as $somethingelse) vulnerability = vuln[1:].replace(')', '\)').replace('(', '\(') regex_declaration2 = re.compile("\$(.*?)([\t ]*)as(?!=)([\t ]*)\$"+vulnerability) declaration2 = regex_declaration2.findall(content) if len(declaration2) > 0: - return check_declaration(content, "$"+declaration2[0][0], path) + return check_declaration(content, "$"+declaration2[0][0], path) - # Extract declaration - $something = $_GET['something'] + # Extract declaration - $something = $_GET['something'] regex_declaration = re.compile("\$"+vulnerability+"([\t ]*)=(?!=)(.*)") declaration = regex_declaration.findall(content) if len(declaration)>0: - # Check constant then return True if constant because it's false positive - declaration_text = "$"+vulnerability +declaration[0][0]+"="+declaration[0][1] - line_declaration = find_line_declaration(declaration_text, content) - regex_constant = re.compile("\$"+vuln[1:]+"([\t ]*)=[\t ]*?([\"\'(]*?[a-zA-Z0-9{}_\(\)@\.,!: ]*?[\"\')]*?);") - false_positive = regex_constant.match(declaration_text) + # Check constant then return True if constant because it's false positive + declaration_text = "$"+vulnerability +declaration[0][0]+"="+declaration[0][1] + line_declaration = find_line_declaration(declaration_text, content) + regex_constant = re.compile("\$"+vuln[1:]+"([\t ]*)=[\t ]*?([\"\'(]*?[a-zA-Z0-9{}_\(\)@\.,!: ]*?[\"\')]*?);") + false_positive = regex_constant.match(declaration_text) - if false_positive: - return (True, "","") - return (False, declaration_text,line_declaration) + if false_positive: + return (True, "","") + return (False, declaration_text,line_declaration) return (False, "","") diff --git a/index.py b/index.py index 6786909..899aec6 100644 --- a/index.py +++ b/index.py @@ -20,16 +20,16 @@ if __name__ == "__main__": results = parser.parse_args() if results.dir != None: - print " (`-') <-. (`-')_ _(`-') (`-') _" - print " _(OO ) .-> <-. \( OO) ) .-> _ .-> ( (OO ).-> ( OO).-/" - print ",--.(_/,-.\,--.(,--. ,--. ) ,--./ ,--/ ,--.' ,-.\-,-----.(`-')----. \ .'_ (,------." - print "\ \ / (_/| | |(`-') | (`-')| \ | | (`-')'.' / | .--./( OO).-. ''`'-..__) | .---'" - print " \ / / | | |(OO ) | |OO )| . '| |)(OO \ / /_) (`-')( _) | | || | ' |(| '--." - print "_ \ /_)| | | | \(| '__ || |\ | | / /) || |OO ) \| |)| || | / : | .--'" - print "\-'\ / \ '-'(_ .' | |'| | \ | `-/ /` (_' '--'\ ' '-' '| '-' / | `---." - print " `-' `-----' `-----' `--' `--' `--' `-----' `-----' `------' `------'" - print " Copyright @pentest_swissky " - print ("\n{}Analyzing '{}' source code{}".format('' if results.plain else '\033[1m', results.dir, '' if results.plain else '\033[0m')) + print(""" (`-') <-. (`-')_ _(`-') (`-') _ + _(OO ) .-> <-. \( OO) ) .-> _ .-> ( (OO ).-> ( OO).-/ + ,--.(_/,-.\,--.(,--. ,--. ) ,--./ ,--/ ,--.' ,-.\-,-----.(`-')----. \ .'_ (,------. + \ \ / (_/| | |(`-') | (`-')| \ | | (`-')'.' / | .--./( OO).-. ''`'-..__) | .---' + \ / / | | |(OO ) | |OO )| . '| |)(OO \ / /_) (`-')( _) | | || | ' |(| '--. + _ \ /_)| | | | \(| '__ || |\ | | / /) || |OO ) \| |)| || | / : | .--' + \-'\ / \ '-'(_ .' | |'| | \ | `-/ /` (_' '--'\ ' '-' '| '-' / | `---. + `-' `-----' `-----' `--' `--' `--' `-----' `-----' `------' `------' + Copyright @pentest_swissky """) + print("\n{}Analyzing '{}' source code{}".format('' if results.plain else '\033[1m', results.dir, '' if results.plain else '\033[0m')) if os.path.isfile(results.dir): analysis(results.dirm, results.plain) From b3734a43f7d142eefa174dbee16050aa68c397d0 Mon Sep 17 00:00:00 2001 From: Tanaydin Sirin Date: Fri, 5 Apr 2019 15:43:04 +0200 Subject: [PATCH 2/2] Python3 fix for directory not found error. --- detection.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/detection.py b/detection.py index fdd8521..a53bbe4 100644 --- a/detection.py +++ b/detection.py @@ -105,8 +105,7 @@ def recursive(dir, progress, plain): recursive(dir + "/" + name, progress, plain) except OSError as e: - print - "Error 404 - Not Found, maybe you need more right ?" + " " * 30 + print("Error 404 - Not Found, maybe you need more right ?" + " " * 30) exit(-1)