常見防禦方法
防禦原理:輸入(解決數字型注入–>即加is_numeric這些去判斷)-------轉義處理(解決字元型注入)-------輸出(解決資料庫報錯)
1.禁止資料庫爆錯資訊洩露件 php.ini檔案中display_errors = Of
2.php内部轉義處理函數
mysql_real_escape_string-->能将特殊字元進行轉義
mysql_escape_string()
magic_quote_gpc()
addslashes->這個函數會加上轉義符
對立函數stripcslashes-->這個函數為删除字元串中存在的\
3.預處理技術進行查詢
利用 m y s q l i − > p r e p a r e 和 mysqli->prepare和 mysqli−>prepare和mysqli_stmt->bind_param函數進行去預處理
<?php
$sql = "select id,username,password from users where id=?";建立一個預定義的對象 ?占位
$mysqli_stmt = $mysqli->prepare($sql);
$id=$_REQUEST['id'];
$mysqli_stmt->bind_param("i",$id);綁定參數
$mysqli_stmt->bind_result($id,$username,$password);綁定結果集
$mysqli_stmt->execute();//執行
while($mysqli_stmt->fetch()){ //取出綁定的結果集
echo $id." ".$username ." ". $password;
}
?>
代碼分析
== 防禦成功的利用這兩個函數即可==
<?php
if (isset($_GET['Submit'])) {
// Retrieve data
$id = $_GET['id'];
$id = stripslashes($id);
$id = mysql_real_escape_string($id);
if (is_numeric($id)){
$getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id'";
$result = mysql_query($getid) or die('<pre>' . mysql_error() . '</pre>' );
$num = mysql_numrows($result);
$i=0;
while ($i < $num) {
$first = mysql_result($result,$i,"first_name");
$last = mysql_result($result,$i,"last_name");
echo '<pre>';
echo 'ID: ' . $id . '<br>First name: ' . $first . '<br>Surname: ' . $last;
echo '</pre>';
$i++;
}
}
}
?>
如果沒有兩個過濾函數
利用方法 http://127.0.0.1/?id=1
特殊案例
1.寬位元組注入思路
1.1 正常寬位元組注入
核心:mysql查詢的時候采用寬位元組方式查詢導緻
<?php
$con = mysql_connect("localhost","root","root");
mysql_query("SET NAMES 'gbk'");
mysql_select_db("test", $con);
$id = isset($_GET['id']) ? addslashes($_GET['id']) : 1;
$query = "SELECT * FROM users WHERE id ='{$id}' ";
?>
是以可以利用
id=%df%27進行去繞
修複方法:
1.将character_set_client設定為binary(二進制)
全部指定為二進制傳輸
mysql_query("SET character_set_connection=gbk, character_set_results=gbk,character_set_client=binary",
$conn);
2.指定php連接配接mysql的字元集
mysql_set_charset('gbk',$conn);
id=mysql_real_escape_string(_GET['id']);
1.2php編碼轉換導緻的寬位元組注入
導緻原理:在字元輸入後進行了編碼轉換進而導緻逃逸單引号
<?php
$con = mysql_connect("localhost","root","root");
mysql_query("SET NAMES 'gbk'");
mysql_select_db("test", $con);
mysql_query("SET character_set_connection=gbk,
character_set_results=gbk,character_set_client=binary", $con);
$id = isset($_GET['id']) ? addslashes($_GET['id']) : 1;
$id=iconv('utf-8','gbk',$id);//和上面相比 添加了這個代碼
$query = "SELECT * FROM users WHERE id ='{$id}' ";
$result = mysql_query($query)or die('<pre>'.mysql_error().'</pre>');
while($row = mysql_fetch_array($result))
{
echo $row['0'] . " " . $row['1'];
echo "<br />";
}
echo "<br/>";
echo $query;
mysql_close($con);
?>
#繞過語句--> 錦',因為utf-8編碼和gbk編碼的不同性質,進而導緻逃逸,溢出導緻sql注入。
2.編碼解碼導緻sql注入
原理:
字元在拼接到sql注入之前進行了解碼
例子
<?php
$con = mysql_connect("localhost","root","root");
mysql_select_db("test", $con);
$id = addslashes($_REQUEST['id']);
$id = urldecode($id);//$id = base64_decode($id);#核心導緻的原因
$query = "SELECT * FROM users WHERE id = '{$id}'";
$result = mysql_query($query)or die('<pre>'.mysql_error().'</pre>');
#繞過方法
id=1%2527union select 1,2,3,4%23
3.二次注入
導緻原理:
1.資料入庫後轉義符号會無
2.而且在次調用了我們插入的内容去查詢
如2018 網鼎杯