Skip to content

Commit 725bd5c

Browse files
committed
UPDATED: CVE-MITRE Source code updated
0 parents  commit 725bd5c

10 files changed

+1971
-0
lines changed

.gitignore

+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
# Intelij
2+
.idea/
3+
*.txt
4+
5+
# MAC OS X
6+
.DS_Store
7+
8+
# temp file
9+
*.html
10+
*.dump
11+
*.json
12+
*.xml
13+
*.csv
14+
*.zip
15+
*.sql
16+
17+
# Visual stduio code
18+
.vscode/
19+
20+
# Byte-compiled / optimized / DLL files
21+
__pycache__/
22+
*.py[cod]
23+
*$py.class
24+
25+
# C extensions
26+
*.so
27+
28+
# Distribution / packaging
29+
.Python
30+
build/
31+
develop-eggs/
32+
dist/
33+
downloads/
34+
eggs/
35+
.eggs/
36+
lib/
37+
lib64/
38+
parts/
39+
sdist/
40+
var/
41+
wheels/
42+
*.egg-info/
43+
.installed.cfg
44+
*.egg
45+
MANIFEST
46+
47+
# PyInstaller
48+
# Usually these files are written by a python script from a template
49+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
50+
*.manifest
51+
*.spec
52+
53+
# Installer logs
54+
pip-log.txt
55+
pip-delete-this-directory.txt
56+
57+
# Unit test / coverage reports
58+
htmlcov/
59+
.tox/
60+
.coverage
61+
.coverage.*
62+
.cache
63+
nosetests.xml
64+
coverage.xml
65+
*.cover
66+
.hypothesis/
67+
.pytest_cache/
68+
69+
# Translations
70+
*.mo
71+
*.pot
72+
73+
# Django stuff:
74+
*.log
75+
local_settings.py
76+
db.sqlite3
77+
78+
# Flask stuff:
79+
instance/
80+
.webassets-cache
81+
82+
# Scrapy stuff:
83+
.scrapy
84+
85+
# Sphinx documentation
86+
docs/_build/
87+
88+
# PyBuilder
89+
target/
90+
91+
# Jupyter Notebook
92+
.ipynb_checkpoints
93+
94+
# pyenv
95+
.python-version
96+
97+
# celery beat schedule file
98+
celerybeat-schedule
99+
100+
# SageMath parsed files
101+
*.sage.py
102+
103+
# Environments
104+
.env
105+
.venv
106+
env/
107+
venv/
108+
ENV/
109+
env.bak/
110+
venv.bak/
111+
112+
# Spyder project settings
113+
.spyderproject
114+
.spyproject
115+
116+
# Rope project settings
117+
.ropeproject
118+
119+
# mkdocs documentation
120+
/site
121+
122+
# mypy
123+
.mypy_cache/

