Bug 67091

Summary: XSS auditor bypass with http-equiv="refresh"
Product: WebKit Reporter: Adam Barth <abarth>
Component: WebKit Misc.Assignee: Nobody <webkit-unassigned>
Severity: Normal CC: ap, dbates, tsepez
Priority: P2    
Version: 528+ (Nightly build)   
Hardware: Unspecified   
OS: Unspecified   
Bug Depends on:    
Bug Blocks: 66579    

Description Adam Barth 2011-08-27 13:30:16 PDT

Reported by j.terh...@gmail.com, Today (4 hours ago)
A basic reflected XSS, using the <meta http-equiv="refresh" /> vector, is allowed by the XSS filter.

Chrome Version: 13.0.782.215 m + stable
Operating System: Windows NT 5.1 build 2600 (Windows XP Home Edition Service Pack 3) i586

Place the attached php file in a web accessible directory of a php enabled apache server at http://<host>/xss.php and call:

The alert is shown and no blocking message is posted to the console. However the call:

_is_ blocked and the usual blocking message ("Refused to execute a JavaScript script. Source code of script found within request.") is posted to the console. See screenshots refresh.jpg and basic.jpg.

If line 4 of the php script is changed to:
echo "<meta http-equiv='refresh' content='0; url=javascript:{$_GET['refresh']}' />";

the filter will also miss the reflected XSS if called as follows: 

Also if line 4 is changed to:
echo "<meta http-equiv='refresh' {$_GET['refresh']} />";

and called using:

the XSS is also allowed. _However_ if line 4 is changed to:
echo "<meta {$_GET['refresh']} />";

and the call:

is made, the filter WILL detect the XSS (see screenshot refresh2.jpg)

PHP Version: 5.3.5
Apache: Apache/2.2.17 (Win32) compiled with MSVC6

        if( isset($_GET['refresh']) ) {
                //echo "<meta http-equiv='refresh' content='0; url={$_GET['refresh']}' />";
                echo "<meta http-equiv='refresh' {$_GET['refresh']} />";
                //echo "<meta http-equiv='refresh' content='0; url=javascript:{$_GET['refresh']}' />";
        if( isset($_GET['body']) ) {
                echo $_GET['body'];
Comment 1 Thomas Sepez 2011-08-29 10:40:47 PDT
<meta> refresh to "javascript:" seems dubious.  Can we measure how often this occurs in the wild?  Might be best to just block it using a mechanism other than XSSAuditor.
Comment 2 Adam Barth 2011-08-29 12:15:20 PDT
Does meta-refresh to a JavaScript URL work in other browsers?  It seems there couple be a compat issue with just removing it.
Comment 3 Adam Barth 2011-08-29 12:16:57 PDT
Actually, this is working as intended.  The bypass is only occurring when the injection is in the context of the refresh itself, which isn't something we're trying to stop.