Server-Side XSS Attack Detection with ModSecurity and PhantomJS

简介: Client-Side JS Overriding LimitationsIn a previous blog post, I outlined how you could use ...

Client-Side JS Overriding Limitations

In a previous blog post, I outlined how you could use ModSecurity to inject defensive JS into the HTML response page sent to the client web browser.  The goal of this technique was to override many common JS elements that are often used by security researchers/attackers when conducting reconnaissance testing for XSS flaws.  While this was an interesting PoC for using ModSecurity in combination with defensive JS, it had one fatal design flaw: the detection logic was exposed to the attacker.  By sending our defensive JS code to the client, we are tipping our hand to the attacker as to our intention and methods.  This allows attackers to then play around with various evasion methods.  

Ideally, we need to keep this type of detection logic server-side, away from the prying eyes of attackers.  But how then do we detect Browser/DOM events server-side?  This blog post willScreen shot 2013-01-22 at 3.31.39 PM demonstrate another PoC that uses ModSecurity's Lua API to execute PhantomJS to evaluate HTML data sent to end users and thus gain insight into XSS payloads that actually execute in the web browser.

What is PhantomJS?

PhantomJS describes itself as:

PhantomJS is a headless WebKit with JavaScript API. It has fast and native support for various web standards: DOM handling, CSS selector, JSON, Canvas, and SVG.
PhantomJS is created by Ariya Hidayat.

It is useful for:

  • Headless Web Testing
  • Screen Captures
  • Automation Tesing
  • Network Monitoring

The key browser functionality at play with PhantomJS is that it uses the WebKit browser engine that is found within Safari and Google Chrome.  For our purposes, the fact that it is "headless" is key as we want to use it for server-side inspection of HTML data to help identify XSS attacks.  

Using PhantomJS for Server-Side XSS Detection

Due to the fact that PhantomJS can utilize WebKit's full browser environment, we can detect successful reflected XSS attacks much more accurately than a server-side app/WAF regular expression filter.  The main advantages are:

  • De-obfuscation - many XSS (and malware/exploit) payloads utilize various encoding and obfuscation tricks to hide their true intention.  Consider techniques such as using partial non-alphanumeric obfuscation.  For example, if an inbound filter was looking for "alert" you could easily use the following non-alpha code to byass it:
Screen shot 2013-02-01 at 4.01.48 PM

By using PhantomJS, we can do our analysis at execution time within the Browser DOM after deobfuscation.

  • Execution Detection - there is a distict difference between identifying an attack payload vs. one that executed successfully.  Just because an attacker sent an XSS payload to the web application does not necessarily mean that it will execute properly within the target's web browser.  The application may in fact apply proper contextual output encoding to the payload and thus neutralize it when it sends it to the browser.  Rather than having a WAF playing the "Boy Who Cried Wolf" everytime some HTML/JS data comes into the application, it would be more useful to only signal an alert if certain data successfully executes within the browser.

In order to use PhantomJS to detect successful XSS attacks, we need to be able to pass it real data from live HTTP transactions. 

Server-Side JS Overriding

Have I mentioned how completely awesome the Lua API is in ModSecurity?  Well, it is.  It allows you to hook in any external program you want which creates an endless number of integrations.  With Lua, we can use ModSecurity to extract the required HTTP data and pass it off to PhantomJS for inspection.  Here is an example rule that launches our js-overrides.lua script:

SecRule RESPONSE_HEADERS:Content-Type "@contains html" "chain,id:'85',phase:5,log,pass"
        SecRule &ARGS "@gt 0" "chain"
                SecRuleScript /usr/local/apache/conf/crs/lua/js-overrides.lua

This script will run at the end of the current transaction (phase:5 in ModSecurity) after the response has already been sent to the client.  This is done to limit latency impacts on clients so the response is not held while PhantomJS tests are being run.  If you want to do active response blocking, you could move this rule to phase:4.  The rule will check the response content-type to verify it contains html data and then checks to see if there was any parameter data being sent to the web application (as we would see in a reflected XSS attack).  If these conditions are met, it will then fire off the js-overrides.lua script:

Screen shot 2013-02-08 at 1.32.11 PM

