PHP PDO Flaw Allows Attackers to Inject Malicious SQL Commands
A critical vulnerability in PHP’s widely-used PDO (PHP Data Objects) library has been discovered that enables attackers to inject malicious SQL commands even when developers implement prepared statements correctly.
The security flaw, revealed through analysis of a DownUnderCTF capture-the-flag challenge, exploits weaknesses in PDO’s SQL parser and affects millions of web applications worldwide.
Technical Overview of the Vulnerability
The vulnerability stems from PDO’s default behavior of emulating prepared statements rather than using native database-prepared statements.
PDO implements its own SQL parser to handle bound parameters, but this parser can be tricked into misinterpreting user input as bound parameters in contexts where they shouldn’t be treated as such.
The attack technique involves exploiting scenarios where user input appears directly in prepared statements, particularly for column and table names that cannot be bound as parameters. Consider this seemingly secure code example:
prepare("SELECT $col FROM fruit WHERE name = ?");
$stmt->execute([$_GET['name']]);
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
Attackers can exploit this by injecting specially crafted payloads containing null bytes and question marks.
When a payload like ?# is used, PDO’s parser incorrectly identifies the question mark as a bound parameter, leading to SQL injection.
The attack works by manipulating PDO’s parsing logic through carefully constructed payloads.
For instance, using the payload http://localhost:8000/?name=x FROM (SELECT table_name AS ‘x from information_schema.tables)y;#&col=?#%00` can successfully extract database schema information.
The vulnerability affects different database systems differently. MySQL is vulnerable by default unless developers explicitly disable PDO::ATTR_EMULATE_PREPARES.
PostgreSQL becomes vulnerable when emulation is enabled, while SQLite remains protected due to its handling of null bytes.
Older PHP versions present even greater risks. PHP 8.3 and earlier versions used a single SQL parser for all database dialects, making them significantly more vulnerable to these attacks.
Security researchers recommend several defensive measures. Developers should disable PDO::ATTR_EMULATE_PREPARES when possible and ensure they’re running the latest PHP version (8.4 or newer). Additionally, applications should prevent null bytes from appearing in SQL queries.
The discovery highlights the importance of never mixing manually constructed SQL fragments with PDO bindings when using query emulation, as this combination creates significant security risks.
This vulnerability underscores the critical need for thorough security testing and the potential dangers lurking in seemingly secure code implementations.
Get Free Ultimate SOC Requirements Checklist Before you build, buy, or switch your SOC for 2025 - Download Now
Source link