You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/network-services-pentesting/pentesting-web/nodejs-express.md
+152-1Lines changed: 152 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,10 +2,29 @@
2
2
3
3
{{#include ../../banners/hacktricks-training.md}}
4
4
5
+
## Quick Fingerprinting
6
+
7
+
Useful Express indicators during recon:
8
+
9
+
-`X-Powered-By: Express` or stack traces mentioning `express`, `body-parser`, `qs`, `cookie-parser`, `express-session`, or `finalhandler`
10
+
- Cookies prefixed with `s:` (signed cookie) or `j:` (JSON cookie)
11
+
- Session cookies such as `connect.sid`
12
+
- Hidden form fields or query parameters such as `_method=PUT` / `_method=DELETE`
13
+
- Error pages leaking `Cannot GET /path`, `Cannot POST /path`, `Unexpected token` in `body-parser`, or `URIError` during query parsing
14
+
15
+
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.
16
+
5
17
## Cookie Signature
6
18
7
19
The tool [https://github.com/DigitalInterruption/cookie-monster](https://github.com/DigitalInterruption/cookie-monster) is a utility for automating the testing and re-signing of Express.js cookie secrets.
8
20
21
+
Express commonly exposes two useful cookie formats:
22
+
23
+
-`s:<value>.<sig>` signed cookies handled by `cookie-parser` or `express-session`
24
+
-`j:<json>` JSON cookies that are automatically parsed by `cookie-parser`
25
+
26
+
If `cookie-parser` receives a signed cookie and the signature is invalid, the value becomes `false` instead of the tampered value. If the application accepts an array of secrets, old secrets may still verify existing cookies after rotation.
Express targets often become interesting when they parse attacker-controlled keys into nested objects.
63
+
64
+
-`req.query` can be configured with different parsers, including `qs`
65
+
-`express.urlencoded({ extended: true })` uses `qs`-style parsing for `application/x-www-form-urlencoded`
66
+
- Nested parsing unlocks object injection, mass assignment, NoSQL injection, and prototype pollution chains if the parsed object is merged into application state
Extra tests that are worth sending against Express specifically:
92
+
93
+
- Deep nesting to look for parser limits, timeouts, or 400/413 differences
94
+
- Duplicate keys to see whether the app keeps the first value, the last one, or an array
95
+
- Bracket syntax such as `a[b][c]=1`, dotted syntax such as `a.b=1`, and `__proto__` / `constructor[prototype]` payloads
96
+
97
+
## `trust proxy` Abuse
98
+
99
+
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.
100
+
101
+
That affects:
102
+
103
+
-`req.hostname` via `X-Forwarded-Host`
104
+
-`req.protocol` via `X-Forwarded-Proto`
105
+
-`req.ip` / `req.ips` via `X-Forwarded-For`
106
+
107
+
This is useful for:
108
+
109
+
- Password reset poisoning and absolute URL poisoning
110
+
- Bypassing IP-based allowlists, rate limits, or audit trails
111
+
- Influencing `secure` cookie handling and HTTPS-only logic in apps that key off `req.protocol`
112
+
- Poisoning redirects or cacheable responses when the app templates absolute links with forwarded host/proto headers
113
+
114
+
```http
115
+
POST /reset-password HTTP/1.1
116
+
Host: target.example
117
+
X-Forwarded-Host: attacker.example
118
+
X-Forwarded-Proto: https
119
+
X-Forwarded-For: 127.0.0.1
120
+
Content-Type: application/json
121
+
122
+
{"email":"victim@target.example"}
123
+
```
124
+
125
+
Check whether generated links, redirect locations, logs, or access-control decisions now use attacker-supplied values.
126
+
127
+
Related pages:
128
+
129
+
{{#ref}}
130
+
../../pentesting-web/reset-password.md
131
+
{{#endref}}
132
+
133
+
{{#ref}}
134
+
../../pentesting-web/cache-deception/README.md
135
+
{{#endref}}
136
+
137
+
## `express-session` Testing Notes
138
+
139
+
Common Express deployments use `express-session`, which signs the session identifier cookie but stores the real state server-side.
140
+
141
+
Useful checks:
142
+
143
+
-**Session fixation**: authenticate with a pre-login cookie and verify whether the SID stays the same after login
144
+
-**Weak secret rotation**: some deployments verify cookies with an array of old secrets, so previously valid signatures may continue to work
145
+
-**`saveUninitialized: true`**: the application issues pre-auth sessions to anonymous users, which makes fixation easier and increases session surface for brute-force or cache analysis
146
+
-**`MemoryStore`** in production usually indicates weak operational maturity and unstable session behavior during restarts
147
+
148
+
A practical fixation workflow:
149
+
150
+
1. Obtain an anonymous session cookie from the target.
151
+
2. Send that cookie to a victim or authenticate with it yourself.
152
+
3. Check whether login binds the authenticated state to the existing SID.
153
+
4. If it does, replay the same cookie in a separate browser session.
154
+
155
+
If the app does not call `req.session.regenerate()` after authentication, fixation is often still possible.
156
+
157
+
## Method Override Tunneling
158
+
159
+
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`.
160
+
161
+
Typical probes:
162
+
163
+
```http
164
+
POST /users/42 HTTP/1.1
165
+
Host: target.example
166
+
X-HTTP-Method-Override: DELETE
167
+
Content-Type: application/x-www-form-urlencoded
168
+
169
+
confirm=yes
170
+
```
171
+
172
+
```http
173
+
POST /users/42?_method=PUT HTTP/1.1
174
+
Host: target.example
175
+
Content-Type: application/x-www-form-urlencoded
176
+
177
+
role=admin
178
+
```
179
+
180
+
Interesting impacts:
181
+
182
+
- Reaching hidden `PUT` / `PATCH` / `DELETE` routes through a `POST`-only edge control
183
+
- Bypassing route-specific middleware that only checks `req.method`
184
+
- Triggering state-changing handlers via CSRF when the application validates only the outer request method
185
+
186
+
By default the middleware usually only overrides `POST`, so prioritize `POST` requests with header, body, and query-string override values.
0 commit comments