PHP mysqli_multi_query 执行多条语句及 web端回显的问题

问题

问题启发于 sqli-labs的42关,堆叠注入。sqli-labs搭建推荐直接使用Docker。
docker run -dt --name sqli-lab -p [PORT]:80 acgpiano/sqli-labs:latest
其中第42关是个堆叠注入的问题。通过post方式来传递参数。但是这关的username输入有mysqli_real_escape_string函数管着,所以注入点在password。最终构造的sql注入语句为
login_user=admin1&login_password=admin1';create table tesst(id INT,name varchar(100)) %23; &mysubmit=Login
当时,我尝试的时候注入语句没有使用create table语句,而是使用的select sleep(5)。既然是堆叠注入就是都当作sql语句来执行,这个语句应该也是可以执行的,页面应该等待5秒再返回才对。但是,事实并不是这样,页面直接返回了。接下来就是找出为什么是这样的结果。

解决

数据库直接执行注入的语句

使用 Navicat 连接数据库,然后直接执行注入的语句。如下图所示。

语句都成功执行了。说明多条语句执行以及sleep()对于我这个数据库来讲都是没有问题的。

然后就猜测是不是注入语句被什么给过滤处理了。

查看数据库的查询记录,并在终端中直接执行注入语句

上一个博客讲了mysql配置记录查询语句的功能以及查看执行语句历史的方法,这里就不赘述了。直接查看历史记录。

上图中红色圈起来的就是从web界面注入的语句。可以看到输入的语句没有被过滤什么的,成功到了数据库中被执行。但是sleep(5)并没有在web端体现出来,为什么呢?

下面尝试在终端中直接执行注入的sql语句。

上图中的sql语句中最后的单引号'是与PHP程序中原查询拼接导致的。原PHP程序中的查询是这样写的$sql = "SELECT * FROM users WHERE username='$username' and password='$password'";。在PHP程序的查询中,这个单引号'会被注释符#注释掉,所以没有影响。但是在终端中,需要分号;作为语句结束,所以可以看到在终端中执行的截图中,我有输入了一个分号;来表示语句的结束。

上面的过程验证了,注入的sql语句是可以到达数据库中并被成功执行的。

对比源代码分析。

对比代码

sqli-labs对应的源代码地址为 https://github.com/Audi-1/sqli-labs/blob/master/Less-42/login.php 。其中的关键查询语句如下。

$sql = "SELECT * FROM users WHERE username='$username' and password='$password'"; if (@mysqli_multi_query($con1, $sql)) { /* store first result set */ if($result = @mysqli_store_result($con1)) { if($row = @mysqli_fetch_row($result)) { if ($row[1]) { return $row[1]; } else { return 0; } } } else { echo '<font size="5" color= "#FFFF00">'; print_r(mysqli_error($con1)); echo "</font>"; } }

为了便于对比,我将sqli-labs中的源码简化成了下面这样的,并将其命名为test2.php

<?php $con=mysqli_connect("localhost","test","test","test"); // Check connection if (mysqli_connect_errno($con)) { echo "Failed to connect to MySQL: " . mysqli_connect_error(); } $sql = "SELECT * FROM users WHERE id=1;"; //$sql .= "SELECT * FROM users where id=2"; $sql .= "select sleep(20);"; $sql .= "select sleep(30);"; /* execute multi query */ if (mysqli_multi_query($con, $sql)) { /* store first result set */ if($result = mysqli_store_result($con)) { if($row = mysqli_fetch_row($result)) { printf("%s\n",$row[0]); printf("==================\n"); } } } ?>

然后从菜鸟教程找了一份同样使用mysqli_multi_query()的例子,并命名为test1.php来做对比,内容如下所示。

<?php $con=mysqli_connect("localhost","test","test","test"); // 检测链接 if (mysqli_connect_errno($con)) { echo "连接到 MySQL 失败: " . mysqli_connect_error(); } $sql = "SELECT * FROM users where id=1;"; //$sql .= "SELECT * FROM users where id=2"; $sql .= "select sleep(20);"; $sql .= "select sleep(30);"; // 执行多个 SQL 语句 if (mysqli_multi_query($con,$sql)) { do { // 存储第一个结果集 if ($result=mysqli_store_result($con)) { while ($row=mysqli_fetch_row($result)) { printf("%s\n",$row[0]); printf("==================\n"); } mysqli_free_result($result); } } while (mysqli_next_result($con)); } mysqli_close($con); ?>

搭建测试环境

测试机 ubuntu 18.04
测试这种小脚本,也没必要搭建web环境,直接安装好php的环境,在终端中执行就行了。安装phpphp-mysql的命令如下。

sudo apt install php7.2-cli sudo apt install php-mysql

切换到包含test1.php的目录下,脚本执行方式为php test1.php

源代码分析

  1. 上面test2.php中的代码,虽然有多条sql查询,但是只取了一次结果。而test1.php则是通过循环依次取多条sql语句的结果。
  2. 上面两份代码中都分别包含3条查询。第一条是正常的查询,第二和第三条分别是睡眠20和30秒

执行结果

先执行php test1.php,结果如下:

可以看到,依次输出了对应的结果,查询数据库的历史记录,也可以看到都依次成功执行了,没啥问题。

然后执行php test2.php,结果如下:

然后再查询数据库的执行记录,如下图所示

虽然这个程序只取了第一条语句的结果,但是所有三条查询均执行了。而且,在程序刚执行第二个查询,也就是select sleep(20)的时候,迅速查看数据库的历史记录如下

可以看到第三条查询sleep(30)还未执行。现在基本可以得出结论了。

结论

mysqli_multi_query中的多条sql查询(由分号'分隔),无论是否取结果,取几个结果,都将提交给数据库执行,并且是顺序执行,执行完一条再执行下一条。

这个sqli-labs第42关使用sleep(5)进行堆叠注入没反应的原因也清楚了。代码中只取了第一条语句的结果,第二条虽然执行了,但是web并没有取它的结果,也就没有等待直接返回了。


__EOF__

本文作者TheTai
本文链接https://www.cnblogs.com/TheTai/p/14378068.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   TheTai  阅读(265)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示