Commit 69d16bc8 authored by Birger Schacht's avatar Birger Schacht

Initial commit of POC

parents
# patchfetch.py
A small proof of concept that iterates over a list of CVEs (it expects the format that [the list of the security-tracker-team has](https://salsa.debian.org/security-tracker-team/security-tracker/blob/master/data/CVE/list).
For every CVE the script checks the URLs in the notes and if the URLs contain patches the script downloads the patches to a temporary directory.
It uses `python3-unidiff` to detect if data is a patch.
#!/usr/bin/env python3
import sys
import re
import whatthepatch
import urllib.request
import tempfile
import unidiff
def main():
tempdirname = tempfile.mkdtemp(prefix="gsoc19")
print("Created temporary directory {}".format(tempdirname))
urls = set()
# open the file with the list of CVEs
with open(sys.argv[1], 'r') as f:
for line in f:
# store the CVE number in a variable
if line.startswith('CVE'):
if urls:
checkurls(cve, urls, tempdirname)
urls.clear()
cve = line[:13]
else:
# find URLs and add them to a temporary set
for url in findurls(line):
urls.add(fixurl(url))
def checkurls(cve, urls, tempdirname):
for pos, url in enumerate(list(urls)):
try:
# connect to every URL and fetch the data
with urllib.request.urlopen(url) as f:
data = f.read().decode()
# check if the fetched data contains a patch
# if so, write it to the temporary directory
if (ispatch(data)):
print("{} contains a patch".format(url))
filename = "{}/{}-{}.patch".format(tempdirname, cve, pos)
print("Writing patch to {}".format(filename))
with open(filename, 'w') as out:
out.write(data)
except urllib.error.URLError as e:
print("Could not connect to {}: {}".format(url, e))
# find one or more URLs in a string
# from https://www.geeksforgeeks.org/python-check-url-string/
def findurls(string):
url = re.findall('http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]||[!*\(\), ]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', string)
return url
# check for known patterns and replace the with the
# accoriding URL to the patch
def fixurl(string):
try:
response = urllib.request.urlopen(string)
string = response.geturl()
except urllib.error.URLError as e:
print("Could not connect to {}: {}".format(string, e))
pattern = re.compile("https://github.com/.+/commit/.+")
if pattern.search(string):
return "{}.patch".format(string)
pattern = re.compile("https://git.kernel.org/.+/commit/.+")
if pattern.search(string):
return string.replace("commit/?id=", "patch/?id=")
return string
# check if some data is indeed a patch
def ispatch(data):
if data.lstrip().startswith("<"):
return 0
patch = unidiff.PatchSet.from_string(data)
return len(patch)
# check if some data is indeed a patch
# this is using whatthepatch
#def ispatch(data):
# diff = []
# try:
# diff = [x for x in whatthepatch.parse_patch(data)]
# except Exception:
# # this occurs for example with binary data
# pass
# return (len(diff) > 0)
if __name__ == "__main__":
if len(sys.argv) is not 2:
print("Usage ./fetchpatch.py list")
exit(1)
main()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment