Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions content/pages/vex.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Title: Vulnerabilities involving Apache Solr
URL: vex.html
save_as: vex.html
template: vex
35 changes: 35 additions & 0 deletions content/solr/vex/2025-01-26-cve-2025-24814.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
cve: CVE-2025-24814
jira: SOLR-16781
severity: moderate
category:
- solr/vex
vulnerable_component:
name: Apache Solr
versions:
- fixed: 9.8.0
analysis:
state: exploitable
response:
- update
title: "Apache Solr: Core-creation with \"trusted\" configset can use arbitrary untrusted files"
---
Core creation allows users to replace "trusted" configset files with arbitrary configuration

Solr instances are vulnerable if they:

1. use the `FileSystemConfigSetService` component (the default in "standalone" or "user-managed" mode), and
2. run without authentication and authorization enabled

In this configuration, attackers can exploit a privilege escalation issue by replacing individual "trusted" configset files with potentially untrusted files from elsewhere on the filesystem.
These replacements are incorrectly treated as "trusted" and can leverage `<lib>` tags to add arbitrary code to Solr's classpath, potentially allowing malicious plugins or components to be loaded.

This issue affects all Apache Solr versions up through Solr 9.7.

#### Mitigation

Users can protect against the vulnerability by enabling authentication and authorization on their Solr clusters or switching to SolrCloud (and away from "FileSystemConfigSetService").
Users are also recommended to upgrade to Solr 9.8.0, which mitigates this issue by disabling use of "<lib>" tags by default.

#### Credit
pwn null (reporter)
39 changes: 39 additions & 0 deletions content/solr/vex/2025-07-25-cve-2024-51504.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
cve: CVE-2024-51504
jira: SOLR-17809
severity: important
category:
- solr/vex
vulnerable_component:
name: zookeeper
versions:
- introduced: 3.9.0
last_affected: 3.9.2
impacted_component:
name: Apache Solr
versions:
- introduced: 9.4.0
fixed: 9.9.0
analysis:
state: not_affected
justification: requires_configuration
title: "Apache ZooKeeper: Authentication bypass with IP-based authentication in Admin Server"
---

CVE-2024-51504 is **not** considered exploitable in typical **production** deployments of Apache Solr (versions 3.4.0 to 3.8.1).
Successful exploitation requires a very specific and non-standard configuration.
The following conditions **must all be met**:

* Solr must be deployed in [SolrCloud mode](https://solr.apache.org/guide/solr/latest/deployment-guide/cluster-types.html#solrcloud-mode), which relies on ZooKeeper for coordination.
* The **embedded ZooKeeper server** must be in use: a setup that is explicitly discouraged for production.
Solr emits a warning when this configuration is detected, and it is not commonly used outside of development or experimentation.
* The **ZooKeeper Admin Server** must be **manually enabled** in the ZooKeeper configuration file (`server/solr/zoo.cfg`).
By default, this feature is disabled:

```properties
# Disable ZK AdminServer since we do not use it
admin.enableServer=false
```

Because these conditions are highly unlikely in secure, production-grade environments,
the Solr community considers this vulnerability **non-exploitable under standard operating conditions**.
19 changes: 19 additions & 0 deletions content/solr/vex/2025-08-02-cve-2024-7254.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
cve: CVE-2024-7254
jira: SOLR-17833
severity: important
category:
- solr/vex
vulnerable_component:
name: protobuf-java
versions:
- fixed: 3.25.5
impacted_component:
name: Apache Solr
versions:
- last_affected: 9.9.0
analysis:
state: in_triage
title: "protobuf-java: Potential Denial of Service issue"
---
When parsing unknown fields in the Protobuf Java Lite and Full library, a maliciously crafted message can cause a StackOverflow error and lead to a program crash.
10 changes: 9 additions & 1 deletion pelicanconf.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,18 @@
'jinja2content',
'regex_replace',
'age_days_lt',
'vex'
'vex',
'yaml_front_matter'
# 'md_inline_extension',
]

