2019-11-03 14:26:43 +00:00
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Finding potential software vulnerabilities from git commit messages
#
# Software is free software released under the "GNU Affero General Public License v3.0"
#
# This software is part of cve-search.org
#
# Copyright (c) 2019 Alexandre Dulaunoy - a@foo.be
import re
import git
import json
import sys
import argparse
2019-12-17 07:45:28 +00:00
import typing
2019-11-03 14:26:43 +00:00
parser = argparse . ArgumentParser ( description = " Finding potential software vulnerabilities from git commit messages. " , epilog = " More info: https://github.com/cve-search/git-vuln-finder " )
parser . add_argument ( " -v " , help = " increase output verbosity " , action = " store_true " )
parser . add_argument ( " -r " , type = str , help = " git repository to analyse " )
parser . add_argument ( " -o " , type = str , help = " Output format: [json] " , default = " json " )
2019-11-03 20:04:09 +00:00
parser . add_argument ( " -s " , type = str , help = " State of the commit found " , default = " under-review " )
2019-12-17 07:45:28 +00:00
parser . add_argument ( " -p " , type = str , help = " Matching pattern to use: [vulnpatterns, cryptopatterns, cpatterns] - the pattern ' all ' is used to match all the patterns at once. " , default = " vulnpatterns " )
2019-11-03 14:26:43 +00:00
args = parser . parse_args ( )
2019-11-04 06:27:16 +00:00
vulnpatterns = re . compile ( " (?i)(denial of service | \b XXE \b |remote code execution| \b open redirect|OSVDB| \b vuln| \b CVE \b | \b XSS \b | \b ReDoS \b | \b NVD \b |malicious|x− frame− options|attack|cross site |exploit|malicious|directory traversal | \b RCE \b | \b dos \b | \b XSRF \b | \b XSS \b |clickjack|session.fixation|hijack| \b advisory| \b insecure |security | \b cross− origin \b |unauthori[z|s]ed |infinite loop) " )
2019-11-03 14:26:43 +00:00
2019-12-17 10:16:00 +00:00
cryptopatterns = re . compile ( " .*(assessment|lack of|bad|vulnerable|missing|unproper|unsuitable|breakable|broken|weak|incorrect|replace|assessment|pen([ \ s-]?)test|pentest|penetration([ \ s-]?)test|report|vulnerablity|replace|fix|issue|fixes|add|remove|check) { 1,} (crypto|cryptographic|cryptography|encipherement|encryption|ciphers|cipher|AES|DES|3DES|cipher|GPG|PGP|OpenSSL|SSH|wireguard|VPN|CBC|ECB|CTR|key[.|,| \ s]|private([ \ s-]?)key|public([ \ s-]?)key size|length|strenght|generation|randomness|entropy|prng|rng) { 1,} " )
2019-12-17 09:51:45 +00:00
2019-11-15 06:39:19 +00:00
cpatterns = re . compile ( " (?i)(double[-| ]free|buffer overflow|double free|race[-| ]condition) " )
if args . p == " vulnpatterns " :
defaultpattern = vulnpatterns
elif args . p == " cryptopatterns " :
defaultpattern = cryptopatterns
elif args . p == " cpatterns " :
defaultpattern = cpatterns
2019-12-17 07:45:28 +00:00
elif args . p == " all " :
defaultpattern = [ vulnpatterns , cryptopatterns , cpatterns ]
2019-11-15 06:39:19 +00:00
else :
parser . print_usage ( )
parser . exit ( )
2019-11-03 14:26:43 +00:00
if not args . r :
parser . print_usage ( )
parser . exit ( )
else :
repo = git . Repo ( args . r )
found = 0
potential_vulnerabilities = { }
2019-11-15 06:39:19 +00:00
def find_vuln ( commit , pattern = vulnpatterns ) :
m = pattern . search ( commit . message )
2019-11-03 14:26:43 +00:00
if m :
if args . v :
print ( " Match found: {} " . format ( m . group ( 0 ) ) , file = sys . stderr )
print ( commit . message , file = sys . stderr )
print ( " --- " , file = sys . stderr )
ret = { }
ret [ ' commit ' ] = commit
2019-12-17 10:10:10 +00:00
ret [ ' match ' ] = m . groups ( )
2019-11-03 14:26:43 +00:00
return ret
else :
return None
2019-12-17 07:45:28 +00:00
def summary ( commit , branch , pattern ) :
rcommit = commit
new: [cve] automatic extraction of CVE id from commit message
If one of more CVE id(s) are found in a commit message, those are added
in the finding output.
Example:
"8c6f86c7c5350fadf22d32d6cd4712e2ad4447ba": {
"message": "Fix an overflow bug in rsaz_512_sqr\n\nThere is an overflow bug in the x64_64 Montgomery squaring procedure used in\nexponentiation with 512-bit moduli. No EC algorithms are affected. Analysis\nsuggests that attacks against 2-prime RSA1024, 3-prime RSA1536, and DSA1024 as a\nresult of this defect would be very difficult to perform and are not believed\nlikely. Attacks against DH512 are considered just feasible. However, for an\nattack the target would have to re-use the DH512 private key, which is not\nrecommended anyway. Also applications directly using the low level API\nBN_mod_exp may be affected if they use BN_FLG_CONSTTIME.\n\nCVE-2019-1551\n\nReviewed-by: Paul Dale <paul.dale@oracle.com>\nReviewed-by: Bernd Edlinger <bernd.edlinger@hotmail.de>\n(Merged from https://github.com/openssl/openssl/pull/10574)\n",
"commit-id": "8c6f86c7c5350fadf22d32d6cd4712e2ad4447ba",
"summary": "Fix an overflow bug in rsaz_512_sqr",
"stats": {
"insertions": 197,
"deletions": 184,
"lines": 381,
"files": 1
},
"author": "Andy Polyakov",
"author-email": "appro@openssl.org",
"authored_date": 1575460101,
"committed_date": 1575635491,
"branches": [
"master"
],
"pattern-selected": "(?i)(denial of service |\bXXE\b|remote code execution|\bopen redirect|OSVDB|\bvuln|\bCVE\b |\bXSS\b|\bReDoS\b|\bNVD\b|malicious|x−frame−options|attack|cross site |exploit|malicious|directory traversal |\bRCE\b|\bdos\b|\bXSRF \b|\bXSS\b|clickjack|session.fixation|hijack|\badvisory|\binsecure |security |\bcross−origin\b|unauthori[z|s]ed |infinite loop)",
"pattern-matches": [
"attack"
],
"cve": [
"CVE-2019-1551"
],
"state": "cve-assigned"
}
The state is also updated to cve-assigned if one or more CVE are present
in the commit message.
2019-12-17 12:37:18 +00:00
cve = extract_cve ( rcommit . message )
2019-12-17 07:45:28 +00:00
if rcommit . hexsha in potential_vulnerabilities :
potential_vulnerabilities [ rcommit . hexsha ] [ ' branches ' ] . append ( branch )
else :
potential_vulnerabilities [ rcommit . hexsha ] = { }
potential_vulnerabilities [ rcommit . hexsha ] [ ' message ' ] = rcommit . message
potential_vulnerabilities [ rcommit . hexsha ] [ ' commit-id ' ] = rcommit . hexsha
potential_vulnerabilities [ rcommit . hexsha ] [ ' summary ' ] = rcommit . summary
potential_vulnerabilities [ rcommit . hexsha ] [ ' stats ' ] = rcommit . stats . total
potential_vulnerabilities [ rcommit . hexsha ] [ ' author ' ] = rcommit . author . name
potential_vulnerabilities [ rcommit . hexsha ] [ ' author-email ' ] = rcommit . author . email
potential_vulnerabilities [ rcommit . hexsha ] [ ' authored_date ' ] = rcommit . authored_date
potential_vulnerabilities [ rcommit . hexsha ] [ ' committed_date ' ] = rcommit . committed_date
potential_vulnerabilities [ rcommit . hexsha ] [ ' branches ' ] = [ ]
potential_vulnerabilities [ rcommit . hexsha ] [ ' branches ' ] . append ( branch )
potential_vulnerabilities [ rcommit . hexsha ] [ ' pattern-selected ' ] = pattern . pattern
potential_vulnerabilities [ rcommit . hexsha ] [ ' pattern-matches ' ] = ret [ ' match ' ]
new: [cve] automatic extraction of CVE id from commit message
If one of more CVE id(s) are found in a commit message, those are added
in the finding output.
Example:
"8c6f86c7c5350fadf22d32d6cd4712e2ad4447ba": {
"message": "Fix an overflow bug in rsaz_512_sqr\n\nThere is an overflow bug in the x64_64 Montgomery squaring procedure used in\nexponentiation with 512-bit moduli. No EC algorithms are affected. Analysis\nsuggests that attacks against 2-prime RSA1024, 3-prime RSA1536, and DSA1024 as a\nresult of this defect would be very difficult to perform and are not believed\nlikely. Attacks against DH512 are considered just feasible. However, for an\nattack the target would have to re-use the DH512 private key, which is not\nrecommended anyway. Also applications directly using the low level API\nBN_mod_exp may be affected if they use BN_FLG_CONSTTIME.\n\nCVE-2019-1551\n\nReviewed-by: Paul Dale <paul.dale@oracle.com>\nReviewed-by: Bernd Edlinger <bernd.edlinger@hotmail.de>\n(Merged from https://github.com/openssl/openssl/pull/10574)\n",
"commit-id": "8c6f86c7c5350fadf22d32d6cd4712e2ad4447ba",
"summary": "Fix an overflow bug in rsaz_512_sqr",
"stats": {
"insertions": 197,
"deletions": 184,
"lines": 381,
"files": 1
},
"author": "Andy Polyakov",
"author-email": "appro@openssl.org",
"authored_date": 1575460101,
"committed_date": 1575635491,
"branches": [
"master"
],
"pattern-selected": "(?i)(denial of service |\bXXE\b|remote code execution|\bopen redirect|OSVDB|\bvuln|\bCVE\b |\bXSS\b|\bReDoS\b|\bNVD\b|malicious|x−frame−options|attack|cross site |exploit|malicious|directory traversal |\bRCE\b|\bdos\b|\bXSRF \b|\bXSS\b|clickjack|session.fixation|hijack|\badvisory|\binsecure |security |\bcross−origin\b|unauthori[z|s]ed |infinite loop)",
"pattern-matches": [
"attack"
],
"cve": [
"CVE-2019-1551"
],
"state": "cve-assigned"
}
The state is also updated to cve-assigned if one or more CVE are present
in the commit message.
2019-12-17 12:37:18 +00:00
if cve : potential_vulnerabilities [ rcommit . hexsha ] [ ' cve ' ] = cve
if cve :
potential_vulnerabilities [ rcommit . hexsha ] [ ' state ' ] = " cve-assigned "
else :
potential_vulnerabilities [ rcommit . hexsha ] [ ' state ' ] = args . s
2019-12-17 07:45:28 +00:00
return rcommit . hexsha
2019-11-15 06:39:19 +00:00
new: [cve] automatic extraction of CVE id from commit message
If one of more CVE id(s) are found in a commit message, those are added
in the finding output.
Example:
"8c6f86c7c5350fadf22d32d6cd4712e2ad4447ba": {
"message": "Fix an overflow bug in rsaz_512_sqr\n\nThere is an overflow bug in the x64_64 Montgomery squaring procedure used in\nexponentiation with 512-bit moduli. No EC algorithms are affected. Analysis\nsuggests that attacks against 2-prime RSA1024, 3-prime RSA1536, and DSA1024 as a\nresult of this defect would be very difficult to perform and are not believed\nlikely. Attacks against DH512 are considered just feasible. However, for an\nattack the target would have to re-use the DH512 private key, which is not\nrecommended anyway. Also applications directly using the low level API\nBN_mod_exp may be affected if they use BN_FLG_CONSTTIME.\n\nCVE-2019-1551\n\nReviewed-by: Paul Dale <paul.dale@oracle.com>\nReviewed-by: Bernd Edlinger <bernd.edlinger@hotmail.de>\n(Merged from https://github.com/openssl/openssl/pull/10574)\n",
"commit-id": "8c6f86c7c5350fadf22d32d6cd4712e2ad4447ba",
"summary": "Fix an overflow bug in rsaz_512_sqr",
"stats": {
"insertions": 197,
"deletions": 184,
"lines": 381,
"files": 1
},
"author": "Andy Polyakov",
"author-email": "appro@openssl.org",
"authored_date": 1575460101,
"committed_date": 1575635491,
"branches": [
"master"
],
"pattern-selected": "(?i)(denial of service |\bXXE\b|remote code execution|\bopen redirect|OSVDB|\bvuln|\bCVE\b |\bXSS\b|\bReDoS\b|\bNVD\b|malicious|x−frame−options|attack|cross site |exploit|malicious|directory traversal |\bRCE\b|\bdos\b|\bXSRF \b|\bXSS\b|clickjack|session.fixation|hijack|\badvisory|\binsecure |security |\bcross−origin\b|unauthori[z|s]ed |infinite loop)",
"pattern-matches": [
"attack"
],
"cve": [
"CVE-2019-1551"
],
"state": "cve-assigned"
}
The state is also updated to cve-assigned if one or more CVE are present
in the commit message.
2019-12-17 12:37:18 +00:00
def extract_cve ( commit ) :
cve_find = re . compile ( r ' CVE-[1-2] \ d { 1,4}- \ d { 1,7} ' , re . IGNORECASE )
m = cve_find . findall ( commit )
if m :
return m
else :
return None
2019-11-03 14:26:43 +00:00
repo_heads = repo . heads
repo_heads_names = [ h . name for h in repo_heads ]
print ( repo_heads_names , file = sys . stderr )
for branch in repo_heads_names :
commits = list ( repo . iter_commits ( branch ) )
2019-12-17 07:45:28 +00:00
defaultpattern
2019-11-03 14:26:43 +00:00
for commit in commits :
2019-12-17 07:45:28 +00:00
if isinstance ( defaultpattern , typing . Pattern ) :
ret = find_vuln ( commit , pattern = defaultpattern )
if ret :
#print("Vulnerability found: {}".format(ret))
#print(ret.hexsha)
rcommit = ret [ ' commit ' ]
summary ( rcommit , branch , defaultpattern )
# Deduplication of commits on different branches
2019-11-03 14:26:43 +00:00
found + = 1
2019-12-17 07:45:28 +00:00
elif isinstance ( defaultpattern , list ) :
for p in defaultpattern :
ret = find_vuln ( commit , pattern = p )
if ret :
rcommit = ret [ ' commit ' ]
summary ( rcommit , branch , p )
found + = 1
2019-11-03 14:26:43 +00:00
print ( json . dumps ( potential_vulnerabilities ) )
2019-12-17 07:45:28 +00:00
2019-11-03 14:26:43 +00:00
print ( " Total potential vulnerability found in {} commit(s) " . format ( found ) , file = sys . stderr )