固原市网站建设_网站建设公司_搜索功能_seo优化
2026/1/12 16:32:26 网站建设 项目流程

JavaScript 文件分析与漏洞挖掘指南

前言

Javascript (.js) 文件一般存储的是客户端代码,Javascript 文件可帮助网站执行某些功能,例如监视单击某个按钮的时间,或者当用户将鼠标移到图像上,甚至代表用户发出请求(例如检索信息)时。有时开发人员可以混淆他们的 javascript 代码,使人无法正常阅读,但是大多数类型的混淆是可以反混淆的;如果你是一个漏洞赏金猎人,你应该花一些时间从中寻找宝藏。如果运气好, 可能会发现严重程度较高的漏洞。


怎么找 JS

1. 手动查找

右键单击所在的页面并单击“查看源代码”,然后开始在 HTML 中查找.js。如果是手动,那么这是首选方法,因为您会注意到某些.js文件仅包含你所在的特定端点的代码,它可能包含你不知道的存在的新的 api 接口。

2. 使用 Burp Suite 专业版

如果使用的是 Burp Suite 专业版,在Target > sitemap下,右键点击感兴趣的站点,选择Engagement tools > Find scripts。使用此特性,你可以导出该应用程序中的所有脚本内容。

3. 使用 waybackurls

这是由英国著名白帽子 tomnomnom 开发的一个工具:https://github.com/tomnomnom/waybackurls

这个工具的主要逻辑是让你在 https://archive.org/web/ (这个网站可以理解为数字图书馆, 你可以查找到相对应网站的所有历史网页) 这个网站里面去查找某个目标网站的所有历史数据。

使用方法:

webbackurls target.com|grep"\.js"|uniq|sort

验证 JS 文件

使用 Wayback Machine 可能会导致误报,所以,在收集了 JavaScript 文件的 url 列表之后,我们需要检查这个 js 文件是否真的还存在。

使用 curl 快速检查:

catjs_files_url_list.txt|parallel -j50 -qcurl-w'Status:%{http_code}\t Size:%{size_download}\t %{url_effective}\n'-o /dev/null -sk

使用 hakcheckurl:

# 安装goinstallgithub.com/hakluke/hakcheckurl@latest# 使用catlyftgalactic-js-urls.txt|hakcheckurl

其它相关工具

当然还有其他的一些工具, 这里简单列一下他们的链接, 有兴趣的读者可以自行去研究研究:

  • https://github.com/003random/getJS
  • https://github.com/jobertabma/relative-url-extractor
  • https://github.com/0xsha/GoLinkFinder
  • gau - https://github.com/lc/gau
  • linkfinder - https://github.com/GerbenJavado/LinkFinder
  • getSrc - https://github.com/m4ll0k/Bug-Bounty-Toolz/blob/master/getsrc.py
  • SecretFinder - https://github.com/m4ll0k/SecretFinder
  • antiburl - https://github.com/tomnomnom/hacks/tree/master/anti-burl
  • antiburl.py - https://github.com/m4ll0k/Bug-Bounty-Toolz/blob/master/antiburl.py
  • ffuf - https://github.com/ffuf/ffuf
  • getJswords.py - https://github.com/m4ll0k/Bug-Bounty-Toolz/blob/master/getjswords.py
  • availableForPurchase.py - https://raw.githubusercontent.com/m4ll0k/Bug-Bounty-Toolz/master/availableForPurchase.py
  • jsbeautify.py - https://github.com/m4ll0k/Bug-Bounty-Toolz/blob/master/jsbeautify.py
  • collector.py - https://github.com/m4ll0k/Bug-Bounty-Toolz/blob/master/collector.py

JS 美化

大多数时候,我们收集的 JavaScript 文件都是经过压缩、混淆的。

  • 压缩工具 (UglifyJS): 这是一个压缩 JS 代码的工具,它也可以作为 npm 包使用。
    • https://github.com/mishoo/UglifyJS
  • 解压缩/美化工具 (JS Beautifier):
    • https://github.com/beautify-web/js-beautify

其他的相关工具如下:

  • https://beautifier.io/
  • https://github.com/geeksonsecurity/illuminatejs
  • https://github.com/mindedsecurity/JStillery
  • https://lelinhtinh.github.io/de4js/

JS 文件中需要去找的关键信息

