|
15 | 15 | import requests |
16 | 16 | from aboutcode.pipeline import LoopProgress |
17 | 17 | from dateutil import parser as dateparser |
18 | | -from django.db import DataError |
19 | 18 |
|
20 | | -from vulnerabilities.models import AdvisoryAlias |
21 | 19 | from vulnerabilities.models import AdvisoryExploit |
22 | | -from vulnerabilities.models import AdvisoryReference |
23 | | -from vulnerabilities.models import AdvisoryV2 |
24 | 20 | from vulnerabilities.pipelines import VulnerableCodePipeline |
25 | | -from vulnerabilities.utils import relate_aliases_with_advisories |
| 21 | +from vulnerabilities.utils import build_alias_to_advisory_map |
26 | 22 |
|
27 | 23 |
|
28 | 24 | class ExploitDBImproverPipeline(VulnerableCodePipeline): |
@@ -66,86 +62,80 @@ def add_exploit(self): |
66 | 62 | raw_data = list(csvreader) |
67 | 63 | fetched_exploit_count = len(raw_data) |
68 | 64 |
|
69 | | - vulnerability_exploit_count = 0 |
70 | 65 | self.log(f"Enhancing the vulnerability with {fetched_exploit_count:,d} exploit records") |
71 | 66 | progress = LoopProgress(total_iterations=fetched_exploit_count, logger=self.log) |
72 | 67 |
|
73 | | - for row in progress.iter(raw_data): |
74 | | - vulnerability_exploit_count += add_vulnerability_exploit(row, self.log) |
75 | | - |
76 | | - self.log(f"Successfully added {vulnerability_exploit_count:,d} exploit-db advisory exploit") |
77 | | - |
78 | | - |
79 | | -def add_vulnerability_exploit(row, logger): |
80 | | - advisories = set() |
81 | | - |
82 | | - aliases = row["codes"].split(";") if row["codes"] else [] |
83 | | - |
84 | | - if not aliases: |
85 | | - return 0 |
| 68 | + all_aliases = set() |
86 | 69 |
|
87 | | - advisories = relate_aliases_with_advisories(aliases) |
| 70 | + for row in raw_data: |
| 71 | + if row["codes"]: |
| 72 | + all_aliases.update(row["codes"].split(";")) |
88 | 73 |
|
89 | | - if not advisories: |
90 | | - logger(f"No advisory found for aliases {aliases}") |
91 | | - return 0 |
| 74 | + alias_to_advisories = build_alias_to_advisory_map(all_aliases) |
92 | 75 |
|
93 | | - date_added = parse_date(row["date_added"]) |
94 | | - source_date_published = parse_date(row["date_published"]) |
95 | | - source_date_updated = parse_date(row["date_updated"]) |
| 76 | + exploits = [] |
| 77 | + seen = set() |
96 | 78 |
|
97 | | - for advisory in advisories: |
98 | | - add_exploit_references(row["codes"], row["source_url"], row["file"], advisory, logger) |
99 | | - try: |
100 | | - AdvisoryExploit.objects.update_or_create( |
101 | | - advisory=advisory, |
102 | | - data_source="Exploit-DB", |
103 | | - defaults={ |
104 | | - "date_added": date_added, |
105 | | - "description": row["description"], |
106 | | - "known_ransomware_campaign_use": row["verified"], |
107 | | - "source_date_published": source_date_published, |
108 | | - "exploit_type": row["type"], |
109 | | - "platform": row["platform"], |
110 | | - "source_date_updated": source_date_updated, |
111 | | - "source_url": row["source_url"], |
112 | | - }, |
113 | | - ) |
114 | | - except DataError as e: |
115 | | - logger( |
116 | | - f"Failed to Create the Vulnerability Exploit-DB with error {e!r}:\n{traceback_format_exc()}", |
117 | | - level=logging.ERROR, |
118 | | - ) |
119 | | - return 1 |
120 | | - |
121 | | - |
122 | | -def add_exploit_references(ref_id, direct_url, path, adv, logger): |
123 | | - url_map = { |
124 | | - "file_url": f"https://gitlab.com/exploit-database/exploitdb/-/blob/main/{path}", |
125 | | - "direct_url": direct_url, |
126 | | - } |
127 | | - |
128 | | - for key, url in url_map.items(): |
129 | | - if url: |
130 | | - try: |
131 | | - ref, created = AdvisoryReference.objects.update_or_create( |
132 | | - url=url, |
133 | | - defaults={ |
134 | | - "reference_id": ref_id, |
135 | | - "reference_type": AdvisoryReference.EXPLOIT, |
136 | | - }, |
137 | | - ) |
138 | | - |
139 | | - if created: |
140 | | - ref.advisories.add(adv) |
141 | | - ref.save() |
142 | | - logger(f"Created {ref} for {adv} with {key}={url}") |
143 | | - |
144 | | - except DataError as e: |
145 | | - logger( |
146 | | - f"Failed to Create the Vulnerability Reference For Exploit-DB with error {e!r}:\n{traceback_format_exc()}", |
147 | | - level=logging.ERROR, |
148 | | - ) |
| 79 | + for row in progress.iter(raw_data): |
| 80 | + aliases = row["codes"].split(";") if row["codes"] else [] |
| 81 | + |
| 82 | + if not aliases: |
| 83 | + continue |
| 84 | + |
| 85 | + date_added = parse_date(row["date_added"]) |
| 86 | + source_date_published = parse_date(row["date_published"]) |
| 87 | + source_date_updated = parse_date(row["date_updated"]) |
| 88 | + |
| 89 | + for alias in aliases: |
| 90 | + for advisory in alias_to_advisories.get(alias, ()): |
| 91 | + |
| 92 | + key = ( |
| 93 | + advisory.id, |
| 94 | + "Exploit-DB", |
| 95 | + alias, |
| 96 | + ) |
| 97 | + |
| 98 | + if key in seen: |
| 99 | + continue |
| 100 | + |
| 101 | + seen.add(key) |
| 102 | + |
| 103 | + exploits.append( |
| 104 | + AdvisoryExploit( |
| 105 | + advisory=advisory, |
| 106 | + record_id=alias, |
| 107 | + data_source="Exploit-DB", |
| 108 | + date_added=date_added, |
| 109 | + description=row["description"], |
| 110 | + known_ransomware_campaign_use=row["verified"], |
| 111 | + source_date_published=source_date_published, |
| 112 | + exploit_type=row["type"], |
| 113 | + platform=row["platform"], |
| 114 | + source_date_updated=source_date_updated, |
| 115 | + source_url=row["source_url"], |
| 116 | + ) |
| 117 | + ) |
| 118 | + |
| 119 | + AdvisoryExploit.objects.bulk_create( |
| 120 | + exploits, |
| 121 | + update_conflicts=True, |
| 122 | + unique_fields=[ |
| 123 | + "advisory", |
| 124 | + "data_source", |
| 125 | + "record_id", |
| 126 | + ], |
| 127 | + update_fields=[ |
| 128 | + "date_added", |
| 129 | + "description", |
| 130 | + "known_ransomware_campaign_use", |
| 131 | + "source_date_published", |
| 132 | + "exploit_type", |
| 133 | + "platform", |
| 134 | + "source_date_updated", |
| 135 | + "source_url", |
| 136 | + ], |
| 137 | + batch_size=1000, |
| 138 | + ) |
149 | 139 |
|
150 | 140 |
|
151 | 141 | def parse_date(date_string): |
|
0 commit comments