".$row["filename"]." filetype:".$r。一张图片也能SQL注入?( 二 )。" />

一张图片也能SQL注入?( 二 )

if(MySQLi_num_rows($result)>0){while($row=mysqli_fetch_assoc($result)){echo "<li>";echo "filename:<a href=https://www.isolves.com/it/aq/sj/2022-03-11/'".$row["filepath"]."'>".$row["filename"]." filetype:".$row["filetype"]."
";} echo "";}
这一段代码就比较简单,就是将存储的文件名列出来
那么造成注入的罪魁祸首就是这一行代码:
$filetype = (new finfo)->file($_FILES['file']['tmp_name']);这里使用finfo::file方法,这个方法在PHP手册介绍如下,但是并不是很详细,后半部分将会对这一个函数进行底层代码跟踪分析 。

一张图片也能SQL注入?

文章插图
 
finfo::file底层跟进finfo::file方法在ext/fileinfo/fileinfo.c中
其中finfo中有这么几个方法:
class finfo{/** @alias finfo_open */public function __construct(int $flags = FILEINFO_NONE, ?string $magic_database = null) {}/*** @param resource|null $context* @return string|false* @alias finfo_file*/public function file(string $filename, int $flags = FILEINFO_NONE, $context = null) {}/*** @param resource|null $context* @return string|false* @alias finfo_buffer*/public function buffer(string $string, int $flags = FILEINFO_NONE, $context = null) {}/*** @return bool* @alias finfo_set_flags*/public function set_flags(int $flags) {}}我们跟进finfo::file
我们在下方图中位置下三个断点
一张图片也能SQL注入?

文章插图
 
将前面题目拉下来的源文件放在一个文件夹中进行调试
源文件如下:
将upload.php修改如下
$filename = md5(md5(rand(1,10000))).".zip";$filetype = (new finfo)->file($_FILES['file']['tmp_name']);$filepath = "upload/".$filename;var_dump($filetype);die(0);开启调试,上传注入文件后程序便会停止在断点处
第一个断点处,421行,这个断点处调用包装器打开资源并返回流对象
一张图片也能SQL注入?

文章插图
 
第二个断点处,431-432行,进入magic_stream,单步调试,监视ms以及ret_val
进入file_or_stream
一张图片也能SQL注入?

文章插图
 
直接看file_or_stream的return
一张图片也能SQL注入?

文章插图
 
跟进file_getbuffer,下方其实就可以看到ms->o.buf已经获取到了exif信息
一张图片也能SQL注入?

文章插图
 
后面的就不继续跟进了,但是可以肯定的是file()方法可以检测图片的EXIF信息,并且作为题目中的filetype传入数据库造成注入
$filetype = (new finfo)->file($_FILES['file']['tmp_name']);总结虽然是几年前的trick,但是每弄清楚一个trick,攻击面就会更广 。
参考文章
  • CTFshow 36D Web Writeup – 颖奇L'Amore (gem-love.com)
  • PHP回顾之流 - SegmentFault 思否

【一张图片也能SQL注入?】


推荐阅读