The Lua script exports the RESPONSE_BODY content obtained by ModSecurity and dumps it into a temporary OS file.  It then executes the highlighted PhantomJS command with two arguments:

  1. xss.js - this is the PhantomJS script file with our detection logic.
  2. tmp_response_body - is the temporary OS file that holds the HTML data.

Let's now take a look at the xss.js file contents:

Screen shot 2013-02-08 at 1.39.08 PM

The script creates a new PhantomJS WebPage object and populates it's contents with the data in the highlighted line.  This line essentially mimicks our previous PoC example where we manipulated the outbound HTML response going to the real client and prepended our JS overrides code (in the js-overrides.js file) to the top. Here are the contents of the js-overrides.js file:  

Screen shot 2013-02-08 at 1.47.08 PM

The script then calls up the wp.evaluate command to have PhantomJS/WebKit evaluate the contents of our web page.    

Example Testing

In order to test this setup, we can take examples from the xssed.com archive such as this one that has been fixed:

Screen shot 2013-02-08 at 1.58.11 PM

The highlighted parameter data would then be reflected into the response body content like this:

Screen shot 2013-02-08 at 1.59.31 PM
And this would execute in the web browser and issue the JS Alert pop-up box:

Screen shot 2013-02-08 at 1.54.54 PM
After the PhantomJS script evaluates the web page data, the JS overrides code would identify the JS alert code execution and it would generate the following ModSecurity event:

Screen shot 2013-02-08 at 2.06.01 PM
As you can see, we now are able to accurately identify when actual JS code executes in a client-side context thanks to PhantomJS/WebKit without having to expose our detections to the end user!

Access Attempts for document.cookie DOM Object

In addition to our JS Override proxy code, we can also gain alert data generated by WebKit if client-side code attempts to violate security policies.  One such can is when JS attempts to access the document.cookie data.  Here is another example taken from xssed.com for an old flaw in the zdnet.com site that is fixed:

Screen shot 2013-02-08 at 2.28.27 PM
When this successfully executes, PhantomJS/WebKit will generate the following ModSecurity alert indicating a DOM Security violation:

Screen shot 2013-02-08 at 2.30.20 PM

Up to this point, we have only been using PhantomJS to evaluate the HTML response body and looking for certain events.  There is another key piece of XSS protection that is available within WebKit that we can take advantage of: XSSAuditor

Leveraging WebKit's XSSAuditor

The WebKit engine contains reflected XSS protection code called XSSAuditor (an excellent whitepaper by the developers is here).   The XSSAuditor filter is located in between the HTML Parser and JS engines which helps with its accuracy.

Screen shot 2013-02-01 at 4.37.24 PM

XSSAuditor will analyze inbound client data with the outbound, parsed HTML data to see if there is any executable code found from the client within the response.  If there is, then XSSAuditor would generate a console alert similar to the following:

Screen shot 2013-02-01 at 4.23.40 PM

Request Mimicking with PhantomJS

In order to use WebKit's XSSAuditor component, you must initiate an actual HTTP request.  We do not want to replay the captured request data on the live web application as that could have negative impacts to the current users application flow.  Fortunately, PhatomJS comes equipped with its own embedded web server!  We can therefore use it to send/receive data captured by ModSecurity from the live transaction.  Let's take a look at the updated ModSecurity rule as it is executing a new Lua script called xssdetect.lua:

SecRule RESPONSE_HEADERS:Content-Type "@contains html" "chain,id:'85',phase:5,log,pass"
        SecRule &ARGS "@gt 0" "chain"
                SecRuleScript /usr/local/apache/conf/crs/lua/xssdetect.lua

Here is the updated xssdetect.lua script contents:

Screen shot 2013-02-08 at 2.48.05 PM
Notice the new bolded/highlighted sections as we now also need to gather the inbound request URI data (including QUERY_STRING contents).  We then execute PhantomJS again but we pass it a new file called xssdetect.js and two more arguments holding the names of the temp OS files holding the request/response data.  Here is the contents of the xssdetect.js file:

Screen shot 2013-02-08 at 2.58.42 PM
Screen shot 2013-02-08 at 2.59.01 PM

The xssdetect.js script does the following:

  1. Initiates its own embedded web server module (based on Mongoose) listening on the loopback interface on a random 4-digit port. 
  2. Sets XSSAuditingEnabled = true.
  3. Initiates a new HTTP request using the REQUEST_URI data exported from ModSecurity.
  4. The PhantomJS web server responds with the HTML response data exported from ModSecurity.
  5. PhantomJS/WebKit then evaluates the HTML page.
  6. Alerts are generated in two different scenarios - if the XSSAuditor triggers or if one of the JS events of interest execute.