1. JS 危险函数

  1. 将字符串当做代码去执行的三个函数

    eval("alert(1)")
    setTimeout("alert(1)",1000)
    // 就是下面这么写Function("alert(1)")()
  2. innerHTML 函数
    如果你发现了这个函数,这意味着如果没有进行适当的处理,XSS 漏洞可能在向你招手, 即使经过了处理,试着看能不能绕过。

    • React 中就有一个和 innerHTML 差不多的函数叫做dangerouslytSetInnerHTML,这个函数也是咱们的重点关注对象。
    • 还有 Angular 中的bypassSecurityTrustX,还有咱们熟悉的eval函数。
  3. Postmessage 函数
    最好先去看看它的官方文档。一旦了解了与 postMessage 相关的可能的安全问题,就可以在 JavaScript 文件中查找实现。在消息发送方,寻找window.postMessage并在接收方寻找监听器window.addEventListener

    // Postmessage 有如下几种发送与监听的方式 // 1. 从父窗口往子窗口发送消息 // 父窗口<body><h1>父窗口</h1><iframeid="childFrame"src="getMessage.html"frameborder="0"></iframe>// 目标子窗口<button>发送</button>// 点击即可触发发送<script>constsendPostmessage=document.querySelector('button');sendPostmessage.addEventListener('click',function(){constiframe=document.getElementById('childFrame');iframe.contentWindow.postMessage('<img src=x onerror="alert(1)">','*');// 通过iframe往iframe引入的子窗口发送postmessage消息});</script></body>// 子窗口<body><h1>子窗口</h1><script>window.addEventListener('message',function(event){document.querySelector('h1').innerHTML=event.data;// 通过在window中注册message事件监听postmessage消息,当有postmessage消息往这个子窗口发送消息时,触发事件,执行回调函数,将发送的消息写入到h1标签。如果开发者没有对接收消息做过滤,且用innerHTML等危险的DOM操作方法接收了数据,则有可能造成XSS漏洞});</script></body>// 2. 子窗口向父窗口发送消息 // 父窗口<body><h1>父窗口</h1><iframeid="childFrame"src="getMessage.html"frameborder="0"></iframe>// 子窗口<script>window.addEventListener('message',function(event){// 开启message监听if(event.origin!==window.location.origin)return;// 来源验证,event.origin检查接收到的数据的原始url,window.location.origin获取当前窗口的原始url,event.origin !== window.location.origin的意思便是如果来源不是同源的url,则不接收数据document.querySelector('h1').innerHTML=event.data;});</script></body>// 子窗口<body><h1>子窗口</h1><script>window.parent.postMessage('<img src=x onerror="alert(1)">',"*");// iframe加载后自动发送数据,如果父窗口没有做好来源校验,则很有可能会造成相关漏洞</script></body>// 3. 父窗口向弹窗发送消息与接收消息 // 父窗口<body><h1>父窗口</h1><buttonid="openPopup">打开弹窗</button><buttonid="sendPopup">向弹窗发送消息</button><script>letpopup;functionopenPopup(){// 打开弹窗popup=window.open('getMessage.html','popup','width=300,height=200');}functionsendToPopup(){// 向弹窗发送消息if(popup){popup.postMessage('<img src=x onerror="alert(1)">','*');}}letopenpopup=document.querySelector('#openPopup');letsendpopup=document.querySelector('#openPopup');openpopup.addEventListener('click',openPopup);sendpopup.addEventListener('click',sendToPopup);// 接收从弹窗来的消息window.onmessage=function(event){if(event.origin!==window.location.origin)return;document.querySelector('h1').innerHTML=event.data;};</script></body>// 弹窗<body><h1>弹窗</h1><button>Send to Opener</button><script>functionsendToOpener(){// 通过opener向父窗口发送消息window.opener.postMessage('<img src=x onerror="alert(1)">','*');}constsendopener=document.querySelector('button');sendopener.addEventListener('click',sendToOpener);// 接收从opener来的消息,即父窗口向弹窗发送的消息window.addEventListener('message',function(event){document.querySelector('h1').innerHTML=event.data;});</script></body>// 4. 兄弟iframe间通信 // 父窗口<body><h1>父窗口</h1><iframeid="iframe1"src="sibling1.html"frameborder="0"></iframe><iframeid="iframe2"src="sibling2.html"frameborder="0"></iframe><script>constiframe1=document.querySelector('#iframe1');constiframe2=document.querySelector('#iframe2');// 接收来自iframe 的消息,并转发到iframe2window.addEventListener('message',function(event){if(event.origin!==window.location.origin)return;if(event.data.type==='toSibling'){iframe2.contentWindow.postMessage(event.data.message,'*');}elseif(event.data.type==='toSibling1'){iframe1.contentWindow.postMessage(event.data.message,'*');}});</script></body>// 子窗口1<body><h1>子窗口1</h1><button>发送到子窗口2</button><script>functionsendToSibling(){// 发送到父窗口,中转到兄弟window.parent.postMessage({type:'toSibling',message:'<img src=x onerror="alert(1)">'},'*');}constbtn=document.querySelector('button');btn.addEventListener('click',sendToSibling);// 接收回复window.addEventListener('message',function(event){console.log('Sibling 1 received:',event.data);});</script></body>// 子窗口2<body><h1>子窗口2</h1><script>// 接收从中转来的消息window.addEventListener('message',function(event){if(event.origin!==window.location.origin)return;document.querySelector('h1').innerHTML=event.data;});// 回复回兄弟1window.parent.postMessage({type:'toSibling1',message:'Hi Hacker!'},'*');</script></body>
    // postmessage存在的漏洞 1. 第一个漏洞在于“postMessage”函数的第二个参数。此参数指定允许哪个源接收消息。使用通配符“*”表示允许任何源接收消息。由于目标窗口位于不同的源,因此发送方窗口在发送消息时无法知道目标窗口是否在目标源。如果目标窗口是另一个源,则另一个源将接收数据。如果发送的数据是敏感信息,则代表着任何网页都有可能通过iframe引入来接收postmessage发送的数据。 2. 第二个漏洞在于接收端。由于侦听器侦听任何消息,攻击者可以通过从攻击者的源发送消息来欺骗应用程序,这将使接收方认为它从发送方的窗口接收了消息。为避免这种情况,接收方必须使用“message.origin”属性验证消息的来源。如使用正则表达式来验证源。 window.addEventListener("message", function(message){ if(/^http://www.examplesender.com$/.test(message.origin)){ console.log(message.data); } }); 显然,这个正则表达式有缺陷,转义“.”字符很重要,这段代码不仅允许来自“www.examplesender.com”的消息,还允许“wwwaexamplesender.com”、“wwwbexamplesender.com”等消息。 3. 第三个漏洞是DOM XSS,它以应用程序将其视为HTML脚本的方式使用消息,例如: window.addEventListener("message", function(message){ if(/^http://www.examplesender.com$/.test(message.origin)){ document.getElementById("message").innerHTML = message.data; } }); 如果发送方发送的数据是<img src=x onerror="alert(1)">,这将触发XSS // 没有postmessage? 就算应用程序本身不使用postmessage,但许多第三方脚本使用postMessage与第三方服务通信,因此应用程序可能会在开发者不知情的情况下使用postMessage。我们可以使用Chrome Devtools在Sources -> Global Listeners下检查页面是否有已注册的消息监听器(以及哪个脚本注册了它)
    • 相关资料:
      • https://labs.detectify.com/2016/12/08/the-pitfalls-of-postmessage/
      • https://medium.com/techiepedia/what-are-sop-cors-and-ways-to-exploit-it-62a5e02100dc
  4. String.prototype.search()
    一些开发人员使用它来查找一个字符串在另一个字符串中的出现。然而,”.” 在此函数中被视为通配符。

    // String.prototype.search()是javascript中字符串的内置方法,如// let i = "hello world!".search("hello");// 从javascript中查找子串是否存在,不存在则返回-1,一些开发人员使用它来查找一个字符串在另一个字符串中的出现,而有的在进行安全验证时使用,从而造成了验证的绕过if("https://www.baidu.com".search(target.origin)!==-1){eval(target.data);}// 根据MDN,search的参数是一个正则表达式对象,如果参数不是RegExp对象,并且不具有Symbol.search方法,则会使用new RegExp(regexp)将其隐式转换为RegExp。在正则表达式中,点(.)被视为通配符。换句话说,任何数字起源的字符都可以替换为点。攻击者可以利用它并使用特殊域而不是官方域来绕过验证,例如 www.bai.u.com
    • 具体报告:https://hackerone.com/reports/129873
  5. location 相关的几个函数

    • location: http://wooyun.2xss.cc/bug_detail.php?wybug_id=wooyun-2015-099935
    • location.href: http://wooyun.2xss.cc/bug_detail.php?wybug_id=wooyun-2014-062771
    • location.pathname: http://wooyun.2xss.cc/bug_detail.php?wybug_id=wooyun-2012-013059
  6. document.cookie

    • https://hackerone.com/reports/422043
  7. window.name

    window.name是浏览器窗口的一个字符串属性,用于标识或存储窗口的“名称”。它本质上是一个持久化存储机制,类似于sessionStorage,但更简单且跨页面持久。只要窗口不关闭、不刷新,window.name就保持不变。即使导航到新URL,它也不会丢失。如果用window.open打开新窗口,它会继承opener的name。有这几种访问方式:当前窗口window.name,父窗口top.name,iframe中parent.name。 比如有一个页面存在XSS,但利用需要写很多javascript代码,同时该注入点有字符限制。攻击者便可以首先编写钓鱼页: var payload = btoa('完整 exploit 代码'); window.open('https://site.com/users/attacker', payload); // 打开存在XSS的页面 接着存在XSS的页面使用 eval(atob(window.name)) atob对payload进行base64解码,eval执行解码后的JS
    • https://xz.aliyun.com/t/6019
    • https://blog.appsecco.com/automating-discovery-and-exploiting-dom-client-xss-vulnerabilities-using-sboxr-part-3-2ea910dfb429
  8. localStorage 以及 sessionStorage

    • https://infosecwriteups.com/stored-xss-to-organisation-takeover-6eaaa2fdcd5b
    • https://hackerone.com/reports/297968