JINJA_ENVIRONMENT = {
'extensions': [
'jinja2.ext.do',
'jinja2.ext.loopcontrols'
]
}

MARKDOWN = {
'extension_configs': {
'toc': {},
Expand Down
137 changes: 137 additions & 0 deletions plugins/vex/enrich_metadata.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# SPDX-License-Identifier: Apache-2.0
from __future__ import annotations
from pelican.contents import Content
from typing import Any
from functools import total_ordering


@total_ordering
class Version:
"""
Version class to handle affected versions in metadata.
"""

def __init__(self, major: int, minor: int, patch: int = 0,
pre_release: str = None):
self.major = major
self.minor = minor
self.patch = patch
self.pre_release = pre_release

def __lt__(self, other: Version | str) -> bool:
"""
Compare two Version objects.
"""
if isinstance(other, str):
other = parse_version(other)
if self.major != other.major:
return self.major < other.major
if self.minor != other.minor:
return self.minor < other.minor
if self.patch != other.patch:
return self.patch < other.patch
if self.pre_release != other.pre_release:
if self.pre_release is None:
return False
if other.pre_release is None:
return True
return self.pre_release < other.pre_release
return False

def __eq__(self, other: Version | str) -> bool:
"""
Check if two Version objects are equal.
"""
if isinstance(other, str):
other = parse_version(other)
return (self.major == other.major and
self.minor == other.minor and
self.patch == other.patch and
self.pre_release == other.pre_release)

def __str__(self):
"""
String representation of the Version object.
"""
version_str = f"{self.major}.{self.minor}.{self.patch}"
if self.pre_release:
return f"{version_str}-{self.pre_release}"
return version_str


def parse_version(version_str: str) -> Version:
"""
Parse a version string into a Version object.
"""
version, pre_release = version_str.split('-') if '-' in version_str else (version_str, None)
parts = version.split('.')
major = int(parts[0])
minor = int(parts[1]) if len(parts) > 1 else 0
patch = int(parts[2]) if len(parts) > 2 else 0
return Version(major, minor, patch, pre_release)


class VersionRange:
"""
VersionRange class to handle a range of versions, with inclusive/exclusive end.
"""

def __init__(self, start: Version | None, end: Version, end_inclusive: bool = True):
self.start = start
self.end = end
self.end_inclusive = end_inclusive

def __str__(self):
"""
String representation of the VersionRange object.
"""
left = "[" if self.start is not None else "(-∞"
right = "]" if self.end_inclusive else ")"
if self.start != self.end or not self.end_inclusive:
return f"{left}{self.start}, {self.end}{right}"
return str(self.start)


class AffectedArtifact:
def __init__(self, name: str, versions: list[VersionRange]):
self.name = name
self.versions = versions

def __str__(self):
"""
String representation of the AffectedArtifact object.
"""
versions_str = ' ∪ '.join(str(vr) for vr in self.versions)
return f"AffectedArtifact[name = {self.name}, versions = {versions_str}]"


def enrich_content_metadata(content: Content) -> None:
"""
Enrich content metadata.

This function parses the metadata for the vulnerable and impacted components,
and replaces them with enriched AffectedArtifact objects.
"""
metadata = content.metadata
if 'vulnerable_component' in metadata:
metadata['vulnerable_component'] = enrich_affected_artifact(metadata['vulnerable_component'])
if 'impacted_component' in metadata:
metadata['impacted_component'] = enrich_affected_artifact(metadata['impacted_component'])
else:
metadata['impacted_component'] = metadata['vulnerable_component']


def enrich_affected_artifact(content: Any) -> AffectedArtifact:
"""
Parse the content to create an AffectedArtifact object.
"""
name = content.get('name', 'Unknown Artifact')
versions = [
VersionRange(
parse_version(v['introduced']) if 'introduced' in v else None,
parse_version(v['fixed' if 'fixed' in v else 'last_affected']),
v.get('last_affected', False)
)
for v in content.get('versions', [])
]
return AffectedArtifact(name, versions)
Loading