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/ ...
808 0
|
2月前
|
JavaScript 安全 前端开发
同源策略如何防止 XSS 攻击?
【10月更文挑战第31天】同源策略通过对 DOM 访问、Cookie 访问、脚本执行环境和跨源网络请求等多方面的严格限制,构建了一道坚实的安全防线,有效地防止了 XSS 攻击,保护了用户在网络浏览过程中的数据安全和隐私。
115 49
|
6月前
|
存储 安全 JavaScript
手摸手带你进行XSS攻击与防御
当谈到网络安全和信息安全时,跨站脚本攻击(XSS)是一个不可忽视的威胁。现在大家使用邮箱进行用户认证比较多,如果黑客利用XSS攻陷了用户的邮箱,拿到了cookie那么就可以冒充你进行收发邮件,那真就太可怕了,通过邮箱验证进行其他各种网站的登录与高危操作。 那么今天,本文将带大家深入了解XSS攻击与对应的防御措施。
|
2月前
|
安全 前端开发 Java
Web安全进阶:XSS与CSRF攻击防御策略深度解析
【10月更文挑战第26天】Web安全是现代软件开发的重要领域,本文深入探讨了XSS和CSRF两种常见攻击的原理及防御策略。针对XSS,介绍了输入验证与转义、使用CSP、WAF、HTTP-only Cookie和代码审查等方法。对于CSRF,提出了启用CSRF保护、设置CSRF Token、使用HTTPS、二次验证和用户教育等措施。通过这些策略,开发者可以构建更安全的Web应用。
108 4
|
2月前
|
安全 Go PHP
Web安全进阶:XSS与CSRF攻击防御策略深度解析
【10月更文挑战第27天】本文深入解析了Web安全中的XSS和CSRF攻击防御策略。针对XSS,介绍了输入验证与净化、内容安全策略(CSP)和HTTP头部安全配置;针对CSRF,提出了使用CSRF令牌、验证HTTP请求头、限制同源策略和双重提交Cookie等方法,帮助开发者有效保护网站和用户数据安全。
93 2
|
2月前
|
存储 安全 Go
Web安全基础:防范XSS与CSRF攻击的方法
【10月更文挑战第25天】Web安全是互联网应用开发中的重要环节。本文通过具体案例分析了跨站脚本攻击(XSS)和跨站请求伪造(CSRF)的原理及防范方法,包括服务器端数据过滤、使用Content Security Policy (CSP)、添加CSRF令牌等措施,帮助开发者构建更安全的Web应用。
119 3
|
2月前
|
SQL 存储 安全
什么是XSS攻击?什么是SQL注入攻击?什么是CSRF攻击?
理解并防范XSS、SQL注入和CSRF攻击是Web应用安全的基础。通过采用严格的输入验证、使用安全编码实践以及实现适当的身份验证和授权机制,可以有效防止这些常见的Web攻击,保障应用程序和用户的数据安全。
48 0
|
4月前
|
存储 安全 JavaScript
XSS跨站脚本攻击详解(包括攻击方式和防御方式)
这篇文章详细解释了XSS跨站脚本攻击的概念、原理、特点、类型,并提供了攻击方式和防御方法。
709 1
|
3月前
|
存储 JavaScript 安全
|
3月前
|
存储 JavaScript 前端开发
Xss跨站脚本攻击(Cross Site Script)
Xss跨站脚本攻击(Cross Site Script)