pyExploitDb 0.2.51__tar.gz → 0.2.54__tar.gz

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.
@@ -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
@@ -26,7 +26,7 @@ This is the new home of "pyExploidDb".
26
26
 
27
27
  pyExploitDb (https://shanewilliamscott.com)
28
28
  ==
29
-
29
+ [![Python package](https://github.com/Hackman238/pyExploitDb/actions/workflows/master.yml/badge.svg)](https://github.com/Hackman238/pyExploitDb/actions/workflows/master.yml)
30
30
  [![Known Vulnerabilities](https://snyk.io/test/github/Hackman238/pyExploitDb/badge.svg?targetFile=requirements.txt)](https://snyk.io/test/github/Hackman238/pyExploitDb?targetFile=requirements.txt)
31
31
  [![Maintainability](https://api.codeclimate.com/v1/badges/a11151ec3314f93a777f/maintainability)](https://codeclimate.com/github/Hackman238/pyExploitDb/maintainability)
32
32
 
@@ -6,7 +6,7 @@ This is the new home of "pyExploidDb".
6
6
 
7
7
  pyExploitDb (https://shanewilliamscott.com)
8
8
  ==
9
-
9
+ [![Python package](https://github.com/Hackman238/pyExploitDb/actions/workflows/master.yml/badge.svg)](https://github.com/Hackman238/pyExploitDb/actions/workflows/master.yml)
10
10
  [![Known Vulnerabilities](https://snyk.io/test/github/Hackman238/pyExploitDb/badge.svg?targetFile=requirements.txt)](https://snyk.io/test/github/Hackman238/pyExploitDb?targetFile=requirements.txt)
11
11
  [![Maintainability](https://api.codeclimate.com/v1/badges/a11151ec3314f93a777f/maintainability)](https://codeclimate.com/github/Hackman238/pyExploitDb/maintainability)
12
12
 
@@ -0,0 +1,153 @@
1
+ import os
2
+ import json
3
+ import csv
4
+ import requests
5
+ import time
6
+ import git
7
+ import re
8
+
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
+
13
+ def __init__(self):
14
+ self.cveToExploitMap = {}
15
+ self.currentPath = os.path.dirname(os.path.abspath(__file__))
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")
19
+ self.requestCoolOffTime = 1
20
+ self.debug = False
21
+
22
+ def logDebug(self, message):
23
+ if self.debug:
24
+ print(message)
25
+
26
+ def cloneOrUpdateRepo(self):
27
+ if not os.path.isdir(self.exploitDbPath):
28
+ self.logDebug("Cloning exploit-database repository")
29
+ git.Repo.clone_from(self.EXPLOIT_DB_REPO, self.exploitDbPath)
30
+ else:
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()
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)
50
+
51
+ def getCveDetails(self, cveSearch):
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 {}
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
81
+
82
+ def searchCve(self, cveSearch):
83
+ if not cveSearch:
84
+ return []
85
+ cveSearch = cveSearch.upper()
86
+ self.logDebug(f"Searching for CVE: {cveSearch}")
87
+ if cveSearch in self.cveToExploitMap:
88
+ return self.getCveDetails(cveSearch)
89
+ return []
90
+
91
+ def updateDb(self):
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:
107
+ try:
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)
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)
144
+
145
+ def test():
146
+ pEdb = PyExploitDb()
147
+ pEdb.debug = False
148
+ pEdb.openFile()
149
+ results = pEdb.searchCve("CVE-2018-14592")
150
+ print('PASS' if results else 'FAIL')
151
+
152
+ if __name__ == "__main__":
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
@@ -26,7 +26,7 @@ This is the new home of "pyExploidDb".
26
26
 
27
27
  pyExploitDb (https://shanewilliamscott.com)
28
28
  ==
29
-
29
+ [![Python package](https://github.com/Hackman238/pyExploitDb/actions/workflows/master.yml/badge.svg)](https://github.com/Hackman238/pyExploitDb/actions/workflows/master.yml)
30
30
  [![Known Vulnerabilities](https://snyk.io/test/github/Hackman238/pyExploitDb/badge.svg?targetFile=requirements.txt)](https://snyk.io/test/github/Hackman238/pyExploitDb?targetFile=requirements.txt)
31
31
  [![Maintainability](https://api.codeclimate.com/v1/badges/a11151ec3314f93a777f/maintainability)](https://codeclimate.com/github/Hackman238/pyExploitDb/maintainability)
32
32
 
@@ -5,10 +5,12 @@ with open("README.md", "r") as fh:
5
5
 
6
6
  setuptools.setup(
7
7
  name="pyExploitDb",
8
- version="0.2.51",
8
+ version="0.2.54",
9
9
  author="Shane William Scott",
10
10
  author_email="gs@shanewilliamscott.com",
11
- description="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.",
11
+ description="""An optimized Python3 library to fetch the most recent exploit-database,
12
+ create searchable indexes for CVE->EDBID and EDBID -> CVE, and provide
13
+ methods to perform searches.""",
12
14
  long_description=long_description,
13
15
  long_description_content_type="text/markdown",
14
16
  url="https://github.com/Hackman238/pyExploitDb",
@@ -1,201 +0,0 @@
1
- import os
2
- import json
3
- import csv
4
- import requests
5
- import time
6
- import sys
7
- import git
8
-
9
- class PyExploitDb:
10
- def __init__(self):
11
- self.cveToExploitMap = {}
12
- 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.requestCoolOffTime = 1
17
- self.debug = False
18
- self.autoUpdate = True
19
- pass
20
-
21
-
22
- def openFile(self, exploitMap = "cveToEdbid.json", encoding="utf-8"):
23
- 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
- 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)
47
-
48
-
49
- 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
95
-
96
-
97
- def searchCve(self, cveSearch):
98
- if not cveSearch:
99
- return []
100
- cveSearch = cveSearch.upper()
101
- print(cveSearch)
102
- 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
110
- return []
111
-
112
-
113
- 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:
120
- 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)
185
-
186
-
187
- def test():
188
- pEdb = PyExploitDb()
189
- pEdb.debug = False
190
- pEdb.openFile()
191
- 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
-
199
-
200
- if __name__ == "__main__":
201
- test()
File without changes
File without changes