Skip to content

Commit 8865d9b

Browse files
Add KDE security advisory importer
Signed-off-by: Dhirenderchoudhary <dhirenderchoudhary0001@gmail.com>
1 parent 94a9c8f commit 8865d9b

8 files changed

Lines changed: 617 additions & 0 deletions

File tree

vulnerabilities/importers/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
from vulnerabilities.pipelines.v2_importers import github_osv_importer as github_osv_importer_v2
5959
from vulnerabilities.pipelines.v2_importers import gitlab_importer as gitlab_importer_v2
6060
from vulnerabilities.pipelines.v2_importers import istio_importer as istio_importer_v2
61+
from vulnerabilities.pipelines.v2_importers import kde_importer as kde_importer_v2
6162
from vulnerabilities.pipelines.v2_importers import mattermost_importer as mattermost_importer_v2
6263
from vulnerabilities.pipelines.v2_importers import mozilla_importer as mozilla_importer_v2
6364
from vulnerabilities.pipelines.v2_importers import nginx_importer as nginx_importer_v2
@@ -99,6 +100,7 @@
99100
curl_importer_v2.CurlImporterPipeline,
100101
oss_fuzz_v2.OSSFuzzImporterPipeline,
101102
istio_importer_v2.IstioImporterPipeline,
103+
kde_importer_v2.KDEImporterPipeline,
102104
postgresql_importer_v2.PostgreSQLImporterPipeline,
103105
mozilla_importer_v2.MozillaImporterPipeline,
104106
github_osv_importer_v2.GithubOSVImporterPipeline,
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
#
2+
# Copyright (c) nexB Inc. and others. All rights reserved.
3+
# VulnerableCode is a trademark of nexB Inc.
4+
# SPDX-License-Identifier: Apache-2.0
5+
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
6+
# See https://github.com/aboutcode-org/vulnerablecode for support or download.
7+
# See https://aboutcode.org for more information about nexB OSS projects.
8+
#
9+
10+
import logging
11+
import re
12+
from datetime import datetime
13+
from datetime import timezone
14+
from typing import Iterable
15+
from typing import List
16+
from typing import Optional
17+
18+
from bs4 import BeautifulSoup
19+
20+
from vulnerabilities.importer import AdvisoryDataV2
21+
from vulnerabilities.importer import ReferenceV2
22+
from vulnerabilities.importer import VulnerabilitySeverity
23+
from vulnerabilities.pipelines import VulnerableCodeBaseImporterPipelineV2
24+
from vulnerabilities.severity_systems import SCORING_SYSTEMS
25+
from vulnerabilities.utils import fetch_response
26+
27+
logger = logging.getLogger(__name__)
28+
29+
KDE_SECURITY_URL = "https://kde.org/info/security/"
30+
31+
32+
class KDEImporterPipeline(VulnerableCodeBaseImporterPipelineV2):
33+
"""Importer for KDE security advisories."""
34+
35+
pipeline_id = "kde_importer"
36+
spdx_license_expression = "CC-BY-SA-4.0"
37+
license_url = "https://kde.org/info/security/"
38+
repo_url = "https://kde.org/info/security/"
39+
40+
precedence = 200
41+
42+
_cached_advisory_urls = None
43+
44+
@classmethod
45+
def steps(cls):
46+
return (cls.collect_and_store_advisories,)
47+
48+
def get_advisory_urls(self) -> List[str]:
49+
if self._cached_advisory_urls is not None:
50+
return self._cached_advisory_urls
51+
52+
try:
53+
response = fetch_response(KDE_SECURITY_URL)
54+
html = response.text
55+
except Exception as e:
56+
logger.error(f"Failed to fetch KDE security page: {e}")
57+
return []
58+
59+
soup = BeautifulSoup(html, "lxml")
60+
advisory_urls = []
61+
62+
for link in soup.find_all("a", href=True):
63+
href = link["href"]
64+
if "advisory-" in href and href.endswith(".txt"):
65+
if href.startswith("http"):
66+
advisory_urls.append(href)
67+
else:
68+
advisory_urls.append(f"https://kde.org{href}")
69+
70+
self._cached_advisory_urls = advisory_urls
71+
return advisory_urls
72+
73+
def advisories_count(self) -> int:
74+
return len(self.get_advisory_urls())
75+
76+
def collect_advisories(self) -> Iterable[AdvisoryDataV2]:
77+
for url in self.get_advisory_urls():
78+
try:
79+
response = fetch_response(url)
80+
advisory = parse_kde_advisory(response.text, url)
81+
if advisory:
82+
yield advisory
83+
except Exception as e:
84+
logger.error(f"Failed to parse advisory {url}: {e}")
85+
continue
86+
87+
88+
def parse_kde_advisory(advisory_text: str, url: str) -> Optional[AdvisoryDataV2]:
89+
"""Parse a KDE security advisory and return an AdvisoryDataV2."""
90+
if not advisory_text:
91+
return None
92+
93+
title = extract_field(advisory_text, "Title")
94+
risk_rating = extract_field(advisory_text, "Risk Rating")
95+
cve = extract_field(advisory_text, "CVE")
96+
date_str = extract_field(advisory_text, "Date")
97+
98+
summary = extract_section(advisory_text, "Overview")
99+
100+
advisory_id = generate_advisory_id(url, cve)
101+
if not advisory_id:
102+
logger.warning(f"Could not generate advisory ID for {url}")
103+
return None
104+
105+
aliases = parse_cve_ids(cve)
106+
if advisory_id in aliases:
107+
aliases.remove(advisory_id)
108+
109+
date_published = parse_date(date_str)
110+
111+
references = [ReferenceV2(url=url)]
112+
for cve_id in aliases:
113+
references.append(
114+
ReferenceV2(
115+
reference_id=cve_id,
116+
url=f"https://cve.mitre.org/cgi-bin/cvename.cgi?name={cve_id}",
117+
)
118+
)
119+
120+
severities = []
121+
if risk_rating:
122+
severities.append(
123+
VulnerabilitySeverity(
124+
system=SCORING_SYSTEMS["generic_textual"],
125+
value=risk_rating.strip(),
126+
url=url,
127+
)
128+
)
129+
130+
return AdvisoryDataV2(
131+
advisory_id=advisory_id,
132+
aliases=aliases,
133+
summary=summary or "",
134+
references=references,
135+
date_published=date_published,
136+
severities=severities,
137+
url=url,
138+
original_advisory_text=advisory_text,
139+
)
140+
141+
142+
def extract_field(text: str, field_name: str) -> Optional[str]:
143+
"""Extract a field value like 'Title: value' from advisory text."""
144+
pattern = rf"^{re.escape(field_name)}:\s*(.+?)$"
145+
match = re.search(pattern, text, re.MULTILINE | re.IGNORECASE)
146+
if match:
147+
return match.group(1).strip()
148+
return None
149+
150+
151+
def extract_section(text: str, section_name: str) -> Optional[str]:
152+
"""Extract a section like 'Overview\n========\ncontent' from advisory text."""
153+
pattern = rf"{re.escape(section_name)}\s*\n=+\s*\n(.*?)(?=\n\w+[^\n]*\n=+|\Z)"
154+
match = re.search(pattern, text, re.DOTALL | re.IGNORECASE)
155+
if match:
156+
content = match.group(1).strip()
157+
content = re.sub(r"\n\s*\n", "\n\n", content)
158+
return content
159+
return None
160+
161+
162+
def generate_advisory_id(url: str, cve: Optional[str]) -> Optional[str]:
163+
"""Generate advisory ID from URL (advisory-YYYYMMDD-N.txt) or fall back to CVE."""
164+
match = re.search(r"advisory-(\d{8})-(\d+)\.txt", url)
165+
if match:
166+
return f"KDE-SA-{match.group(1)}-{match.group(2)}"
167+
168+
cve_ids = parse_cve_ids(cve)
169+
if cve_ids:
170+
return cve_ids[0]
171+
172+
return None
173+
174+
175+
def parse_cve_ids(cve_field: Optional[str]) -> List[str]:
176+
"""Parse CVE IDs from field, including old CAN- format."""
177+
if not cve_field:
178+
return []
179+
180+
cve_pattern = r"(CVE-\d{4}-\d+|CAN-\d{4}-\d+)"
181+
matches = re.findall(cve_pattern, cve_field, re.IGNORECASE)
182+
return [m.upper().replace("CAN-", "CVE-") for m in matches]
183+
184+
185+
def parse_date(date_str: Optional[str]) -> Optional[datetime]:
186+
"""Parse date from various formats used in KDE advisories."""
187+
if not date_str:
188+
return None
189+
190+
date_str = date_str.strip()
191+
192+
formats = [
193+
"%Y-%m-%d",
194+
"%d %B %Y",
195+
"%d/%m/%Y",
196+
"%B %d, %Y",
197+
"%d %b %Y",
198+
]
199+
200+
for fmt in formats:
201+
try:
202+
dt = datetime.strptime(date_str, fmt)
203+
return dt.replace(tzinfo=timezone.utc)
204+
except ValueError:
205+
continue
206+
207+
try:
208+
from dateutil import parser as dateparser
209+
210+
dt = dateparser.parse(date_str)
211+
if dt:
212+
return dt.replace(tzinfo=timezone.utc)
213+
except Exception:
214+
pass
215+
216+
logger.warning(f"Could not parse date: {date_str}")
217+
return None
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
-----BEGIN PGP SIGNED MESSAGE-----
2+
Hash: SHA1
3+
4+
5+
6+
KDE Security Advisory: KDM vulnerabilities
7+
Original Release Date: 2003-09-16
8+
URL: http://www.kde.org/info/security/advisory-20030916-1.txt
9+
10+
0. References
11+
http://cert.uni-stuttgart.de/archive/suse/security/2002/12/msg00101.html
12+
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2003-0690
13+
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2003-0692
14+
15+
16+
1. Systems affected:
17+
18+
All versions of KDM as distributed with KDE up to and including
19+
KDE 3.1.3.
20+
21+
22+
2. Overview:
23+
24+
Two issues have been discovered in KDM:
25+
26+
a) CAN-2003-0690:
27+
Privilege escalation with specific PAM modules
28+
b) CAN-2003-0692:
29+
Session cookies generated by KDM are potentially insecure
30+
31+
32+
3. Impact:
33+
34+
If KDM is used in combination with the MIT pam_krb5 module and given
35+
a valid username and password of an existing user, the login attempt
36+
succeeds and establishes a session with excessive privileges. This
37+
may enable a local root compromise of the system.
38+
39+
It is possible that the same vulnerability exists if KDM is used
40+
with other PAM modules. At the date of this advisory we are however
41+
not aware of any other PAM module being affected by this
42+
vulnerability.
43+
44+
The weak cookie generation may allow non-authorized users to guess
45+
the session cookie by a brute force attack, which allows, assuming
46+
hostname / IP restrictions can be bypassed, to authorize to the running
47+
session and gain full access to it.
48+
49+
50+
4. Solution:
51+
52+
A patch for KDE 3.1.3 is available from
53+
ftp://ftp.kde.org/pub/kde/security_patches :
54+
55+
8553c20798b321e333d8c516636f2297 post-3.1.3-kdebase-kdm.patch
56+
57+
58+
5. Credits:
59+
60+
Thanks to the KDE Security Team for handling this issue.
61+
62+
63+
-----BEGIN PGP SIGNATURE-----
64+
Version: GnuPG v1.2.2-rc1-SuSE (GNU/Linux)
65+
66+
iD8DBQE/Z1fBvsXr+iuy1UoRAi02AJ90TqHxCeqzqGJrN3jS7mRSd9u5xQCg6/Do
67+
LB3tubiwfy8TUy5rL7B8UFY=
68+
=2tbX
69+
-----END PGP SIGNATURE-----
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
KDE Project Security Advisory
2+
=============================
3+
4+
Title: kauth: Local privilege escalation
5+
Risk Rating: High
6+
CVE: CVE-2017-8422
7+
Versions: kauth < 5.34, kdelibs < 4.14.32
8+
Date: 10 May 2017
9+
10+
11+
Overview
12+
========
13+
KAuth contains a logic flaw in which the service invoking dbus
14+
is not properly checked.
15+
16+
This allows spoofing the identity of the caller and with some
17+
carefully crafted calls can lead to gaining root from an
18+
unprivileged account.
19+
20+
Solution
21+
========
22+
Update to kauth >= 5.34 and kdelibs >= 4.14.32 (when released)
23+
24+
Or apply the following patches:
25+
kauth: https://commits.kde.org/kauth/df875f725293af53399f5146362eb158b4f9216a
26+
kdelibs: https://commits.kde.org/kdelibs/264e97625abe2e0334f97de17f6ffb52582888ab
27+
28+
Credits
29+
=======
30+
Thanks to Sebastian Krahmer from SUSE for the report and
31+
to Albert Astals Cid from KDE for the fix.

0 commit comments

Comments
 (0)