
CakePHP 5.4.2 - उच्च - रिमोट - SQLi - WindowExpression रेंज/फ्रेम ऑफसेट SQL में जोड़े गए
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · cakephp-window-sqli
राइट-अप: https://abraxaslabs.tech/research/cakephp-window-sqli
वर्ग: SQLi पहुँच: रिमोट
CakePHP 5.4.2 (887b641) - Cake Software Foundation
CVE-2026-79752 ने FunctionsBuilder के cast / extract / dateAdd को ensureSimpleString() के साथ बंद कर दिया। WindowExpression::range() और frame() उस फ़िक्स में शामिल नहीं थे। rows() और groups() ?int लेते हैं। range() अभी भी एक स्ट्रिंग लेता है। buildOffsetSql ऑफ़सेट, फ़्रेम प्रकार, और PRECEDING / FOLLOWING को OVER में जोड़ देता है। बाइंडर का उपयोग तब तक नहीं होता जब तक ऑफ़सेट पहले से ExpressionInterface न हो।
जो ऐप अनुरोध डेटा को func()->count('*')->over()->range($start, $end) में अग्रेषित करता है, वह कॉलर की स्ट्रिंग को RANGE BETWEEN में बिना बाइंड और बिना कोट के डाल देता है।
| ID | अभी तक कोई CVE नहीं |
| वर्ग | SQLi |
| पहुँच | रिमोट (वह ऐप जो अनुरोध डेटा को range() / frame() में अग्रेषित करता है) |
| CWE | CWE-89 |
| CVSS | उच्च: 8.1 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N |
| उत्पाद | CakePHP (cakephp/database) |
| प्रभावित | 5.4.2 (887b641de9f7aba06071f98f17edcbc573cbcf63) |
| प्रमाणीकरण | वह एप्लिकेशन जो क्वेरी/फ़ॉर्म डेटा को ->over()->range($start, $end) / frame() में अग्रेषित करता है |
| लाइसेंस | GNU Affero GPL v3.0 |
| लैब | केवल 127.0.0.1 |
जो उपयोगकर्ता ऐप द्वारा अग्रेषित विंडो बाउंड सेट कर सकता है (एनालिटिक्स "पिछले N दिन", एक रिपोर्ट बिल्डर), वह OVER क्लॉज़ को अतिरिक्त SQL में बदल देता है।
| विशेषाधिकार | विधि / सिंक | प्रकार | लैब-प्रमाणित या अनुमानित |
|---|---|---|---|
OVER (RANGE BETWEEN ...) में SQL अंश जोड़ना | GET /?mode=range&start= को AggregateExpression::range($start, $end) / WindowExpression::frame() में | संकलित SQL की अखंडता | लैब-प्रमाणित। संकलित SQL है RANGE BETWEEN 1) /* CAKEPHP-WINDOW-SQLI-WITNESS */ -- PRECEDING जिसमें खाली बाइंडर है |
| ऐप के DB उपयोगकर्ता के रूप में पंक्तियाँ पढ़ना या संशोधित करना | वही क्वेरी, निष्पादित | DB की अखंडता / रेकॉन | स्प्लाइस से अनुमानित। यह लैब केवल-संकलन है |
| उसी तरह फ़्रेम प्रकार या दिशा बदलना | frame($type, $offset, $direction, ...) उन स्ट्रिंग्स को भी जोड़ता है | संकलित SQL की अखंडता | sql() / buildOffsetSql() से अनुमानित। लैब ने range() का उपयोग किया |
rows() / groups() को उसी तरह तोड़ना | टाइप्ड ?int | बंद | लैब-प्रमाणित बंद। rows(3) है ROWS BETWEEN 3 PRECEDING, न कोट किया गया, न बाइंड किया गया |
इस पिन पर बंद: FunctionsBuilder cast / extract / dateAdd / jsonValue (CVE-2026-79752 / CVE-2026-77635); Query::limit / offset (टाइप्ड int)। डिफ़ॉल्ट cakephp/app क्वेरी-स्ट्रिंग डेटा के साथ range() को कॉल नहीं करता। बचा हुआ हिस्सा प्रलेखित विंडो API है। स्केलेटन ऐप पर अनप्रमाणित RCE नहीं। शेल नहीं।
वही पिन शेष: collate SQLi, attachment CRLF, cache unserialize।
मैंने 2026 FunctionsBuilder SQLi GHSAs के बाद cakephp/cakephp 5.4.2 को पिन किया। उस टैग पर दस हंट्स। CSRF / FormProtection, View LFI, BodyParser XXE, mass assignment, helper XSS, और trustProxy के बिना clientIp() इस बार में खाली लौटे। WindowExpressionTest::testRange अभी भी यह दावा करता है:
$w = (new WindowExpression())->range("'1 day'", "'10 days'");
buildOffsetSql कभी भी स्ट्रिंग ऑफ़सेट को बाइंड नहीं करता:
protected function buildOffsetSql(
ValueBinder $binder,
ExpressionInterface|string|int|null $offset,
string $direction,
): string {
if ($offset === 0) {
return 'CURRENT ROW';
}
if ($offset instanceof ExpressionInterface) {
$offset = $offset->sql($binder);
}
return sprintf('%s %s', $offset ?? 'UNBOUNDED', $direction);
}
$binder का उपयोग तब तक नहीं होता जब तक कि offset पहले से ही एक ExpressionInterface न हो।
पहले से दर्ज गलत मोड़: rows() को छिद्र मानना (यह int टाइप्ड है); यह दावा करना कि स्टॉक cakephp/app इसे किसी सार्वजनिक फ़ॉर्म पर उजागर करता है; SQLite में इंजेक्ट किए गए SQL को oracle के रूप में निष्पादित करना (POC-READY केवल-कंपाइल है); एक रिवर्स शेल। नाटक।
python3 cakephp-window-sqli-Abraxas-Labs.py
or
cd lab
./run.sh
केवल http://127.0.0.1:19440 को लक्षित करें। छोटा PHP ऐप, cakephp/database 5.4.2, SQLite :memory:। GET /?mode=range&start= को स्ट्रिंग के रूप में range() में पास किया जाता है। GET /?mode=rows&n=3 int नियंत्रण है।
SUCCESS cakephp-window-sqli pin=5.4.2 range-raw=yes rows-numeric=yes bound=no quoted=no CAKEPHP-WINDOW-SQLI-WITNESS
संकलित SQL का IOC:
SELECT (COUNT(*) OVER (RANGE BETWEEN 1) /* CAKEPHP-WINDOW-SQLI-WITNESS */ -- PRECEDING AND CURRENT ROW)) AS n FROM sqlite_master
नियंत्रण:
SELECT (COUNT(*) OVER (ROWS BETWEEN 3 PRECEDING AND CURRENT ROW)) AS n FROM sqlite_master
संख्यात्मक ऑफ़सेट को बाइंड करें। फ़्रेम प्रकार (RANGE / ROWS / GROUPS) और दिशा (PRECEDING / FOLLOWING) को अनुमत-सूची में रखें। इंटरवल स्ट्रिंग्स के लिए, उन्हें कोट करें या ExpressionInterface आवश्यक करें। एक परीक्षण जोड़ें कि गैर-int range() ऑफ़सेट एक प्लेसहोल्डर या एक कोटेड लिटरल बने, कच्चा SQL नहीं।
887b641de9f7aba06071f98f17edcbc573cbcf63)WindowExpression.php · AggregateExpression.phpGNU Affero GPL v3.0. देखें LICENSE। केवल लूपबैक लैब। कोई वारंटी नहीं।