README.md

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# cve-mysql-python
2+
CVE 데이터베이스 구축을 위한 프로그램입니다. MySQL 기반으로 작동합니다.
3+
4+
# Function
5+
해당 통합 플랫폼은 NVD-NIST, CVE-MITRE, ICS-CERT로부터 CVE 리스트들을 읽어들여 데이터베이스로 구축하여 필요한 데이터만을 로드하고 추출하는 데 도움을 줄 수 있습니다.
6+
이것은 다음과 같은 기능을 포함하고 있습니다.
7+
8+
- SQL Database, CSV 파일 추출 지원
9+
- CVE, CPE, Vendor등 데이터베이스 기본 요소 자동 탐색
10+
11+
# Installation
12+
귀하의 컴퓨터에 MySQL 데이터베이스에 접근할 수 있는 클라이언트가 요구됩니다.<br>
13+
Python Framework을 기반으로 작동하므로, Python 3 이상의 인터프리터를 요구하며, 해당 모듈을 실행하려면 다음과 같은 명령어가 권장됩니다:<br>
14+
```
15+
git clone https://github.com/ruskonert/cve-mysql-python.git
16+
cd cve-mysql-python
17+
pip install -r requirements.txt
18+
```
19+
만약 파이썬 인터프리터가 없다면, 아래의 링크를 통해 Released된 실행 가능한 최신 파일을 다운로드하여 사용하십시오.<br>
20+
https://github.com/Ruskonert/cve-mysql-python/releases
21+
22+
23+
# Command
24+
해당 모듈을 사용하기 전 정의된 명령어는 다음과 같습니다.
25+
```
26+
python cvemysql.py [-u user] [-p password] [-y year] [output_name] [--cofigurations]...
27+
```
28+
29+
## Requirement argument
30+
`[-y year]` CVE 리스트 연도를 설정합니다. `2010-2018` 처럼 특정 연도를 지정하는 것도 가능합니다.<br>
31+
단, `content``mitre`라면 해당 인자 값은 무시합니다.
32+
33+
## Option argument
34+
`[-u user]` MySQL 서버에 연결할 유저명을 입력합니다. 지정하지 않으면 기본값은 `root`입니다.<br>
35+
`[-p password]` MySQL 서버에 연결할 유저 비밀번호를 입력합니다. 지정하지 않으면 콘솔에서 입력받습니다.<br>
36+
`[-i ip]` MySQL 서버에 연결하기 위한 IP 주소를 지정합니다. 지정하지 않으면 기본값은 `127.0.0.1`입니다.<br>
37+
`[-port]` MySQL 서버에 연결하기 위한 포트를 지정합니다. 지정하지 않으면 기본값은 `3309`입니다.<br>
38+
`[-d dbname]` 생성할 데이터베이스의 이름을 미리 설정합니다. 기본값은 `NVD_NIST`입니다.<br>
39+
`[-t tablename]` 테이블 이름을 미리 설정합니다. 기본값은 `NVD_NIST_TABLE`입니다.<br>
40+
`[-c content]` 리스트 컨텐츠을 선택합니다. 현재는 해당 인자를 사용하지 않아도 자동으로 `NVD_NIST`로 기본 설정되어 있습니다.<br> Available type - nvd, mitre<br>
41+
42+
`[-tc thread_count]` 멀티쓰레드 갯수를 설정합니다. 기본값은 `4`입니다. 해당 값을 건드리는 것은 추천하지 않습니다.
43+
44+
`[output_file]` 출력 타입 지정시, 추출될 파일명을 지정합니다. 출력 파일의 이름을 지정하는 것을 강력히 권장합니다. 확장자는 기재하지 않아도 되며, 만약 압축 확장자(.zip)가 붙어있다면, 추출된 파일들을 전부 압축하여 `zip` 파일로 만들어줍니다.<br>
45+
46+
47+
## Configuration argument
48+
`[--year-all]` 모든 연도를 지정합니다. (NVD-NIST 전용)<br>
49+
`[--db]` 데이터베이스 파일로 추출합니다. MySQL 기반에서는 SQL 파일이 기본 확장자입니다.<br>
50+
`[--csv]` 데이터베이스에 있는 데이터 값들을 CSV 파일로 추출합니다.<br>
51+
`[--setup-install]` 처음 실행할 때 모듈이 정상적으로 작동할 수 있도록 합니다. DEPRECATED.<br>
52+
53+
<b>현재, ICS-CERT 타입은 지원하지 않아 `-type` 이나 `--all` 옵션 인자값을 사용해도 NVD-NIST 타입 1개만 사용됩니다.</b><br>
54+
## Example
55+
아래는 해당 플랫폼을 사용하기 위해 입력하는 명령어의 예시들을 나열한 것입니다. 프로그램을 실행시킬 때 참조하시기 바랍니다.<br>
56+
예를 들어 특정 년도의 NVD-NIST CVE 리스트를 모두 가져와서 데이터베이스만 만들려면 다음과 같이 하십시오:
57+
```
58+
python cvemysql.py -year <year>
59+
```
60+
61+
2003년부터 2008년까지의 NVD-NIST CVE 리스트를 데이터베이스에 담고 CSV 파일과 DB로 추출하고 싶다면 다음과 같이 하십시오:
62+
```
63+
python cvemysql.py -u <name> -p <password> -year 2003-2008 --db --csv "my-cve-list-export"
64+
```
65+
66+
모든 년도의 NVD-NIST 리스트를 데이터베이스에 담고 CSV 파일과 DB로 추출한 후, 파일이름이 `my-cve-list-export``zip`파일로 압축하고 싶다면 다음과 같이 하십시오.
67+
단, 이 경우에는 시간이 오래 걸릴 수 있으며, 용량이 매우 클 수 있습니다:
68+
```
69+
python cvemysql.py -u <name> -p <password> --year-all --db --csv "my-cve-list-export.zip"
70+
```

cve.py

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# -*- coding: utf-8 -*-
2+
import abc
3+
from database import *
4+
5+
class TypeInstanceException(Exception):
6+
def __init__(self, *args, **kwargs):
7+
super().__init__(args, kwargs)
8+
9+
class CVEDatabase(MySqlBase):
10+
def __init__(self, db):
11+
if isinstance(db, MySqlBase):
12+
self.conn = db.conn
13+
self.database = db.database
14+
self.user = db.user
15+
self.port = db.port
16+
self.host = db.host
17+
self.password = db.password
18+
self.cur = db.cur
19+
if self.database is not None:
20+
self.use_database(self.database)
21+
else:
22+
raise TypeInstanceException("The variable 'db' is not instance of MySqlBase")
23+
24+
def default_table_column(self):
25+
raise NotImplementedError("You should override this method to use.")
26+
27+
def insert(self, obj):
28+
raise NotImplementedError("You should override this method to use.")
29+
30+
def load(self, obj):
31+
raise NotImplementedError("You should override this method to use.")
32+
33+
def table_insert(self, tablename, jsonCollection):
34+
raise NotImplementedError("You should override this method to use.")

cvemitre.py

