pyExploitDb 0.2.51__py3-none-any.whl → 0.2.53__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyExploitDb/__init__.py +112 -160
- {pyExploitDb-0.2.51.dist-info → pyExploitDb-0.2.53.dist-info}/METADATA +3 -3
- pyExploitDb-0.2.53.dist-info/RECORD +8 -0
- pyExploitDb-0.2.51.dist-info/RECORD +0 -8
- {pyExploitDb-0.2.51.dist-info → pyExploitDb-0.2.53.dist-info}/LICENSE +0 -0
- {pyExploitDb-0.2.51.dist-info → pyExploitDb-0.2.53.dist-info}/WHEEL +0 -0
- {pyExploitDb-0.2.51.dist-info → pyExploitDb-0.2.53.dist-info}/top_level.txt +0 -0
pyExploitDb/__init__.py
CHANGED
@@ -3,199 +3,151 @@ import json
|
|
3
3
|
import csv
|
4
4
|
import requests
|
5
5
|
import time
|
6
|
-
import sys
|
7
6
|
import git
|
7
|
+
import re
|
8
8
|
|
9
9
|
class PyExploitDb:
|
10
|
+
EXPLOIT_DB_REPO = "https://gitlab.com/exploit-database/exploitdb.git"
|
11
|
+
USER_AGENT = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) Chrome/39.0 Safari/537.36'}
|
12
|
+
|
10
13
|
def __init__(self):
|
11
14
|
self.cveToExploitMap = {}
|
12
15
|
self.currentPath = os.path.dirname(os.path.abspath(__file__))
|
13
|
-
self.edbidToCveFile = self.currentPath
|
14
|
-
self.cveToEdbidFile = self.currentPath
|
15
|
-
self.exploitDbPath = self.currentPath
|
16
|
+
self.edbidToCveFile = os.path.join(self.currentPath, "edbidToCve.json")
|
17
|
+
self.cveToEdbidFile = os.path.join(self.currentPath, "cveToEdbid.json")
|
18
|
+
self.exploitDbPath = os.path.join(self.currentPath, "exploit-database")
|
16
19
|
self.requestCoolOffTime = 1
|
17
20
|
self.debug = False
|
18
|
-
self.autoUpdate = True
|
19
|
-
pass
|
20
21
|
|
22
|
+
def logDebug(self, message):
|
23
|
+
if self.debug:
|
24
|
+
print(message)
|
21
25
|
|
22
|
-
def
|
26
|
+
def cloneOrUpdateRepo(self):
|
23
27
|
if not os.path.isdir(self.exploitDbPath):
|
24
|
-
|
25
|
-
git.Repo.clone_from(
|
26
|
-
print("Updating db...")
|
27
|
-
self.updateDb()
|
28
|
+
self.logDebug("Cloning exploit-database repository")
|
29
|
+
git.Repo.clone_from(self.EXPLOIT_DB_REPO, self.exploitDbPath)
|
28
30
|
else:
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
git.Repo.clone_from("https://gitlab.com/exploit-database/exploitdb.git", self.exploitDbPath)
|
39
|
-
print("Updating db...")
|
40
|
-
self.updateDb()
|
41
|
-
print("Loading database...")
|
42
|
-
with open(self.currentPath + "/" + exploitMap, encoding="utf-8") as fileData:
|
43
|
-
cveToExploitMap = json.load(fileData)
|
44
|
-
self.cveToExploitMap = cveToExploitMap
|
45
|
-
if self.debug == True:
|
46
|
-
print(self.cveToExploitMap)
|
31
|
+
self.pullLatestUpdates()
|
32
|
+
|
33
|
+
def pullLatestUpdates(self):
|
34
|
+
try:
|
35
|
+
self.logDebug("Pulling exploit-database updates...")
|
36
|
+
git.Git(self.exploitDbPath).pull('origin', 'main')
|
37
|
+
except git.exc.GitCommandError:
|
38
|
+
self.logDebug("Repo broken, re-cloning...")
|
39
|
+
self.deleteAndRecloneRepo()
|
47
40
|
|
41
|
+
def deleteAndRecloneRepo(self):
|
42
|
+
os.rmdir(self.exploitDbPath)
|
43
|
+
git.Repo.clone_from(self.EXPLOIT_DB_REPO, self.exploitDbPath)
|
44
|
+
|
45
|
+
def openFile(self, exploitMap="cveToEdbid.json", encoding="utf-8"):
|
46
|
+
self.cloneOrUpdateRepo()
|
47
|
+
with open(os.path.join(self.currentPath, exploitMap), encoding=encoding) as fileData:
|
48
|
+
self.cveToExploitMap = json.load(fileData)
|
49
|
+
self.logDebug(self.cveToExploitMap)
|
48
50
|
|
49
51
|
def getCveDetails(self, cveSearch):
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
found = True
|
59
|
-
result['id'] = id
|
60
|
-
result['file'] = file
|
61
|
-
result['description'] = description
|
62
|
-
result['date'] = date
|
63
|
-
result['author'] = author
|
64
|
-
result['type'] = type
|
65
|
-
result['platform'] = platform
|
66
|
-
result['port'] = port
|
67
|
-
result['date_updated'] = date_updated
|
68
|
-
result['verified'] = verified
|
69
|
-
result['codes'] = codes
|
70
|
-
result['tags'] = tags
|
71
|
-
result['aliases'] = aliases
|
72
|
-
result['app_url'] = app_url
|
73
|
-
result['src_url'] = src_url
|
74
|
-
|
75
|
-
if self.debug == True:
|
76
|
-
print("Exploit DB Id: {0}".format(id))
|
77
|
-
print("File: {0}".format(self.exploitDbPath + "/" + file))
|
78
|
-
print("Date: {0}".format(date))
|
79
|
-
print("Author: {0}".format(author))
|
80
|
-
print("Platform: {0}".format(platform))
|
81
|
-
print("Type: {0}".format(type))
|
82
|
-
print("Description: {0}".format(description))
|
83
|
-
print("App URL: {0}".format(app_url))
|
84
|
-
print("Source URL: {0}".format(src_url))
|
85
|
-
|
86
|
-
if port != "0":
|
87
|
-
result['port'] = port
|
88
|
-
if self.debug == True:
|
89
|
-
print("Port: {0}".format(port))
|
90
|
-
if not found:
|
91
|
-
if self.debug == True:
|
92
|
-
print("ERROR - No EDB Id found")
|
93
|
-
files.close()
|
94
|
-
return result
|
52
|
+
with open(os.path.join(self.exploitDbPath, "files_exploits.csv"), encoding="utf-8") as file:
|
53
|
+
reader = csv.reader(file)
|
54
|
+
next(reader)
|
55
|
+
for row in reader:
|
56
|
+
if row[0] in self.cveToExploitMap.get(cveSearch, []):
|
57
|
+
return self.extractCveDetails(row)
|
58
|
+
self.logDebug("ERROR - No EDB Id found")
|
59
|
+
return {}
|
95
60
|
|
61
|
+
def extractCveDetails(self, row):
|
62
|
+
details = {
|
63
|
+
'id': row[0],
|
64
|
+
'file': row[1],
|
65
|
+
'description': row[2],
|
66
|
+
'date': row[3],
|
67
|
+
'author': row[4],
|
68
|
+
'type': row[5],
|
69
|
+
'platform': row[6],
|
70
|
+
'port': row[7],
|
71
|
+
'date_updated': row[9],
|
72
|
+
'verified': row[10],
|
73
|
+
'codes': row[11],
|
74
|
+
'tags': row[12],
|
75
|
+
'aliases': row[13],
|
76
|
+
'app_url': row[14],
|
77
|
+
'src_url': row[15],
|
78
|
+
}
|
79
|
+
self.logDebug(f"CVE Details: {details}")
|
80
|
+
return details
|
96
81
|
|
97
82
|
def searchCve(self, cveSearch):
|
98
83
|
if not cveSearch:
|
99
84
|
return []
|
100
85
|
cveSearch = cveSearch.upper()
|
101
|
-
|
86
|
+
self.logDebug(f"Searching for CVE: {cveSearch}")
|
102
87
|
if cveSearch in self.cveToExploitMap:
|
103
|
-
|
104
|
-
print("Found")
|
105
|
-
cveData = self.getCveDetails(cveSearch)
|
106
|
-
if cveData:
|
107
|
-
return cveData
|
108
|
-
else:
|
109
|
-
return cveSearch
|
88
|
+
return self.getCveDetails(cveSearch)
|
110
89
|
return []
|
111
90
|
|
112
|
-
|
113
91
|
def updateDb(self):
|
114
|
-
data =
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
92
|
+
data = self.loadExistingData(self.edbidToCveFile)
|
93
|
+
exploits = self.loadExploitCsv()
|
94
|
+
|
95
|
+
for i, row in enumerate(exploits):
|
96
|
+
edb_id = row[0]
|
97
|
+
if edb_id not in data:
|
98
|
+
data[edb_id] = self.fetchCvesForExploit(edb_id)
|
99
|
+
|
100
|
+
self.writeJson(self.edbidToCveFile, data)
|
101
|
+
self.createCveToExploitMap(data)
|
102
|
+
self.writeJson(self.cveToEdbidFile, self.cveToExploitMap)
|
103
|
+
|
104
|
+
def loadExistingData(self, file_path):
|
105
|
+
if os.path.exists(file_path):
|
106
|
+
with open(file_path, encoding="utf-8") as fileData:
|
120
107
|
try:
|
121
|
-
|
122
|
-
except:
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
edb = tuple(reader[i])[0]
|
143
|
-
if edb in data:
|
144
|
-
if self.debug == True:
|
145
|
-
print("Skipping {0}".format(str(edb)))
|
146
|
-
pass
|
147
|
-
else:
|
148
|
-
content = ""
|
149
|
-
while True:
|
150
|
-
try:
|
151
|
-
requestUri = "https://www.exploit-db.com/exploits/{0}".format(str(edb))
|
152
|
-
if self.debug == True:
|
153
|
-
print("Requesting {0}".format(requestUri))
|
154
|
-
r = requests.get(requestUri, headers = headers, timeout=10)
|
155
|
-
content = r.content.decode("ISO-8859-1")
|
156
|
-
except Exception as e:
|
157
|
-
if self.debug == True:
|
158
|
-
print("Error {0}".format(e))
|
159
|
-
time.sleep(self.requestCoolOffTime)
|
160
|
-
continue
|
161
|
-
finally:
|
162
|
-
break
|
163
|
-
indexes = locations_of_substring(content, 'https://nvd.nist.gov/vuln/detail/CVE-')
|
164
|
-
used = []
|
165
|
-
for pos in indexes:
|
166
|
-
cve = r.content[pos + 33: pos + 33 + 14]
|
167
|
-
if type(cve) == type(bytes()):
|
168
|
-
cve = cve.decode("ISO-8859-1")
|
169
|
-
cve = cve.replace('\"', '')
|
170
|
-
cve = cve.replace('\r', '')
|
171
|
-
cve = cve.replace('\n', '')
|
172
|
-
if cve in used:
|
173
|
-
continue
|
174
|
-
used.append(cve)
|
175
|
-
data[edb] = used
|
176
|
-
with open(self.edbidToCveFile, "w", encoding="utf-8") as fileData:
|
177
|
-
json.dump(data, fileData, indent = 2)
|
178
|
-
self.cveToExploitMap = {}
|
179
|
-
for k, v in data.items():
|
180
|
-
for e in v:
|
181
|
-
self.cveToExploitMap[e] = self.cveToExploitMap.get(e, [])
|
182
|
-
self.cveToExploitMap[e].append(k)
|
183
|
-
with open(self.cveToEdbidFile, "w", encoding="utf-8") as fileData:
|
184
|
-
json.dump(self.cveToExploitMap, fileData, indent = 2)
|
108
|
+
return json.load(fileData)
|
109
|
+
except json.JSONDecodeError:
|
110
|
+
self.logDebug(f"Corrupt file detected at {file_path}, recreating...")
|
111
|
+
return {}
|
112
|
+
|
113
|
+
def loadExploitCsv(self):
|
114
|
+
with open(os.path.join(self.exploitDbPath, "files_exploits.csv"), encoding="utf-8") as file:
|
115
|
+
reader = csv.reader(file)
|
116
|
+
next(reader)
|
117
|
+
return list(reader)
|
118
|
+
|
119
|
+
def fetchCvesForExploit(self, edb_id):
|
120
|
+
requestUri = f"https://www.exploit-db.com/exploits/{edb_id}"
|
121
|
+
self.logDebug(f"Requesting {requestUri}")
|
122
|
+
while True:
|
123
|
+
try:
|
124
|
+
response = requests.get(requestUri, headers=self.USER_AGENT, timeout=10)
|
125
|
+
return self.parseCvesFromContent(response.content)
|
126
|
+
except requests.RequestException as e:
|
127
|
+
self.logDebug(f"Request error: {e}, retrying after cool-off")
|
128
|
+
time.sleep(self.requestCoolOffTime)
|
185
129
|
|
130
|
+
def parseCvesFromContent(self, content):
|
131
|
+
indexes = [m.start() for m in re.finditer('https://nvd.nist.gov/vuln/detail/CVE-', content)]
|
132
|
+
return {content[pos + 33: pos + 47].decode("ISO-8859-1").strip() for pos in indexes}
|
133
|
+
|
134
|
+
def writeJson(self, file_path, data):
|
135
|
+
with open(file_path, "w", encoding="utf-8") as fileData:
|
136
|
+
json.dump(data, fileData, indent=2)
|
137
|
+
|
138
|
+
def createCveToExploitMap(self, data):
|
139
|
+
for edb_id, cves in data.items():
|
140
|
+
for cve in cves:
|
141
|
+
if cve not in self.cveToExploitMap:
|
142
|
+
self.cveToExploitMap[cve] = []
|
143
|
+
self.cveToExploitMap[cve].append(edb_id)
|
186
144
|
|
187
145
|
def test():
|
188
146
|
pEdb = PyExploitDb()
|
189
147
|
pEdb.debug = False
|
190
148
|
pEdb.openFile()
|
191
149
|
results = pEdb.searchCve("CVE-2018-14592")
|
192
|
-
if results
|
193
|
-
print(results)
|
194
|
-
print('PASS')
|
195
|
-
else:
|
196
|
-
print('FAIL')
|
197
|
-
sys.exit(1)
|
198
|
-
|
150
|
+
print('PASS' if results else 'FAIL')
|
199
151
|
|
200
152
|
if __name__ == "__main__":
|
201
153
|
test()
|
@@ -1,7 +1,7 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: pyExploitDb
|
3
|
-
Version: 0.2.
|
4
|
-
Summary: An optimized Python3 library to fetch the most recent exploit-database,
|
3
|
+
Version: 0.2.53
|
4
|
+
Summary: An optimized Python3 library to fetch the most recent exploit-database,
|
5
5
|
Home-page: https://github.com/Hackman238/pyExploitDb
|
6
6
|
Author: Shane William Scott
|
7
7
|
Author-email: gs@shanewilliamscott.com
|
@@ -28,7 +28,7 @@ This is the new home of "pyExploidDb".
|
|
28
28
|
|
29
29
|
pyExploitDb (https://shanewilliamscott.com)
|
30
30
|
==
|
31
|
-
|
31
|
+
[](https://github.com/Hackman238/pyExploitDb/actions/workflows/master.yml)
|
32
32
|
[](https://snyk.io/test/github/Hackman238/pyExploitDb?targetFile=requirements.txt)
|
33
33
|
[](https://codeclimate.com/github/Hackman238/pyExploitDb/maintainability)
|
34
34
|
|
@@ -0,0 +1,8 @@
|
|
1
|
+
pyExploitDb/__init__.py,sha256=gbunzcwgZRZuJMGgafULAAWsUsyYZLQ0qhdfrcYo8fE,5629
|
2
|
+
pyExploitDb/cveToEdbid.json,sha256=RzcfsMC1vfN0ieZbFN0hDD4wnRCsF1Bc3G42lp6rPXA,984560
|
3
|
+
pyExploitDb/edbidToCve.json,sha256=WaI6yPMbSLG3qjcObz4s-O3BSQqTwalPEUkVIHReaeg,1358145
|
4
|
+
pyExploitDb-0.2.53.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
5
|
+
pyExploitDb-0.2.53.dist-info/METADATA,sha256=kU1Y7VNp2sx0kJOkETdHkQktK7GiX0HTMl0D1hnxmvI,2693
|
6
|
+
pyExploitDb-0.2.53.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
|
7
|
+
pyExploitDb-0.2.53.dist-info/top_level.txt,sha256=9RS0bXZhz9Wz4-FytP-Cs8qpdAuVzWqmHQRnjYtuOwk,12
|
8
|
+
pyExploitDb-0.2.53.dist-info/RECORD,,
|
@@ -1,8 +0,0 @@
|
|
1
|
-
pyExploitDb/__init__.py,sha256=dBPIBtm3EWgqm0JuTnxeYrLmqN8Uj5cRZMWsiCJDOGQ,8260
|
2
|
-
pyExploitDb/cveToEdbid.json,sha256=RzcfsMC1vfN0ieZbFN0hDD4wnRCsF1Bc3G42lp6rPXA,984560
|
3
|
-
pyExploitDb/edbidToCve.json,sha256=WaI6yPMbSLG3qjcObz4s-O3BSQqTwalPEUkVIHReaeg,1358145
|
4
|
-
pyExploitDb-0.2.51.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
5
|
-
pyExploitDb-0.2.51.dist-info/METADATA,sha256=6IWsLKujlZ1K356GKXpXI0XJsxylG-VxDLOM16XPAGs,2620
|
6
|
-
pyExploitDb-0.2.51.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
|
7
|
-
pyExploitDb-0.2.51.dist-info/top_level.txt,sha256=9RS0bXZhz9Wz4-FytP-Cs8qpdAuVzWqmHQRnjYtuOwk,12
|
8
|
-
pyExploitDb-0.2.51.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|