@Author:Y4tacker
@time:2021/01/27 11:10 AM.
PDO的ATTR_EMULATE_PREPARES屬性帶來的安全問題
這次的思考來源于我昨天對TP5.0.9進行SQL漏洞復現的時候所引發的思考

當時在PDO的prepare編譯階段報錯直接拋出例外之后,在頁面居然發現sql被執行了!!!

因為我們知道PDO分為三個階段,prepare,bindParam和execute,如下所示
<?php
$dsn = 'mysql:dbname=test;host=localhost;charset=utf8';
$user = 'root';
$password = '123456';
try {
$pdo = new PDO($dsn, $user, $password);
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
$pdo->query('set names utf8');
$sql = "select * from user where uid>? and age>?";
$stat = $pdo->prepare($sql);
$stat->bindParam(4,$id);
$stat->bindParam(10,$name);
$stat->execute();
$arrResult = $stat->fetchAll();php
我們也知道,會在execute執行后才會執行結果,可是我們如果設定了
PDO::ATTR_EMULATE_PREPARES => false,
我們看看官網給的描述
PDO::ATTR_EMULATE_PREPARES啟用或禁用預處理陳述句的模擬, 有些驅動不支持或有限度地支持本地預處理,使用此設定強制PDO總是模擬預處理陳述句(如果為true),或試著使用本地預處理陳述句(如果為false),如果驅動不能成功預處理當前查詢,它將總是回到模擬預處理陳述句上, 需要 bool 型別,
他會在拋出例外的時候同時也執行了sql陳述句,當然為了能拋出例外我們同時也會設定
PDO::ERRMODE_EXCEPTION來拋出例外
下面進行實驗環節,我們利用報錯注入拋出例外,同時我們打開WireShark進行簡單分析
<?php
use think\exception\PDOException;
$dsn = 'mysql:dbname=tptptp;host=localhost;port=3306;charset=utf8';
$user = 'tptptp';
$password = 'tptptp';
$params = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false,
];
try {
$pdo = new PDO($dsn, $user, $password, $params);
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
$sql = "SELECT * FROM `users` WHERE `Id` IN (1,updatexml(0,concat(0xa,@@version),0)) ";
try {
$stat = $pdo->prepare($sql);
}catch (\PDOException $e) {
throw new PDOException($e, $this->config, $this->getLastsql());
}
這里我們進入了發起了prepare的請求包

在response中居然帶了我們的

因此也不難解釋為什么TP拋出例外的時候顯示執行了sql陳述句了,分析完畢
參考鏈接
PDO::setAttribute
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/264442.html
標籤:其他
