daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

nodejs-express.md (8736B)


      1 ---
      2 title: "NodeJS Express"
      3 section: "Network Services"
      4 sectionSlug: "network-services-pentesting"
      5 sourcePath: "src/network-services-pentesting/pentesting-web/nodejs-express.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/network-services-pentesting/pentesting-web/nodejs-express.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: false
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # NodeJS Express
     14 
     15 ## Quick Fingerprinting
     16 
     17 Useful Express indicators during recon:
     18 
     19 - `X-Powered-By: Express` or stack traces mentioning `express`, `body-parser`, `qs`, `cookie-parser`, `express-session`, or `finalhandler`
     20 - Cookies prefixed with `s:` (signed cookie) or `j:` (JSON cookie)
     21 - Session cookies such as `connect.sid`
     22 - Hidden form fields or query parameters such as `_method=PUT` / `_method=DELETE`
     23 - Error pages leaking `Cannot GET /path`, `Cannot POST /path`, `Unexpected token` in `body-parser`, or `URIError` during query parsing
     24 
     25 When you confirm Express, focus on the middleware chain, because most interesting bugs come from parsers, proxy trust, session handling, and method-tunneling rather than from the framework core itself.
     26 
     27 ## Cookie Signature
     28 
     29 The `cookie-monster` tool automates testing candidate Express.js cookie secrets and re-signing cookie values once a secret is known.<sup>[[3]](#references)</sup>
     30 
     31 Express commonly exposes two useful cookie formats:
     32 
     33 - `s:<value>.<sig>` signed cookies handled by `cookie-parser` or `express-session`
     34 - `j:<json>` JSON cookies that are automatically parsed by `cookie-parser`
     35 
     36 If `cookie-parser` receives a signed cookie and its signature is invalid, the unsigned value becomes `false` rather than the attacker-supplied string. When the application supplies an array of secrets, verification tries each secret in order, so retained rotation keys continue to validate old signatures.<sup>[[4]](#references)</sup>
     37 
     38 ### Single cookie with a specific name
     39 
     40 ```bash
     41 cookie-monster -c eyJmb28iOiJiYXIifQ== -s LVMVxSNPdU_G8S3mkjlShUD78s4 -n session
     42 ```
     43 
     44 ### Custom wordlist
     45 
     46 ```bash
     47 cookie-monster -c eyJmb28iOiJiYXIifQ== -s LVMVxSNPdU_G8S3mkjlShUD78s4 -w custom.lst
     48 ```
     49 
     50 ### Test multiple cookies using batch mode
     51 
     52 ```bash
     53 cookie-monster -b -f cookies.json
     54 ```
     55 
     56 ### Test multiple cookies using batch mode with a custom wordlist
     57 
     58 ```bash
     59 cookie-monster -b -f cookies.json -w custom.lst
     60 ```
     61 
     62 ### Encode and sign a new cookie
     63 
     64 If you know the secret you can sign the cookie.
     65 
     66 ```bash
     67 cookie-monster -e -f new_cookie.json -k secret
     68 ```
     69 
     70 ## Query String and URL-Encoded Parser Abuse
     71 
     72 Express targets often become interesting when they parse attacker-controlled keys into nested objects.
     73 
     74 - `req.query` can be configured with different parsers, including `qs`
     75 - `express.urlencoded({ extended: true })` uses `qs`-style parsing for `application/x-www-form-urlencoded`
     76 - Nested parsing unlocks object injection, mass assignment, NoSQL injection, and prototype pollution chains if the parsed object is merged into application state<sup>[[2]](#references)</sup>
     77 
     78 Practical payloads to try:
     79 
     80 ```bash
     81 # Mass assignment style probe
     82 curl 'https://target.example/profile?role=admin&isAdmin=true'
     83 
     84 # Nested object / qs syntax
     85 curl 'https://target.example/search?user[role]=admin&filters[name][$ne]=x'
     86 
     87 # URL-encoded body against express.urlencoded({ extended: true })
     88 curl -X POST 'https://target.example/api/update'   -H 'Content-Type: application/x-www-form-urlencoded'   --data 'profile[role]=admin&filters[$ne]=x'
     89 ```
     90 
     91 If the app reflects or persists the resulting object, pivot into the dedicated pages for exploitation details:
     92 
     93 [Mass Assignment Cwe 915](/hacktricks/pentesting-web/mass-assignment-cwe-915)
     94 
     95 [Express Prototype Pollution Gadgets](/hacktricks/pentesting-web/deserialization/nodejs-proto-prototype-pollution/express-prototype-pollution-gadgets)
     96 
     97 Extra tests that are worth sending against Express specifically:
     98 
     99 - Deep nesting to look for parser limits, timeouts, or 400/413 differences
    100 - Duplicate keys to see whether the app keeps the first value, the last one, or an array
    101 - Bracket syntax such as `a[b][c]=1`, dotted syntax such as `a.b=1`, and `__proto__` / `constructor[prototype]` payloads
    102 
    103 ## `trust proxy` Abuse
    104 
    105 If the app uses `app.set("trust proxy", true)` or trusts too many hops, Express will derive security-relevant values from forwarding headers. If the reverse proxy does not overwrite them, a client can spoof them directly.<sup>[[1]](#references)</sup>
    106 
    107 That affects:
    108 
    109 - `req.hostname` via `X-Forwarded-Host`
    110 - `req.protocol` via `X-Forwarded-Proto`
    111 - `req.ip` / `req.ips` via `X-Forwarded-For`
    112 
    113 This is useful for:
    114 
    115 - Password reset poisoning and absolute URL poisoning
    116 - Bypassing IP-based allowlists, rate limits, or audit trails
    117 - Influencing `secure` cookie handling and HTTPS-only logic in apps that key off `req.protocol`
    118 - Poisoning redirects or cacheable responses when the app templates absolute links with forwarded host/proto headers
    119 
    120 ```http
    121 POST /reset-password HTTP/1.1
    122 Host: target.example
    123 X-Forwarded-Host: attacker.example
    124 X-Forwarded-Proto: https
    125 X-Forwarded-For: 127.0.0.1
    126 Content-Type: application/json
    127 
    128 {"email":"victim@target.example"}
    129 ```
    130 
    131 Check whether generated links, redirect locations, logs, or access-control decisions now use attacker-supplied values.
    132 
    133 Related pages:
    134 
    135 [Reset Password](/hacktricks/pentesting-web/reset-password)
    136 
    137 [Readme](/hacktricks/pentesting-web/cache-deception/overview)
    138 
    139 ## `express-session` Testing Notes
    140 
    141 Common Express deployments use `express-session`, which signs the session identifier cookie but stores the real state server-side.
    142 
    143 Useful checks:
    144 
    145 - **Session fixation**: authenticate with a pre-login cookie and verify whether the SID stays the same after login
    146 - **Weak secret rotation**: some deployments verify cookies with an array of old secrets, so previously valid signatures may continue to work
    147 - **`saveUninitialized: true`**: the application stores new but unmodified sessions, increasing anonymous session volume. It does not create fixation by itself, but it supplies pre-authentication SIDs that make a failure to rotate the SID easier to test.
    148 - **`MemoryStore`** is intentionally unsuitable for production: it leaks memory under many workloads, does not scale beyond one process, and loses sessions on restart.<sup>[[5]](#references)</sup>
    149 
    150 A practical fixation workflow:
    151 
    152 1. Obtain an anonymous session cookie from the target.
    153 2. Send that cookie to a victim or authenticate with it yourself.
    154 3. Check whether login binds the authenticated state to the existing SID.
    155 4. If it does, replay the same cookie in a separate browser session.
    156 
    157 If the application does not rotate or regenerate the session after authentication, test whether authenticated state remains bound to a SID chosen or learned before login. `req.session.regenerate()` is the middleware's built-in rotation primitive.<sup>[[5]](#references)</sup>
    158 
    159 ## Method Override Tunneling
    160 
    161 Some Express apps use `method-override` to tunnel verbs that HTML forms cannot send natively. When enabled, always test whether you can smuggle dangerous methods through a route that the front-end, WAF, or CSRF logic assumed was only `POST`.
    162 
    163 Typical probes:
    164 
    165 ```http
    166 POST /users/42 HTTP/1.1
    167 Host: target.example
    168 X-HTTP-Method-Override: DELETE
    169 Content-Type: application/x-www-form-urlencoded
    170 
    171 confirm=yes
    172 ```
    173 
    174 ```http
    175 POST /users/42?_method=PUT HTTP/1.1
    176 Host: target.example
    177 Content-Type: application/x-www-form-urlencoded
    178 
    179 role=admin
    180 ```
    181 
    182 Interesting impacts:
    183 
    184 - Reaching hidden `PUT` / `PATCH` / `DELETE` routes through a `POST`-only edge control
    185 - Bypassing route-specific middleware that only checks `req.method`
    186 - Triggering state-changing handlers via CSRF when the application validates only the outer request method
    187 
    188 The official `method-override` middleware checks only original `POST` requests by default (`options.methods: ['POST']`), so prioritize `POST` requests with header, body, and query-string override values.<sup>[[6]](#references)</sup>
    189  
    190 ## References
    191 
    192 - [1] [Express behind proxies - Express.js](https://expressjs.com/en/guide/behind-proxies.html)
    193 - [2] [Server-side prototype pollution: Black-box detection without the DoS - PortSwigger Research](https://portswigger.net/research/server-side-prototype-pollution)
    194 - [3] [DigitalInterruption/cookie-monster](https://github.com/DigitalInterruption/cookie-monster)
    195 - [4] [Express.js - cookie-parser middleware](https://expressjs.com/en/resources/middleware/cookie-parser.html)
    196 - [5] [Express.js - express-session middleware](https://expressjs.com/en/resources/middleware/session.html)
    197 - [6] [Express.js - method-override middleware](https://expressjs.com/en/resources/middleware/method-override.html)