def add_findings(title, scan_rules, line_no, lines, full_file_path): """Add Findings""" filename = ntpath.basename(full_file_path) finding = {} finding["title"] = title finding["description"] = scan_rules["desc"][title] finding["tag"] = scan_rules["tag"][title] finding["line"] = line_no + 1 finding["lines"] = get_lines(line_no, lines) finding["filename"] = filename finding["path"] = full_file_path.replace(settings.UPLOAD_FOLDER, "", 1) finding["sha2"] = utils.gen_sha256_hash(finding["lines"]) return finding
def general_code_analysis(paths): """Static Code Analysis""" try: scan_results = {} scan_rules = read_rules() security_issues = [] good_finding = [] missing_header = [] all_files = [] # Initializing Security Header flag as not present header_found = {} sec_issues_by_tag = {} good_finding_by_tag = {} missing_header_by_tag = {} vuln_n_count = {} count = {} # Sort By Tag tags = {'rce': 'Remote Command Execution', 'rci': 'Remote Code Injection', 'ssrf': 'Server Side Request Forgery', 'module': 'Vulnerable Node Module', 'node': 'Application Related', 'web': 'Web Security', 'dir': 'Directory Traversal', 'opr': 'Open Redirect Vulnerability', 'sqli': 'SQL Injection (SQLi)', 'xss': 'Cross Site Scripting (XSS)', 'nosqli': 'NoSQL Injection', 'hhi': 'HTTP Header Injection', } for path in paths: for header in scan_rules["missing_sec_header"].iterkeys(): header_found[header] = 0 print "\n[INFO] Running Static Analyzer Running on - " + path + "\n" for root, _, files in os.walk(path): for filename in files: full_file_path = os.path.join(root, filename) relative_path = full_file_path.replace(path, "") all_files.append({relative_path.replace("/", "", 1): full_file_path.replace(settings.UPLOAD_FOLDER, "", 1)}) data = is_valid_node(filename, full_file_path) if data is not None: # print relative_path beautified_data = None lines = data.splitlines() if len(lines) <= 2: # Possible Minified Single Line Code try: # Try Because of Possible Bug in JS Beautifier beautified_data = jsbeautifier.beautify(data) lines = beautified_data.splitlines() except: pass for line_no, line in enumerate(lines): # Avoid Comments - Multiline is a problem still if not line.lstrip().startswith("//") and not line.lstrip().startswith("/*"): # Limit the no of caracters in a line to 2000 line = line[0:2000] # Vulnerability String Match for rule_key in scan_rules["vuln_rules"].iterkeys(): if scan_rules["vuln_rules"][rule_key] in line: finding = {} finding["title"] = rule_key finding["description"] = scan_rules[ "desc"][rule_key] finding["tag"] = scan_rules[ "tag"][rule_key] finding["line"] = line_no + 1 finding["lines"] = get_lines( line_no, lines) finding["filename"] = filename finding["path"] = full_file_path.replace(settings.UPLOAD_FOLDER,"",1) finding["sha2"] = utils.gen_sha256_hash( str(finding["lines"])) security_issues.append(finding) # Vulnerability Regex Match for regex in scan_rules["vuln_regex"].iterkeys(): if re.search(scan_rules["vuln_regex"][regex], line): finding = {} finding["title"] = regex finding["description"] = scan_rules[ "desc"][regex] finding["tag"] = scan_rules[ "tag"][regex] finding["line"] = line_no + 1 finding["lines"] = get_lines( line_no, lines) finding["filename"] = filename finding["path"] = full_file_path.replace(settings.UPLOAD_FOLDER,"",1) finding["sha2"] = utils.gen_sha256_hash( str(finding["lines"])) security_issues.append(finding) # Vulnerability Multi Regex Match for mulregex in scan_rules["vuln_mul_regex"].iterkeys(): sig_source = scan_rules["vuln_mul_regex"][ mulregex]["sig_source"] sig_line = scan_rules["vuln_mul_regex"][ mulregex]["sig_line"] if re.search(sig_source, data): if re.search(sig_line, line): finding = {} finding["title"] = mulregex finding["description"] = scan_rules[ "desc"][mulregex] finding["tag"] = scan_rules[ "tag"][mulregex] finding["line"] = line_no + 1 finding["lines"] = get_lines( line_no, lines) finding["filename"] = filename finding["path"] = full_file_path.replace(settings.UPLOAD_FOLDER,"",1) finding["sha2"] = utils.gen_sha256_hash( str(finding["lines"])) security_issues.append(finding) # Dynamic Regex for dynregex in scan_rules["vuln_dyn_regex"].iterkeys(): signature = scan_rules["vuln_dyn_regex"][ dynregex]["signature"] dyn_sig = scan_rules["vuln_dyn_regex"][ dynregex]["dyn_sig"] sig = re.search(signature, line) if sig: index = line.find(sig.group()) dyn_variable = line[0:index] dyn_variable = dyn_variable.replace( "var", "").replace("=", "").strip() if re.match(r'^[\w]+$', dyn_variable): dyn_sig = dyn_variable + dyn_sig for line_no, nline in enumerate(lines): if re.search(dyn_sig, nline): finding = {} finding["title"] = dynregex finding["description"] = scan_rules[ "desc"][dynregex] finding["tag"] = scan_rules[ "tag"][dynregex] finding[ "line"] = line_no + 1 finding["lines"] = get_lines( line_no, lines) finding[ "filename"] = filename finding[ "path"] = full_file_path.replace(settings.UPLOAD_FOLDER,"",1) finding["sha2"] = utils.gen_sha256_hash( str(finding["lines"])) security_issues.append( finding) # Good Finding String Match for good_find in scan_rules["good_to_have_rgx"].iterkeys(): if re.search(scan_rules["good_to_have_rgx"][good_find], line): finding = {} finding["title"] = good_find finding["description"] = scan_rules[ "desc"][good_find] finding["tag"] = scan_rules[ "tag"][good_find] finding["line"] = line_no + 1 finding["lines"] = get_lines( line_no, lines) finding["filename"] = filename finding["path"] = full_file_path.replace(settings.UPLOAD_FOLDER,"",1) finding["sha2"] = utils.gen_sha256_hash( str(finding["lines"])) good_finding.append(finding) # Missing Security Headers String Match for header in scan_rules["missing_sec_header"].iterkeys(): if re.search(scan_rules["missing_sec_header"][header], line, re.I): # Good Header is present header_found[header] = 1 # Write Beautifed Data If Any if beautified_data is not None: utils.unicode_safe_file_write( full_file_path, beautified_data) # After Every Files are done. # Check for missing Security Headers for header in header_found.iterkeys(): if header_found[header] == 0: finding = {} finding["title"] = header finding["description"] = scan_rules["desc"][header] finding["tag"] = scan_rules["tag"][header] missing_header.append(finding) #Vulnerability and Count for issue in security_issues: if not issue["title"] in vuln_n_count: vuln_n_count[issue["title"]] = 0 vuln_n_count[issue["title"]] += 1 for issue in security_issues: if not tags[issue["tag"]] in sec_issues_by_tag: sec_issues_by_tag[tags[issue["tag"]]] = [] sec_issues_by_tag[tags[issue["tag"]]].append(issue) for find in good_finding: if not tags[find["tag"]] in good_finding_by_tag: good_finding_by_tag[tags[find["tag"]]] = [] good_finding_by_tag[tags[find["tag"]]].append(find) for sec_header in missing_header: if not tags[sec_header["tag"]] in missing_header_by_tag: missing_header_by_tag[tags[sec_header["tag"]]] = [] missing_header_by_tag[tags[sec_header["tag"]]].append(sec_header) count["sec"] = len(security_issues) count["mis"] = len(missing_header) count["good"] = len(good_finding) scan_results["sec_issues"] = sec_issues_by_tag scan_results["good_finding"] = good_finding_by_tag scan_results["missing_sec_header"] = missing_header_by_tag scan_results["total_count"] = count scan_results["vuln_count"] = vuln_n_count scan_results["files"] = all_files return scan_results except: utils.print_exception("Error Performing Code Analysis")