2. 过时的依赖和框架

从 JS 代码中查找过时的依赖项,可以直接使用retire.js来扫描漏洞。可以在以下链接中找到该项目:

  • https://retirejs.github.io/retire.js/

3. 敏感信息

有时,开发人员会在客户端 JS 代码中留下大量信息,例如密码、API 密钥等硬编码。从 JS 代码中找到这些信息。

例如,AWS 密钥正则表达式可能如下所示:

(?i)aws(.{0,20})?(?-i)['\”][0–9a-zA-Z\/+]{40}['\”]

更多参考工具:

  • https://github.com/l4yton/RegHex
  • https://github.com/securing/DumpsterDiver
  • https://github.com/auth0/repo-supervisor
  • https://github.com/trufflesecurity/truffleHog

相关的漏洞报告:

  • https://hackerone.com/reports/991718
  • https://hackerone.com/reports/983331
  • https://hackerone.com/reports/638635

4. 隐蔽的接口

有时,不是对接口进行模糊测试,而是从 Javascript 文件中查找隐蔽接口会更有效。这些接口可能是一些废弃的服务(开发人员有时忘记删除它)或用户不应该访问的服务(如隐蔽的 API)。如果你找到了,这些隐蔽接口通常比主要的 Web 应用程序更容易受到攻击。

