在CISP PTE考试中有一道INSERT型SQL注入题目,考试过程中我找到注入点、也获取了部分数据,但是最终未能成功拿到key。
这篇文章将对题目环境进分析复现,并进行拓展思考。

环境复现

使用关键词cisp "insert article1"可以找到题目的题解,使用AI模型可以快速根据题解生成题目环境:

请根据这篇writeup文章 https://www.cnblogs.com/Summer-123/p/16925457.html
设计一个基于Docker环境的INSERT型SQL注入练习靶场,数据库采用MySQL,后端使用PHP语言
靶场环境是一个博客发表系统,提供如下功能:用户注册、登录;发表博客;查看博客。
在发表博客功能上留存SQL注入点用来练习,其余功能的SQL语句均使用预处理避免SQL注入。

要求如下:
1. 只将web应用暴露在本地的38080端口,其余端口不暴露;
2. 输出一个生成系统环境的busybox bash脚本

在大模型输出的基础上进行调整,即可得到可用的源代码。

解法分析

题目环境是一个博客发表系统,提供如下功能:

  1. 用户注册、登录;
  2. 发表博客;
  3. 查看博客。

发表博客位置存在SQL注入漏洞点,程序将博客标题和博客内容两个字段拼接进SQL语句。
程序虽然对SQL注入里常用的注释符(--#)进行了过滤,但可以被绕过。

解法1:绕过过滤

在下面过滤代码中先后对两种注释符进行了过滤,而且后处理的过滤符可以包含在前一种过滤符中。因此如果用户输入的字符为-#-时,前面的过滤对用户输入不起作用,而后一种则帮助攻击者去除掉了干扰字符、达到了注释后续语句的目的。

//代码过滤规则
function filter_sql(string $sql): string
{
while (strstr($sql,'--')){
$sql = str_replace("--","",$sql);
}
while (strstr($sql,'#')){
$sql = str_replace("#","",$sql);
}
return $sql;
}

解法2:补全语句

按照MySQL的手册[1]INSERT ... VALUES语句可以使用英文逗号隔开多行数据,一次性插入数据库。
根据题目给出的表结构提示,通过如下方式可以补全SQL语句,完成注入:

博客标题: title1
博客内容: content1','[username]'), ('FAKE-UUID-2', SQL_COMMAND_2, 'content2

解法3:多行注释+特殊用户名

解法参考这篇博文[2],由于系统在注册用户处未对用户名的特殊字符进行过滤,因此可以注册恶意的用户名对SQL语句进行补全。

按照下面内容注册用户、发表博客文章之后,SQL注入回显会在user1用户的博文列表里显示。

注册用户: */,'user1
博客标题: title1', SQL_COMMAND_2 /*
博客内容: 1

这种解法的关键在于多行注释/* ... */,特殊用户名用来闭合多行注释。

后续思考

注意点

  1. 按照一般业务逻辑,因为博客正文内容长度要超过博客标题,所以应该优先考虑在博客正文处回显。

PostgreSQL、SQLite数据库

因为PostgreSQL和SQLite数据库默认支持使用||对字符串进行拼接(MySQL需要单独设置SQL模式[3]),所以这两种数据库的INSERT型注入攻击实现要比MySQL容易些。
可以直接使用 ' || (SELECT key from key || '将flag信息拼接在输出中。

insert with select

sqlmap

对于手工测试已知存在漏洞的SQL注入点,可以借助sqlmap工具进行自动化测试。

合法授权情况下,怎样使用SQLmap对存在INSERT型注入的PHP应用、MariaDB数据库进行渗透测试?
注入点在title参数,以a1aa',(SQL_QUERY),'user1');-#- -为例,将SQL_QUERY替换为sql语句(其余结构不能变化)、提交之后follow 302跳转正常得到回显。

sqlmap -r publish.txt -p title --prefix="a1aa',(" --suffix="),'user1');-#- -" --dbms=mysql --batch --sql-query="SELECT version()" --dbs --flush-session

SQL注入辅助理解工具

人工想象注入时恶意输入对SQL语句语义的修改不直观,可以借助AI编写小工具。

请用纯js编写一个SQL注入辅助理解网页工具:
1. 包含三个部分:用户输入区,代码拼接区和SQL语句区
2. 代码拼接区(可编辑修改)定义拼接语句,拼接语句里用户输入的变量用$开头的变量进行展示;
i. 使用SQL语法高亮对拼接语句进行高亮展示。
ii. 修改拼接语句时,如果修改涉及某几个变量,则用户输入区内对应的变量清零;
iii. 修改如果不涉及变量定义,则用户输入区不用清零。
iiii. 变量替换时,先将$变量名替换成类似于`__SQLVAR_[name]__`的形式,在进行替换,不要使用字符串替换
3. 用户输入区域(可编辑修改)按照代码拼接区拼接语句的定义自动生成对应的变量;
4. SQL语句区(不可编辑)对用户输入进行拼接并展示处理后结果,SQL语句区的语法进行如下高亮显示:
i. 对SQL语句关键字进行彩色字体显示;
ii. 按照SQL语义对单双引号进行闭合区域进行高亮,对注释区域(`/* ... */` 之间、#之后、--之后)进行灰色显示
iii. 将用户输入使用粗体字体显示;

对大语言模型的网页输出进行简单测试:

LLM ChatGPT Gemini Grok
a变量重定义b内容不清空 OK OK OK
内容替换正常 OK OK ~OK
注释正确显示 NOK OK OK
引号与注释正常处理 NOK NOK OK
网页设计 NOK OK ~OK