0x01起因
原题在http://hackinglab.cn/中的http://lab1.xseclab.com/code1_9f44bab1964d2f959cf509763980e156/
点开后查看源码,得到php源码如下
<?php
include "config.php";
if(isset($_GET['userid']) && isset($_GET['pwd'])){
$strsql="select * from `user` where userid=".intval($_GET['userid'])." and password='".md5($_GET['pwd'], true) ."'";
$conn=mysql_connect($dbhost,$username,$pwd);
mysql_select_db($db,$conn);
$result=mysql_query($strsql);
print_r(mysql_error());
$row=mysql_fetch_array($result);
mysql_close($conn);
echo " <pre>";
print_r($row);
echo " </pre>";
if($row!=null){
echo "Flag: ".$flag;
}
}
else{
echo "PLEASE LOGINT!";
}
echo " <noscript>";
echo file_get_contents(__FILE__);
根据题目提示.据说哈希后的密码是不能产生注入的
应该是加密后的哈希反而存在注入,有意思。
0x02学习
通过查阅资料可知php的md5函数
md5(string,raw)
参数 | 描述 |
string | 必需。规定要计算的字符串。 |
raw | 可选。规定十六进制或二进制输出格式: · TRUE - 原始 16 字符二进制格式 · FALSE - 默认。32 字符十六进制数 |
我们来实际测试下
Md51.php
<?php
$str =”sfsrc”;
echo md5($str);
Md52.php
<?php
$str=”sfsrc”;
echo md5($str,true);
php Md51.php >Md51.txt
php Md52.php>Md52.txt
将Md51.txt Md52.txt分别用16进制编辑器打开
可以清楚地看到md5($str)直接输出我们日常见到的32位MD5哈希串。
而md5($str,true)输出了一串二进制,并且二进制的16进制表示刚好等同于上面的32位字符串,
我们继续看下md5哈希算法的原理
网络上搜索到以下资料
MD5加密字符串实例
现以字符串"jklmn”为例。
该字符串在内存中表示为:6A 6B 6C 6D 6E(从左到右为低地址到高地址,后同),信息长度为40 bits, 即0x28。
对其填充,填充至448位,即56字节。结果为:
6A 6B 6C 6D 6E 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
剩下64位,即8字节填充填充前信息位长,按小端字节序填充剩下的8字节,结果为。
6A 6B 6C 6D 6E 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 28 00 00 00 00 00 00 00
(64字节,512 bits)
初始化A、B、C、D四个变量。
将这64字节填充后数据分成16个小组(程序中对应为16个数组),即:
M0:6A 6B 6C 6D (这是内存中的顺序,按照小端字节序原则,对应数组M(0)的值为0x6D6C6B6A,下同)
M1:6E 80 00 00
M2:00 00 00 00
.....
M14:28 00 00 00
M15:00 00 00 00
经过"3. 分组数据处理”后,a、b、c、d值分别为0xD8523F60、0x837E0144、0x517726CA、0x1BB6E5FE
在内存中为a:60 3F 52 D8
b:44 01 7E 83
c:CA 26 77 51
d:FE E5 B6 1B
a、b、c、d按内存顺序输出即为最终结果:603F52D844017E83CA267751FEE5B61B。这就是字符串"jklmn”的MD5值
由此恍然大悟,MD5函数哈希的结果本是一串二进制(md5($str,true)),日常我们看到的32位哈希串是二进制数据的16进制表示而已(md5($str))
0X03尝试攻击
通过前面的知识
$strsql="select * from `user` where userid=".intval($_GET['userid'])." and password='".md5($_GET['pwd'], true) ."'";
这一句如果生成的哈希串以0x27开头,将成功闭合password=’的单引号,从而形成SQL注入,
如果生成的哈希串以0x276f72312f2a即’or1/*开头则将成功地绕过密码检测,欺骗程序得到flag
小编想的是大量生成随机字符串并哈希 筛选出生成哈希以276f72312f2a开头的字符串,还未成功,网络上已有人用ffifdyop这个密码解题成功,对应生成的哈希是276f722736c95d99e921722cf9ed621c,转成字符串为'or'6 <trash>。