Merge pull request #7 from tanaydin/python3
Reformated files for python3, changed some function calls.pull/10/head
commit
659b6a1e2c
145
detection.py
145
detection.py
|
@ -8,105 +8,104 @@ 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 +113,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))
|
||||
|
|
74
functions.py
74
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, "","")
|
||||
|
|
20
index.py
20
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)
|
||||
|
|
Loading…
Reference in New Issue