0x01 漏洞描述
HTMLy 是一个开源的基于 PHP 的博客平台。它可以让用户创建安全、轻量且功能强大的网站或博客,并且即使在拥有数千篇文章的情况下,也能高效扩展。
该系统存在存储型XSS漏洞,由于xxx.php
文件中的xxx函数
对用户传入的数据没有进行严格过滤,导致用户可以在新建文章时写入恶意的攻击代码,由此触发XSS攻击。
0x02 环境搭建
版本信息
通过phpstudy 进行搭建
php:7.1.9
apache:2.4.39
htmly版本:2.9.9 最新版本
安装htmly
- 也可以直接下载installer.php 进行一键安装,默认下载最新版本
- 下载源码
Release Composer Vendor Update and Improvements · danpros/htmly (github.com) - 将文件夹放入phpstudy的web目录下
C:\phpstudy_pro\WWW
- 根据
README.md
中的步骤,修改htmly的配置文件- 在config文件夹中将example重命名为
config.ini
- 修改
config.ini
,设置siteurl的地址1
2; The URL of your blog.
site.url = "http://htmly:8088/\/" - 在
config/users
的文件夹中,将example重命名为htmly.ini
(填入自己像设置的用户名即可) - 修改
htmly.ini
,填入密码
- 在config文件夹中将example重命名为
- 在phpstudy中创建项目
- 访问
http://htmly:8088/install.php
页面,进行安装 - 成功安装后跳转到该页面
- 访问
http://htmly:8088/login
进入到管理员页面
phpstorm动态调试
参考往期文章,配置动态调试
thinkphp5.0 文件包含漏洞分析-超详细保姆级 - Gryffinbit的思维殿堂 0x03 动态调试章节
0x03 漏洞分析
XSS漏洞原理
跨站脚本攻击XSS通过将恶意得Script代码注入到Web页面中,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户的目的。
漏洞函数
在htmly.php
中,对传入的数据进行了处理
1 | add_content($title, $tag, $url, $content, $user, $draft, $category, 'post', $description, null, $dateTime); |
在对$content
变量进行的定义
1 | $content = from($_REQUEST, 'content'); |
用户传入content数据,经过from函数进行处理并赋值给$content
变量。跟进from函数。这个函数可以从数组中提取单个值或多个值(如果$name
是数组),并且在提取过程中处理换行符和去除空白。
1 | function from($source, $name) |
这个from()
函数的作用是从指定的$source
数组(例如$_REQUEST
)中提取指定键的值,并进行一些处理。以下是对代码的详细解释:
$map = array("\r\n" => "\n", "\r" => "\n");
:- 这是一个映射数组,用于将Windows和Mac风格的换行符(
\r\n
和\r
)转换为Unix风格的换行符(\n
)。这有助于统一处理不同操作系统下的换行符,确保数据一致性。
- 这是一个映射数组,用于将Windows和Mac风格的换行符(
if (is_array($name))
:- 如果
$name
是一个数组,函数将遍历这个数组,从$source
中提取每个键的值,并进行处理。
- 如果
$data = array();
:- 如果
$name
是数组,函数会创建一个空数组$data
来存储结果。
- 如果
foreach ($name as $k)
:- 遍历
$name
数组中的每个键$k
。
- 遍历
$data[$k] = isset($source[$k]) ? trim(strtr($source[$k], $map)) : null;
:- 对于每个键
$k
,检查它是否存在于$source
数组中。 - 如果存在,使用
strtr()
函数将换行符替换成\n
,再用trim()
去掉值的首尾空白字符,然后将结果存入$data[$k]
。 - 如果键不存在,将结果设置为
null
。
- 对于每个键
return $data;
:- 如果
$name
是数组,返回处理后的结果数组$data
。
- 如果
return isset($source[$name]) ? trim(strtr($source[$name], $map)) : null;
:- 如果
$name
不是数组,则直接从$source
中获取对应的值,处理后返回。 - 如果键不存在,返回
null
。
- 如果
由于该函数对传入的数据没有进行严格过滤,所以导致了漏洞的存在。
0x04 攻击演示
漏洞点:http://htmly:8088///add/content?type=post
文章内容写入处存在xss
点击xss的文章
触发xss漏洞