一次小破站JS代码审计出XSS漏洞思路学习

Posted RDrug

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一次小破站JS代码审计出XSS漏洞思路学习相关的知识,希望对你有一定的参考价值。

  • 今天看了小破站一个大佬的分析,感觉思路很有意思,感兴趣的xdm可以到大佬视频下提供的链接进行测试(传送门)这类社交平台的XSS漏洞利用起来其实危害是特别大的,利用XSS能在社交平台上呈现蠕虫式的扩散,大部分资产其实很容易存在这样的问题,也是一种挖高危的好思路。
  • 由于up主视频分析比较概括,自己吧源码拉下来再研究和复现一遍,加深印象。
  • 最后,JS看来还是得再学一下,学的东西都还给老师了qaq,代码还是理解得不透彻,不过暂且记录下来,有什么问题欢迎各路大佬来指正。

一、私信功能JS的部分代码:

<script>
function test()
    var any_url = 'https?:\\\\/\\\\/(www\\\\.)?[-a-zA-Z0-9@:%._\\\\+~#=]1,256\\\\.[a-zA-Z0-9()]1,6\\\\b([-a-zA-Z0-9()@:%_\\\\+.~#?&//=]*)|bilibili://[\\\\w!@#$&\\\\*=\\\\./?~_%\\\\-]*';
    var white_list = JSON.parse('["^https?://[-A-Za-z0-9.]*(bilibili.com|biligame.com|acg.tv|b23.tv|(bili2233|bili23|bili33|bili22).cn|dl.hdslb.com)(/[A-Za-z0-9!@#$&\\\\\\\\*=\\\\\\\\./?~_%\\\\\\\\-]*)*$","^bilibili://[\\\\\\\\w!@#$&\\\\\\\\*=\\\\\\\\./?~_%\\\\\\\\-]*"]');
    var msgRegex = 
        any_url:any_url,
        white_list:white_list,
        black_list:[]
    
    var g = null;
    var p = document.getElementById("in").value;
     //sort((function(t, e))是比值函数结合sort()函数以字符长度大到小排序,具体解释:https://blog.51cto.com/u_15076212/4265209
    var m, f, h = new RegExp(any_url,"g"), g = (p.match(h) || []).sort((function(t, e) 
        return e.length - t.length
    
    )), v = null === (m = msgRegex) || void 0 === m ? void 0 : m.white_list.filter((function(t) 
        return -1 === t.indexOf("bilibili://")
    
    )), b = new RegExp(v.join("|")), y = new RegExp(null === (f = msgRegex) || void 0 === f ? void 0 : f.black_list.join("|"));
    g.forEach((function(e, n) 
        var i, s;
        console.log(e);
        !b.test(e) || null !== (i = msgRegex) && void 0 !== i && null !== (s = i.black_list) && void 0 !== s && s.length && y.test(e) || (p = p.split(e).join("bilibili-msg-link-placeholder-".concat(n)))
    
    )),
    (function()
        //url是bilibili://开头的提示移动端打开
        p = p.replace(/(?:bilibili:\\/\\/)(?:[/.$*?~=#!%@&\\-\\w]*)?/g,function(t)
            return '\\n              <span data-href="'.concat(t, '">\\n                【请在移动端上打开链接】\\n              </span>\\n            ')
        )
    )(),
    //p = u(d, p).join(""),
    g.forEach((function(t, e) 
        //造成漏洞的关键部分:满足条件的字符串拼接bilibili-msg-link-placeholder-(序号)
        p = p.split("bilibili-msg-link-placeholder-".concat(e)).join('\\n              <a href="'.concat(t, '" target="_blank" class="dynamic-link">\\n                <i class="bp-icon-font icon-link"></i> 网页链接\\n              </a>\\n            '))
    
    )),
    document.getElementById("output_html").value = p;
    console.log(document.getElementById("output"));
    document.getElementById("output").contentWindow.document.documentElement.innerHTML=p;
    console.log(p);
;
</script>

chatgpt对这一部分代码解释:

二、分析原理

  1. 首先要理解的是js代码里面的”bilibili-msg-link-placeholder-".concat(e)部分,这部分称为占位符,也可以理解为一个便于后面进行输出的数组变量,代码中看出只要符合url格式的字符串都会被归入占位符数组中,concat(e)可以简单理解为当存在多个符合条件的url的时候按短到长的顺序生成序号1,2,3…,

最后再满足white_list正则的占位符进行拼接并输出
显示效果就是这样

  1. 当攻击者故意在URL里面插入”bilibili-msg-link-placeholder-".concat(e)这样的字符串时就有可能导致XSS的发生。

比如发送两条符合条件的url:
https://www.bilibili.com/bilibili-msg-link-placeholder-1
https://www.baidu.com/οnmοuseοver=console.log(99)//

此时占位符的排序是由url长到短排序的,所以
bilibili-msg-link-placeholder-1的值是https://www.baidu.com/οnmοuseοver=console.log(99)//,但是由于格式不符合white_list,最后不会进行超链接的拼接
bilibili-msg-link-placeholder-0的值是https://www.bilibili.com/bilibili-msg-link-placeholder-1,格式符合white_list,最后会进行超链接的拼接

bilibili-msg-link-placeholder-0拼接的结果为

  <a href="https://www.bilibili.com/
  <a href="https://www.baidu.com/onmouseover=console.log(99)//" target="_blank" class="dynamic-link">
    <i class="bp-icon-font icon-link"></i> 网页链接
  </a>
" target="_blank" class="dynamic-link">
    <i class="bp-icon-font icon-link"></i> 网页链接
  </a>

最后效果:
可以看到控制台console.log(99)显示出来了。

三、一些疑问

最后的结果到html为什么拼接部分的斜线会转成等号导致漏洞最终生效的?
不太理解。。。滚回去补JS了

记一次小有成就的代码审计

一 前言

前不久逛cnvd的时候看到一款小众CMS,大型CMS咱也审计不出啥漏洞呀,复盘了下上面的漏洞,仔细看了下,又发现了一些其他的问题,小众cms可以跟一下具体的流程,了解下漏洞发生的原因,用来练手还是可以的。

二 反射型XSS漏洞

其实像这样小众的CMS出现XSS漏洞是比较常见的,而他出现XSS的地方也算是经常遇到的地方,报错时直接把输入的信息在没有任何安全措施的情况下进行了原样输出从而触发了XSS漏洞。
拿到该CMS的第一步首先简单看下看下该CMS的URL路由情况,方便定位相关函数

$t = @$_GET['t'] ? $_GET['t'] : "sys";
$n = @$_GET['n'] ? $_GET['n'] : "index";
$c = @$_GET['c'] ? $_GET['c'] : "index";
$a = @$_GET['a'] ? $_GET['a'] : "index";
define("L_TYPE", $t);
define("L_NAME", $n);
define("L_CLASS", $c);
define("L_MODULE", "admin");
define("L_ACTION", "do{$a}");
require_once '../core/route.php';

包含了/core/route.php函数,跟进去看一下

定义了一些常量,在最后调用了load类中的module函数, 该函数位于\\core\\class\\load.class.php中

然后调用相关函数,该函数会查看传入的文件是否存在

如果文件不存在会将错误信息传入类LCMS的X函数,该函数位于\\core\\class\\lcms.class.php中,该函数会调用template函数生成模板进行错误的输出

然后生成报错信息模板

在进行输出的时候并没有看到对错误进行的任何过滤行为,直接进行了输出,触发了反射型XSS

基本上涉及到的这种错误输出都没有过滤,都存在反射型xss漏洞

三 存储型XSS漏洞

在通过Seay代码审计工具自动扫描的时候发现了该CMS获取客户端IP的方式存在漏洞,可以进行伪造,并且后台记录了登录成功的IP,但是只会记住登录成功的用户的IP,所以只能通过拿下一个低权限的账号的时候才有可能触发该存储XSS。
注册一个低权限的账号,然后在登录的时候进行客户端IP伪造,发现可以触发存储型XSS。

管理员登录系统,点击用户中心—用户管理处即可触发储存型XSS漏洞

定位到IP伪造的相关函数,函数位于\\app\\sys\\login\\admin\\index.class.php中,获取客户端的IP然后进行数据库的更新

而CLIENT_IP,根据全局变量可知为LCMS::IP(),跟进到相关函数,函数位于\\core\\class\\lcms.class.php中,根据函数可知攻击者可以在客户端伪造IP

最后将从客户端获取到的IP更新到了数据库中

当我们点击用户中心的时候,查看调用的函数\\app\\sys\\user\\admin\\admin.class.php

从数据库中取数据然后进行模板的渲染输出,触发XSS漏洞

四 任意文件删除

在删除备份SQL文件的时候

跟进到相关函数,函数位于\\app\\sys\\backup\\admin\\database.class.php中

case 'del':
 $file = PATH_WEB . "backup/data/{$_L['form']['name']}";
 if (is_file($file)) {
 delfile($file);
 ajaxout(1, "删除成功");
 } else {
 ajaxout(0, "文件不存在");
 }
 break;

跟进到delfile函数,该函数会调用path_absolute函数,该函数在 \\core\\function\\file.func.php中存在过滤

function path_absolute($path)
{
 $path = PATH_WEB . str_replace([
 "../", "./", PATH_WEB,
 ], "", $path);
 $path = str_replace("\\/", "\\\\", $path);
 return is_dir($path) ? path_standard($path) : $path;
}

过滤为…/ ./,在windows系统下可以通过…\\绕过

五 任意文件上传

很少看到有这么干的CMS了,看到的时候还是有些吃惊,有人说这是正常功能,看了写这个CMS的上传他的本意应该还是上传非执行性脚本的意思,初衷并不是希望你可以上传php文件。
在设置中心—>安全性能—>格式白名单添加php

然后在设置中心—>后台设置—>后台LOGO直接上传php文件即可

上传函数位于\\core\\class\\upload.class.php中,只要php是允许的后缀名即可实现文件上传getshell

打印下保存的文件白名单

跟进下相关函数,位于app\\sys\\config\\admin\\admin.class.php中的dosafe函数,该函数会将用户添加的白名单保存在全局变量中,在校验白名单时从全局变量中取值导致触发任意文件上传漏洞

六 SQL注入漏洞

这个CMS应该是全部都没有进行安全检测的,基本上和数据库交互的地方都存在SQL注入吧,举一个例子吧,多了都是同类。
在用户管理—>添加用户处

payload: admin1'and(select*from(select+sleep(1))a)='

通过更改sleep时间可以看到sleep函数生效了,执行时间相差了大概1倍,通过查看SQL语句执行记录可知,sleep函数被拼接到了sql语句中,并执行了sql语句

根据url跟进到漏洞函数,函数位于\\app\\sys\\user\\admin\\admin.class.php中的doiframe。具体代码如下,在没有经过过滤的情况下直接获取了数据

L 是 全 局 的 变 量 , 包 含 系 统 所 有 的 变 量 数 据 , 打 印 下 可 以 看 到 输 出 了 网 站 的 所 有 参 数 , 可 以 看 到 _L 是全局的变量,包含系统所有的变量数据,打印下可以看到输出了网站的所有参数,可以看到 L,_L包含了系统所有的变量数据

name值为拼接了恶意sql语句的内容,该值直接拼接到了SQL语句中去执行从而触发了sql注入漏洞

我是一名网安渗透工程师,不仅仅研究渗透,当然,你想学习网络安全的话可以学习网络安全视频、src技术文档、工具包、应急响应和代码审计等,分享给大家

【资料领取】

七 总结

也没啥亮点吧,很平常的cms流程跟踪一下就得了

以上是关于一次小破站JS代码审计出XSS漏洞思路学习的主要内容,如果未能解决你的问题,请参考以下文章

从某cms的xss漏洞来学习代码审计

小皮1-click漏洞的代码审计学习笔记

insert后面value可控的盲注(第一次代码审计出漏洞)

PHP代码审计 | 记一次CMS代码审计

通过代码审计找出网站中的XSS漏洞实战

实战解析看我是如何在XSS漏洞实战中做到“擒贼先擒王”!