有一些很方便的工具帮助我们从 js 文件中提取这些接口:

  • https://github.com/jobertabma/relative-url-extractor
  • https://github.com/GerbenJavado/LinkFinder
  • https://github.com/Threezh1/JSFinder

5. 开发人员的注释

开发人员注释(例如// 这是一个开发评论/* 这是一个多行开发评论 */)有时可以包含诸如代码何时发布或发生的任何更新之类的信息(有时候还会注释关于 XSS 过滤,这有助于我了解他们如何修复它并去绕过)。如果代码是旧版本的,那么你发现问题的机会就更大。

6. js.map 文件

还有一个比较特殊的文件, 是以js.map为后缀的文件, 非常多 Webpack 打包的站点都会存在js.map文件。通过还原前端代码找到 API, 间接性获取未授权访问漏洞。

简单说,Source map 就是一个信息文件,里面储存着位置信息。转换后的代码的每一个位置,所对应的转换前的位置。有了它,出错的时候,除错工具将直接显示原始代码,而不是转换后的代码, 这无疑给开发者带来了很大方便。

相关的处理工具有 (可以使用它们将代码还原):

  • https://www.npmjs.com/package/restore-source-tree
  • https://github.com/paazmaya/shuji
  • https://www.npmjs.com/package/reverse-sourcemap
  • https://github.com/rarecoil/unwebpack-sourcemap

在 React.js 上读取 .js 文件的示例

在查看一个 React.js 的网站的时候, 发现一个settings.js文件:app.js是我们的重点。我们要找什么?新的端点、参数,也许还有 api key。打开它时,我们会看到似乎是“乱七八糟”的东西。

第一步:美化。
美化会将我们的代码变成可读的代码。复制代码内容并使用 Javascript 美化器,例如:https://beautifier.io/

第二步:搜索关键字。
现在我们的代码可读了,让我们开始寻找新的端点、参数,也许还有 api key。通过搜索关键字pathname,我能够找到网站上使用的所有端点,这些端点扩展了攻击面以查找错误,并开始查找有关其 API 的信息。

要查找的其他常见关键字:

  • url:
  • POST
  • api
  • GET
  • setRequestHeader
  • send((注意: 只有一个 (,因为它在发出 Ajax 请求时使用!)
  • headers
  • onreadystatechange
  • var {xyz} =
  • getParameter()
  • parameter
  • .theirdomain.com
  • apiKey
  • postMessage
  • messageListenger
  • .innerHTML
  • document.write(
  • document.cookie
  • location.href
  • redirectUrl
  • window.hash

自动化读取工具

如果是自动读取的话,可以利用上面的三个工具:

  • https://github.com/003random/getJS
  • https://github.com/jobertabma/relative-url-extractor
  • https://github.com/0xsha/GoLinkFinder

JS 混淆处理

如果 js 被混淆了,可以使用下面的工具:

  • https://lelinhtinh.github.io/de4js/

大多数类型的混淆都可以解决。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询