+127
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
import csv
2+
import re
3+
import xml.etree.ElementTree as ET
4+
from database import *
5+
from cve import CVEDatabase
6+
7+
execption_list = {}
8+
9+
class Cvemitre(CVEDatabase):
10+
def __init__(self, mysql_base):
11+
super().__init__(mysql_base)
12+
13+
def default_table_column(self):
14+
a1 = TableColumn("_number", "INT PRIMARY KEY AUTO_INCREMENT")
15+
a2 = TableColumn("cve_year", "VARCHAR(5)")
16+
a3 = TableColumn("name", "VARCHAR(24)")
17+
a4 = TableColumn("status", "VARCHAR(12)")
18+
a5 = TableColumn("description", "TEXT")
19+
a6 = TableColumn("reference", "TEXT")
20+
a9 = TableColumn("phase", "VARCHAR(32)")
21+
a7 = TableColumn("vote", "TEXT")
22+
a8 = TableColumn("comment", "TEXT")
23+
return tuple(vars().values())
24+
25+
def load(self, obj):
26+
self.connect()
27+
if isinstance(obj, dict):
28+
year = obj.get('year')
29+
raw_type = obj.get('specific_type')
30+
else:
31+
raise TypeError("The variable 'obj' must be dict, not {t}".format(t=type(obj).__str__()))
32+
33+
url = "https://cve.mitre.org/data/downloads/"
34+
35+
if raw_type is None:
36+
raw_type = "csv"
37+
raw_file = "allitems.{ft}".format(ft=raw_type)
38+
is_exist = False
39+
40+
if os.path.exists(raw_file):
41+
if raw_type == "xml":
42+
if util.vaildxml(raw_file):
43+
print("The resource file already exist, continue without the download")
44+
is_exist = True
45+
else:
46+
os.remove(raw_file)
47+
elif raw_type == "csv":
48+
if util.vaildcsv(raw_file):
49+
print("The resource file already exist, continue without the download")
50+
is_exist = True
51+
else:
52+
os.remove(raw_file)
53+
if not is_exist:
54+
target_url = url + raw_file
55+
print("Downloading the resource file ...")
56+
util.downloadfrom(target_url)
57+
58+
collection = []
59+
if raw_type == "xml":
60+
readTo = ET.parse(raw_file).getroot()
61+
else:
62+
with open(raw_file, 'r', newline='', encoding='ISO-8859-1') as fs:
63+
readTo = csv.reader(fs)
64+
for line in readTo:
65+
try:
66+
name : str = line[0]
67+
if not name.startswith("CVE-"):
68+
continue
69+
status = line[1]
70+
description = line[2]
71+
reference = line[3]
72+
phase = line[4]
73+
vote = line[5]
74+
comment = line[6]
75+
collection.append((name,status,description,reference,phase,vote,comment))
76+
except UnicodeDecodeError as e:
77+
print("오류: 해당 CSV를 객체화할 수 없었습니다 -> {cve} | Reason: {reason}".format(cve=name, reason=e))
78+
return raw_file, collection
79+
80+
def table_insert(self, tablename, collection):
81+
for line in collection:
82+
line = list(line)
83+
name = line[0]
84+
p = re.compile(r'CVE-(\d{4})-.+$')
85+
cve_year = str(p.match(name).group(1))
86+
87+
status = line[1]
88+
description = line[2]
89+
reference = line[3]
90+
phase = line[4]
91+
vote = line[5]
92+
comment = line[6]
93+
94+
ex = None
95+
query_argument = None
96+
query_format = None
97+
query_argument = None
98+
query_header = None
99+
variable_name = None
100+
101+
v = dict(vars())
102+
103+
query_header = "("
104+
query_format = "("
105+
query_argument = []
106+
# automatic insert value
107+
for variable_name in v.keys():
108+
if isinstance(v[variable_name], str) and not variable_name == "tablename":
109+
query_header += variable_name + ','
110+
query_format += "%s,"
111+
query_argument.append(v[variable_name])
112+
query_header = query_header[:-1]
113+
query_header += ")"
114+
query_format = query_format[:-1]
115+
query_format += ")"
116+
self.send_query("INSERT INTO {table_name} {header} VALUES {format}".format(table_name=tablename, header=query_header, format=query_format), tuple(query_argument), False, execption_list)
117+
if len(execption_list) != 0:
118+
current_key = list(execption_list.keys())
119+
for ex in current_key:
120+
print("\n실패: Column에 값을 넣을 수 없습니다. -> {cve} | Reason: {r}".format(cve=name, r=ex))
121+
execption_list.clear()
122+
123+
def insert(self, obj):
124+
raise NotImplementedError("No need to execute")
125+
126+
def export(self, export_path_name="unspecified", export_type='sql', tablename="Unknown_table", option=None, charset='utf-8'):
127+
return super().export(export_path_name, export_type, tablename, option, "ISO-8859-1")

0 commit comments

Comments
 (0)