抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

0x01 漏洞描述

HTMLy 是一个开源的基于 PHP 的博客平台。它可以让用户创建安全、轻量且功能强大的网站或博客,并且即使在拥有数千篇文章的情况下,也能高效扩展​。
该系统存在存储型XSS漏洞,由于xxx.php 文件中的xxx函数 对用户传入的数据没有进行严格过滤,导致用户可以在新建文章时写入恶意的攻击代码,由此触发XSS攻击。

0x02 环境搭建

版本信息

通过phpstudy 进行搭建
php:7.1.9
apache:2.4.39
htmly版本:2.9.9 最新版本

安装htmly

  1. 也可以直接下载installer.php 进行一键安装,默认下载最新版本
  2. 下载源码
    Release Composer Vendor Update and Improvements · danpros/htmly (github.com)
  3. 将文件夹放入phpstudy的web目录下 C:\phpstudy_pro\WWW
  4. 根据README.md中的步骤,修改htmly的配置文件
    1. 在config文件夹中将example重命名为config.ini
    2. 修改config.ini,设置siteurl的地址
      1
      2
      ; The URL of your blog.
      site.url = "http://htmly:8088/\/"
    3. config/users 的文件夹中,将example重命名为htmly.ini(填入自己像设置的用户名即可)
    4. 修改htmly.ini,填入密码
  5. 在phpstudy中创建项目
  6. 访问http://htmly:8088/install.php页面,进行安装
  7. 成功安装后跳转到该页面
  8. 访问 http://htmly:8088/login 进入到管理员页面

phpstorm动态调试

参考往期文章,配置动态调试
thinkphp5.0 文件包含漏洞分析-超详细保姆级 - Gryffinbit的思维殿堂 0x03 动态调试章节

0x03 漏洞分析

XSS漏洞原理

跨站脚本攻击XSS通过将恶意得Script代码注入到Web页面中,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户的目的。

XSS漏洞(全网最详细)-CSDN博客

漏洞函数

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
2
3
4
5
6
7
8
9
10
11
function from($source, $name)  
{
$map = array("\r\n" => "\n", "\r" => "\n");
if (is_array($name)) {
$data = array();
foreach ($name as $k)
$data[$k] = isset($source[$k]) ? trim(strtr($source[$k], $map)) : null;
return $data;
}
return isset($source[$name]) ? trim(strtr($source[$name], $map)) : null;
}

这个from()函数的作用是从指定的$source数组(例如$_REQUEST)中提取指定键的值,并进行一些处理。以下是对代码的详细解释:

  1. $map = array("\r\n" => "\n", "\r" => "\n");:

    • 这是一个映射数组,用于将Windows和Mac风格的换行符(\r\n\r)转换为Unix风格的换行符(\n)。这有助于统一处理不同操作系统下的换行符,确保数据一致性。
  2. if (is_array($name)):

    • 如果$name是一个数组,函数将遍历这个数组,从$source中提取每个键的值,并进行处理。
  3. $data = array();:

    • 如果$name是数组,函数会创建一个空数组$data来存储结果。
  4. foreach ($name as $k):

    • 遍历$name数组中的每个键$k
  5. $data[$k] = isset($source[$k]) ? trim(strtr($source[$k], $map)) : null;:

    • 对于每个键$k,检查它是否存在于$source数组中。
    • 如果存在,使用strtr()函数将换行符替换成\n,再用trim()去掉值的首尾空白字符,然后将结果存入$data[$k]
    • 如果键不存在,将结果设置为null
  6. return $data;:

    • 如果$name是数组,返回处理后的结果数组$data
  7. return isset($source[$name]) ? trim(strtr($source[$name], $map)) : null;:

    • 如果$name不是数组,则直接从$source中获取对应的值,处理后返回。
    • 如果键不存在,返回null

由于该函数对传入的数据没有进行严格过滤,所以导致了漏洞的存在。

0x04 攻击演示

漏洞点http://htmly:8088///add/content?type=post
文章内容写入处存在xss

点击xss的文章

触发xss漏洞

评论