项目结构
通过对代码的一个大致结构分析,知道了它的主要功能都是在system目录下。
system目录下有class和template文件,template代表是前端,class是后端处理文件。
同时也可以搞清楚路由的生成规律:
1 | http://localhost:8097/index.php?mod=site&act=manager&do=store&op=display&beid=1 |
这里的act参数代表system文件夹下某个功能点,do代表功能点下具体的PHP文件,op则代表文件走哪个分支。
代码审计
sql注入
在store.php
中有这么一段话。
1 | if($operation=='display') |
该功能对应为店铺查询处。
追溯源头发现$_GP
只是将get,post中的数据进行了一个数组合并,却没有做任何过滤。
1 | $_GP = $_CMS = array(); |
sql语句代入为
1 | "SELECT store.* FROM table('system_store') store where store.`deleted`=0 and store.sname like '%123' limit 0,20" |
直接将我们的数据带入数据库,由此可以判断这里存在sql注入漏洞。
构造payload如下:
1 | sname=123%' and sleep(5) # |
sqlmap也验证成功。
任意文件删除
在database.php下有一个delete分支。
1 | if($operation=='delete') |
由上面的代码可以知道,$_GP[‘id’]函数接收前端的文件名参数后,仅仅只是把文件名base64解密了一下,就直接拼接到删除文件路径下了,没有做任何的过滤限制操作,造成了任意文件删除漏洞。
同时看代码目录可以发现,每次备份数据库后,都会在conifg/data_backup数据库下生成一个随机文件夹。
但是删除代码因为要判断必须是目录,所以只能删除目录及其目录下的文件。
先去代码目录下去新建一个test文件夹。
构造payload如下:
1 | GET /index.php?mod=site&act=manager&do=database&op=delete&id=Li4vdGVzdA==&beid=1 |
同时源码目录也没有test文件夹。
任意文件删除2
common.inc.php文件中,还有一个file_delete
函数。
1 | function file_delete($file_relative_path) { |
关键点在于只要跳过上面的if条件,进入下面的else条件,就可以进行任意文件删除。而if条件是关于一个叫做system_isnetattach的东西。
找了很久都不知道这个到底是什么东西,翻译出来叫做附件,看了网上的wp才知道system_isnetattach
是设置图片压缩比例。
那么接下来我们到了else环节,else环节的代码一目了然。
现在我们需要找到file_delete
函数调用的地方。可以发现是在system/eshop/core/mobile/util/uploader.php
里面。
先去源码目录创建一个新的文件test.txt
由于利用的参数在baijiacms-master/system/eshop/core/mobile/util/uploader.php文件的upload分支下,参数名为file。所以直接构造url为:http://localhost:8097/index.php?mod=mobile&act=uploader&op=post&do=util&m=eshop&op=remove&file=../test.txt
删除成功。
我也没搞懂怎么找到这个路由的。
任意命令执行
在http://localhost:8097/index.php?mod=site&act=weixin&do=setting&beid=1
中有一个上传微信验证文件的选项。
使用burp可以抓包到里面的路由为
根据对应路由,找到代码是
同时在数据包中,发现传入的文件参数名称为:weixin_verify_file。
发现在setting文件中有相关描述。
大致的意思是先判断文件后缀名是不是txt格式,然后用file_save函数处理文件,并且file_save函数中参数file[‘name’]就是上传的文件的名字:&whoami&.txt。
然后再file_save函数当中,传进来了五个参数
file_full_path里面有我们上传的文件名&whoami&.txt
。
而其中最重要的是该方法中调用了system函数,其中也会把我们的file_full_path参数带进去,我们的&whoami$.txt恰巧可以通过&(与)的分割,来进行命令执行。
任意文件写入
在system/public/class/web/file.php
下面发现了以下分支。
1 | if ($do == 'fetch') { |
而其中调用的函数fetch_net_file_upload
函数,发现此函数中使用了file_get_contents函数获取文件,但是并没有进行任何过滤。
总结
太菜了,后头基本上是按照网上师傅的wp照在在做,但是任意命令执行这个漏洞确实是打开了我的视野。还有就是不知道他们是怎么做到精准找到php路由的,太菜了太菜了。