pyExploitDb 0.2.51__py3-none-any.whl → 0.2.54__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 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 + "/edbidToCve.json"
14
- self.cveToEdbidFile = self.currentPath + "/cveToEdbid.json"
15
- self.exploitDbPath = self.currentPath + "/exploit-database"
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 openFile(self, exploitMap = "cveToEdbid.json", encoding="utf-8"):
26
+ def cloneOrUpdateRepo(self):
23
27
  if not os.path.isdir(self.exploitDbPath):
24
- print("Cloning exploit-database repository")
25
- git.Repo.clone_from("https://gitlab.com/exploit-database/exploitdb.git", self.exploitDbPath)
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
- if self.autoUpdate == True:
30
- try:
31
- print("Pulling exploit-database updates...")
32
- git.Git(self.exploitDbPath).pull('origin', 'main')
33
- except git.exc.GitCommandError as e:
34
- print("Broken or obsoleted exploit-database clone found. Deleting and re-cloning...")
35
- print("Deleting " + self.currentPath + "/exploit-database/...")
36
- os.system("rm -Rf " + self.currentPath + "/exploit-database/")
37
- print("Cloning exploit-database repository")
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
- files = open(self.currentPath + "/exploit-database/files_exploits.csv", encoding="utf-8")
51
- reader = csv.reader(files)
52
- next(reader)
53
- result = {}
54
- found = False
55
- for row in reader:
56
- id, file, description, date, author, type, platform, port, _, date_updated, verified, codes, tags, aliases, _, app_url, src_url = tuple(row)
57
- if id in self.cveToExploitMap[cveSearch]:
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
- print(cveSearch)
86
+ self.logDebug(f"Searching for CVE: {cveSearch}")
102
87
  if cveSearch in self.cveToExploitMap:
103
- if self.debug == True:
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
- if not os.path.exists(self.edbidToCveFile):
116
- os.system("touch {0}".format(self.edbidToCveFile))
117
- data = {}
118
- else:
119
- with open(self.edbidToCveFile, encoding="utf-8") as fileData:
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
- data = json.load(fileData)
122
- except:
123
- print("Possibly corrupt or empty: {0}".format(self.edbidToCveFile))
124
- os.system("rm -f {0}".format(self.edbidToCveFile))
125
- os.system("touch {0}".format(self.edbidToCveFile))
126
- data = {}
127
- files = open(self.exploitDbPath + "/files_exploits.csv", encoding="utf-8")
128
- reader = csv.reader(files)
129
- next(reader)
130
- reader = list(reader)
131
- edbCount = len(reader)
132
- headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'}
133
- def locations_of_substring(string, substring):
134
- import re
135
- results = [m.start() for m in re.finditer(substring, string)]
136
- return results
137
- print("Refreshing EDBID-CVE mapping. This may take a long time.")
138
- for i in range(edbCount):
139
- percentDone = (i / edbCount) * 100
140
- if self.debug == True:
141
- print("Processing...{0}%".format(str(percentDone)))
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.51
4
- Summary: An optimized Python3 library to fetch the most recent exploit-database, create searchable indexes for CVE->EDBID and EDBID -> CVE, and provide methods to perform searches.
3
+ Version: 0.2.54
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
+ [![Python package](https://github.com/Hackman238/pyExploitDb/actions/workflows/master.yml/badge.svg)](https://github.com/Hackman238/pyExploitDb/actions/workflows/master.yml)
32
32
  [![Known Vulnerabilities](https://snyk.io/test/github/Hackman238/pyExploitDb/badge.svg?targetFile=requirements.txt)](https://snyk.io/test/github/Hackman238/pyExploitDb?targetFile=requirements.txt)
33
33
  [![Maintainability](https://api.codeclimate.com/v1/badges/a11151ec3314f93a777f/maintainability)](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.54.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
5
+ pyExploitDb-0.2.54.dist-info/METADATA,sha256=W8tKacIw7Z14K2V6ScZtfd0iYOL-qgOBr22ucaVM2Ew,2693
6
+ pyExploitDb-0.2.54.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
7
+ pyExploitDb-0.2.54.dist-info/top_level.txt,sha256=9RS0bXZhz9Wz4-FytP-Cs8qpdAuVzWqmHQRnjYtuOwk,12
8
+ pyExploitDb-0.2.54.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,,