XSSAuditor Alerts with PhantomJS

If this same request from the previous ZDnet XSS screenshot was sent through our server-side implementation, we would received the following alert indicating that WebKit's XSSAuditor blocked execution of reflected XSS code:

 Screen shot 2013-02-08 at 3.04.50 PM

Future Testing

While I must admit that I am pretty excited about the possibilities for server-side XSS detection with this proof of concept, there are some considerations that must be addressed if you want to field this setup in a production environment.

  1. When to use it - As you can see from my example SecRules, I am only initiating this script under certain circumstances.  You may only have very specific conditions or locations within your web application that you want to activate this analysis.
  2. Asynchronous Mode -  in the current setup, we are actually waiting for the command line PhantomJS program to return results.  This leads to an obvious latency/performance impact.  One option for dealing with this would be to set the PhantomJS execution as a background process and then have the PhantomJS code actually initiate its own request back to the web server sort of like a RESTful API.  When sending back this beacon request, it would be wise to pass the UNIQUE_ID variable data that was assigned to the original transaction.  This would allow you to then tie the beacon alert with the actual data.
  3. PhantomJS N-tier Architecture - ideally you could setup and entire platform of PhantomJS nodes where you can pass job requests to them.  There are other web automation frameworks that could be utilized here such as NodeJS, Selenium, WebDriver, etc... 

Acknowledgments

There are many security researchers who have in part inspired this work and/or who directly helped me with developing this proof of concept:


目录
相关文章
VIDEO: web application firewall bypass with a XSS attack
http://www.acunetix.com/blog/news/web-application-firewall-bypass-xss-attack/ ...
768 0
|
1月前
|
JavaScript 安全 前端开发
js开发:请解释什么是XSS攻击和CSRF攻击,并说明如何防范这些攻击。
XSS和CSRF是两种常见的Web安全威胁。XSS攻击通过注入恶意脚本盗取用户信息或控制账户,防范措施包括输入验证、内容编码、HTTPOnly Cookie和CSP。CSRF攻击则诱使用户执行未经授权操作,防范手段有CSRF Tokens、双重验证、Referer检查和SameSite Cookie属性。开发者应采取这些防御措施并定期进行安全审计以增强应用安全性。
20 0
|
3月前
|
存储 JSON 前端开发
【面试题】XSS攻击是什么?
【面试题】XSS攻击是什么?
|
3月前
|
存储 开发框架 安全
如何处理预防XSS漏洞攻击问题
防止XSS攻击需要从多个方面入手,包括输入验证和过滤、输出编码、设置正确的HTTP头部、使用最新的安全框架和库、定期进行安全审计和漏洞扫描以及培训和意识提升等。只有综合运用这些措施,才能有效地防止XSS攻击,保护网站和用户的安全。
|
6月前
|
存储 安全 JavaScript
渗透攻击实例-xss跨站脚本攻击
渗透攻击实例-xss跨站脚本攻击
|
8天前
|
安全 JavaScript Go
跨站脚本攻击(XSS)防护在Django中的应用
【4月更文挑战第15天】本文介绍了Django如何防范XSS攻击。Django模板引擎自动转义HTML以防止恶意脚本,提供`mark_safe`函数和CSRF防护。此外,建议开发者验证清理用户输入、使用内容安全策略、更新库以及遵循安全编码实践来增强防护。通过这些措施,开发者能构建更安全的Web应用。
|
1月前
|
安全 JavaScript 前端开发
Low 级别反射型 XSS 演示(附链接)
Low 级别反射型 XSS 演示(附链接)
19 0
|
1月前
|
存储 JavaScript 前端开发
DOM 型 XSS 演示(附链接)
DOM 型 XSS 演示(附链接)
69 0
|
1月前
|
存储 前端开发 JavaScript
存储型 XSS 攻击演示(附链接)
存储型 XSS 攻击演示(附链接)
75 0
|
1月前
|
存储 前端开发 JavaScript
反射型 XSS 攻击演示(附链接)
反射型 XSS 攻击演示(附链接)
125 0