Full Report
Answerdev is a question-and-answer platform written in Go. The original post is at here but the translation is what I used above since I don't read anything besides English. Using can upload pictures. When they upload a file, it's stored on the file system. When it's retrieved, a static resource server called gin will grab the resource and send it back. To prevent vulnerabilities for running JavaScript or something else on the site, the Content-Type is set based upon the file extension. This prevents many attacks, since the Content-Type changes how the browser will handle the file. The MIME standard library is used for the returning the Content-Type given a file extension. This relies upon a set of mapping files stored in a few different locations, but commonly added by other packages. If there is not an extension-to-type mapping, then this is simply ignored. Why is this bad? MIME Sniffing is the browser trying to guess the type of the response based upon the content of the page. Without a Content-Type and X-Content-Type-Options: nosniff, this functionality occurs. If we can find a file that isn't in the mapping that can be uploaded by the server, we can confuse the browser to upload HTML, leading to XSS! Oddly enough, this bug was discovered because of a difference between production and development usage of a docker container. In the production version, a minimized version of Alpine was used. So, the MIME types were not present in the container, leading to a tiff value to be used as an XSS payload. An example of this can be found at here for client side attacks. Although this is a weird use case for MIME sniffing on the server-side, it is an interesting vulnerability that is still valid in today's world.
Analysis Summary
# Vulnerability: Server-Side MIME Sniffing in Answerdev via Alpine Containerization
## CVE Details
- **CVE ID:** CVE-2023-0105
- **CVSS Score:** 5.4 (Medium)
- **CWE:** CWE-79 (Improper Neutralization of Input During Web Page Generation / Cross-site Scripting), CWE-430 (Deployment of Wrong MIME Type)
## Affected Systems
- **Products:** Answerdev/Answer (Q&A platform written in Go)
- **Versions:** Affected versions prior to v1.0.5
- **Configurations:** Systems deployed using **minimalist Docker images (e.g., Alpine Linux)** or environments lacking a comprehensive system MIME-info database (`mime.types`).
## Vulnerability Description
The vulnerability arises from a discrepancy between how the Go `mime` standard library handles file extensions and how browsers perform MIME sniffing.
1. **Dependency on Host OS:** The Go `mime.TypeByExtension()` function relies on a small built-in table and external system files (like `/etc/mime.types`).
2. **Missing Mappings:** In minimal container environments like Alpine, these external mapping files are often absent. Consequently, many common extensions (e.g., `.bmp`, `.tiff`, `.ico`) return an empty string for their Content-Type.
3. **Server-Side Logic:** When the Gin-based static server receives an empty string from the MIME lookup, it defaults to server-side MIME sniffing of the file content.
4. **MIME Sniffing Conflict:** If a user uploads a file with a permitted extension (e.g., `.bmp`) containing HTML/JavaScript, and the server fails to find a MIME mapping, the server (and subsequently the browser) may identify the content as `text/html`. Because the application does not set `X-Content-Type-Options: nosniff`, the browser executes the payload, leading to **Stored Cross-Site Scripting (XSS)**.
## Exploitation
- **Status:** PoC available; identified in the wild/via security audits.
- **Complexity:** Low
- **Attack Vector:** Network (Remote) - An attacker uploads a malicious file via the image upload feature.
## Impact
- **Confidentiality:** Medium (Session hijacking via XSS)
- **Integrity:** Medium (Unauthorized actions on behalf of users)
- **Availability:** Low
## Remediation
### Patches
- **Answerdev v1.0.5+:** The vendor has released patches to address file handling and header configurations.
### Workarounds
- **Header Injection:** Manually configure the web server or proxy (Nginx/Apache) to send `X-Content-Type-Options: nosniff` for all static assets.
- **Environment Enrichment:** Add the `mailcap` or `mime-types` package to the Dockerfile to provide the necessary `/etc/mime.types` file:
`RUN apk add --no-cache mailcap`
- **Manual Mapping:** Hardcode a comprehensive MIME map within the Go application using `mime.AddExtensionType()`.
## Detection
- **Indicators of Compromise:** Presence of image files (.bmp, .tiff, .tif) in the upload directory containing `<script>` tags or HTML elements.
- **Detection Methods:**
- Use browser developer tools to check if `Content-Type: text/html` is returned for non-HTML file extensions.
- Scan the environment for the existence of `/etc/mime.types`.
## References
- **Huntr Advisory:** hxxps[://]huntr[.]dev/bounties/366cf8bb-19f6-4388-b089-d0a260efd863/
- **Original Research:** hxxps[://]tttang[.]com/archive/1880/
- **GitHub Repository:** hxxps[://]github[.]com/answerdev/answer