Skip to content

Commit 2ca2b56

Browse files
committed
add blogs
1 parent a75c4c4 commit 2ca2b56

8 files changed

+260
-0
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
---
2+
title: Apache httpd XSS Using Multiple Extensions
3+
date: 2025-07-08
4+
tags:
5+
- "content-type"
6+
- "xss"
7+
- "apache"
8+
advisory: false
9+
origin:
10+
cves:
11+
---
12+
# Introduction
13+
This post dives into a stored Cross-Site Scripting (XSS) technique I discovered while researching Fortinet's endpoint protection solution. It builds on previous work, specifically [part two](https://yaniv-git.github.io/2025/06/29/Caught%20in%20the%20FortiNet:%20How%20Attackers%20Can%20Exploit%20FortiClient%20to%20Compromise%20Organizations%202/#From-Limited-File-Write-to-XSS-CVE-2025-22859) of my series (CVE-2025-22859), where I detailed an `httpd` stored XSS vulnerability using a files with a predefined extensions.
14+
15+
I have already [covered](https://yaniv-git.github.io/2023/11/04/Apache%20httpd%20XSS%20by%20design/) a small technique of achieving XSS on `httpd` when the attacker can't control the file extension. However, unlike that prior method, which involved creating files with no name or only dots to bypass extension assignage, this new trick doesn't depend on the absense of the `X-Content-Type-Options: nosniff` header. Complicating the other writeup, making these nice to add to our toolbox.
16+
17+
# Details
18+
19+
The core of this technique lies in how [Apache httpd's](https://httpd.apache.org/) [mod_mime](https://httpd.apache.org/docs/2.4/mod/mod_mime.html) module determines a file's `Content-Type`. Typically, `mod_mime` guesses the content type based on the file's extension. If the `X-Content-Type-Options: nosniff` header is present, browsers are instructed not to "sniff" the content type and will default to `text/plain` when an `Content-Type` isn't set. However, a closer look at the `mod_mime` documentation reveals an interesting behavior:
20+
21+
<img src="/img/blogs/fortinet/2/mod_mime_doc.png" style="width: 100%;"/>
22+
23+
Files can have [multiple extensions](https://httpd.apache.org/docs/2.4/mod/mod_mime.html#multipleext "multiple extensions"), with a priority given to the last one. For example, these file extensions will correspond to the following content-types:
24+
25+
| File Extension | mod_mime Content-Type |
26+
| -------- | ------- |
27+
|Filename.**html** | text/html |
28+
|Filename.**gif** | image/gif |
29+
|Filename.gif.**html** | text/html |
30+
|Filename.**unknown** | |
31+
|Filename.unknown.**html** | text/html |
32+
|Filename.**html**.unknown | text/html |
33+
34+
# The Attack Scenario
35+
Armed with this knowledge, in a scenario where an attacker has the ability to upload a file, but can't control the extension. If the extension doesn't correlate to any content type in `mod_mime` (for example `.abc`), all the attacker would need to do is to add `.html` to the filename (`filename.html.abc`). When Apache serves this file, `mod_mime` will process the multiple extensions, recognize `.html` as the last and most significant one since `.abc` doesnt cererlate ot anything, and serve the file with `Content-Type: text/html`, resulting in stored XSS. This technique might also be used to bypass some server-side validation that only permits specific file types.
36+
37+
# References
38+
* [CVE-2025-22859 blog](https://yaniv-git.github.io/2025/06/29/Caught%20in%20the%20FortiNet:%20How%20Attackers%20Can%20Exploit%20FortiClient%20to%20Compromise%20Organizations%202/#From-Limited-File-Write-to-XSS-CVE-2025-22859)
39+
* [X-Content-Type-Options](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options)
40+
* [Content-Type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type)
41+
* [mod_mime](https://httpd.apache.org/docs/2.4/mod/mod_mime.html)
42+
* [Tweet](https://x.com/YNizry/status/1940053407127007587)

source/_posts/Caught in the FortiNet: How Attackers Can Exploit FortiClient to Compromise Organizations 3.md

Lines changed: 218 additions & 0 deletions
Large diffs are not rendered by default.
Loading
402 KB
Loading
420 KB
Loading

source/img/blogs/fortinet/3/race.gif

531 KB
Loading
251 KB
Loading
75.2 KB
Loading

0 commit comments

Comments
 (0)