-1

I found an XSS vuln at a big wiki software. Here's the vuln code:

<?php
/**
 * Mock load.php with pre-defined test modules.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 * http://www.gnu.org/copyleft/gpl.html
 *
 * @file
 * @package MediaWiki
 * @author Lupo
 * @since 1.20
 */
header( 'Content-Type: text/javascript; charset=utf-8' );

$moduleImplementations = [
    'testUsesMissing' => "
mw.loader.implement( 'testUsesMissing', function () {
    mw.loader.testFail( 'Module usesMissing script should not run.' );
}, {}, {});
",

    'testUsesNestedMissing' => "
mw.loader.implement( 'testUsesNestedMissing', function () {
    mw.loader.testFail('Module testUsesNestedMissing script should not run.' );
}, {}, {});
",

    'testSkipped' => "
mw.loader.implement( 'testSkipped', function () {
    mw.loader.testFail( false, 'Module testSkipped was supposed to be skipped.' );
}, {}, {});
",

    'testNotSkipped' => "
mw.loader.implement( 'testNotSkipped', function () {}, {}, {});
",

    'testUsesSkippable' => "
mw.loader.implement( 'testUsesSkippable', function () {}, {}, {});
",

    'testUrlInc' => "
mw.loader.implement( 'testUrlInc', function () {} );
",
    'testUrlInc.a' => "
mw.loader.implement( 'testUrlInc.a', function () {} );
",
    'testUrlInc.b' => "
mw.loader.implement( 'testUrlInc.b', function () {} );
",
    'testUrlOrder' => "
mw.loader.implement( 'testUrlOrder', function () {} );
",
    'testUrlOrder.a' => "
mw.loader.implement( 'testUrlOrder.a', function () {} );
",
    'testUrlOrder.b' => "
mw.loader.implement( 'testUrlOrder.b', function () {} );
",
];

$response = '';

// Does not support the full behaviour of ResourceLoaderContext::expandModuleNames(),
// Only supports dotless module names joined by comma,
// with the exception of the hardcoded cases for testUrl*.
if ( isset( $_GET['modules'] ) ) {
    if ( $_GET['modules'] === 'testUrlInc,testUrlIncDump|testUrlInc.a,b' ) {
        $modules = [ 'testUrlInc', 'testUrlIncDump', 'testUrlInc.a', 'testUrlInc.b' ];
    } elseif ( $_GET['modules'] === 'testUrlOrder,testUrlOrderDump|testUrlOrder.a,b' ) {
        $modules = [ 'testUrlOrder', 'testUrlOrderDump', 'testUrlOrder.a', 'testUrlOrder.b' ];
    } else {
        $modules = explode( ',', $_GET['modules'] );
    }
    foreach ( $modules as $module ) {
        if ( isset( $moduleImplementations[$module] ) ) {
            $response .= $moduleImplementations[$module];
        } elseif ( preg_match( '/^test.*Dump$/', $module ) === 1 ) {
            $queryModules = $_GET['modules'];
            $queryVersion = isset( $_GET['version'] ) ? strval( $_GET['version'] ) : null;
            $response .= 'mw.loader.implement( ' . json_encode( $module )
                . ', function ( $, jQuery, require, module ) {'
                . 'module.exports.query = { '
                . 'modules: ' . json_encode( $queryModules ) . ','
                . 'version: ' . json_encode( $queryVersion )
                . ' };'
                . '} );';
        } else {
            // Default
            $response .= 'mw.loader.state(' . json_encode( $module ) . ', "missing" );' . "\n";
        }
    }
}

echo $response;

The output of $_GET["modules"] isnt filtered. Can you tell me if this XSS is vulnerable and also dangerous in your eyes?

7
  • You've put a dump of code without any context - how is this used in the software, and what payload would result in a problem? Without those details, it's effectively asking for a code review.
    – Matthew
    Commented Jul 19, 2018 at 13:24
  • Thanks for your answer, i see ...in ie9 its working with url parameter ?modules=test.Dump&version=%3Cbody%20onload=alert(document.cookie);%3E ... but you are right - ill report it to the vendor - but thanks anyway! Commented Jul 19, 2018 at 13:35
  • okay its working with ie 10 as well ... Commented Jul 19, 2018 at 13:39
  • 3
    Two things: first, you just potentially outed a vuln on a major software package. Second, it's a unit test ....
    – schroeder
    Commented Jul 19, 2018 at 14:07
  • 1
    @schroeder The first point is important, but does it matter that it's a unit test? The file seems to be standalone, and if the tests are bundled into releases, then reflected XSS would be exploitable (if it exists).
    – tim
    Commented Jul 19, 2018 at 15:01

3 Answers 3

5

This doesn't seem dangerous as the content type isn't HTML:

header( 'Content-Type: text/javascript; charset=utf-8' );

For specifics about XSS and content type text/javascript see eg Reflective XSS in script codes with Content Type “text/javascript”.

As an aside, I would suggest to either anonymize the code in the future or to not ask such a question in a public forum. Full disclosure without contacting the vendor first is bad form.

6
  • IMO, Open source/GNU stuff is meant to be shared publicly so it's fine
    – Xenos
    Commented Jul 19, 2018 at 14:29
  • 4
    @Xenos No, it is not fine. The reason why you don't publish vulnerabilities in public before contacting the vendor / maintainer team is that doing so puts end-users in danger. Whether the software is open source or proprietary doesn't make a difference in this regard. Those in a position to fix a vulnerability need to be the first to learn about it so they get a head-start to work on a patch before the black hats start to exploit it.
    – Philipp
    Commented Jul 19, 2018 at 14:44
  • okay - i reported it yesterday to the vendor - and yes it is xss -> just try xenotix or something else to the ?modules=[X] and you will get the stuff! But i wont go deeper... to prevent the vendor from any damage ... Commented Jul 20, 2018 at 8:49
  • @RobertBeran I don't see how it's XSS (just because a tool says so doesn't mean it really is). But if you remember, it would be great if you could update us here once the vendor has released a fix.
    – tim
    Commented Jul 20, 2018 at 9:23
  • @RobertBeran FYI, I tested with IE9, and it doesn't work. With content type text/javascript, IE9 offers me the file for download instead of executing the script. I also thought about the possibility to use this to bypass CSP policies (if there is an XSS issue somewhere), but that doesn't work either as they properly JSON encode the input.
    – tim
    Commented Jul 20, 2018 at 9:44
3

For reference, the file in question is https://github.com/wikimedia/mediawiki/blob/master/tests/qunit/data/load.mock.php

It's partially protected with a 'Deny from all' .htaccess in the root of the test directory https://github.com/wikimedia/mediawiki/blob/master/tests/.htaccess

Deny from all
3
  • on my installation - here: lists.wikimedia.org/pipermail/mediawiki-announce/2018-June/… it isnt protected by any htaccess!!! Commented Jul 20, 2018 at 15:58
  • 2
    Known packaging issue for the 1.30 tarball
    – Sam Reed
    Commented Jul 20, 2018 at 17:03
  • By default, Apache doesn't parse htaccess files (and other servers never do). If the application requires AllowOverride All to run, then this is a small mitigation. But if an XSS vulnerability exists in this file, it would still be a problem.
    – tim
    Commented Jul 21, 2018 at 7:21
0

If I read this code correctly it is listing the installed modules on the web server. This is a vulnerability but you'd have to be the server admin and have a module with a name like <script>alert('xss');</script> .

However is it an XSS? OWASP defines XSS as :

"Cross-Site Scripting (XSS) attacks are a type of injection, in which malicious scripts are injected into otherwise benign and trusted websites. XSS attacks occur when an attacker uses a web application to send malicious code, generally in the form of a browser side script, to a different end user. Flaws that allow these attacks to succeed are quite widespread and occur anywhere a web application uses input from a user within the output it generates without validating or encoding it." https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)

Since this attack would be from an authenticated user on the operating system it would not be an XSS.

2
  • The definition never mentions the "authenticated" status of the user. If you've injected javascript in a HTML document and it got interpreted by the browser, then it's a XSS. More generally, if you've injected something in a web document that got interpreted, then it's XSS.
    – Xenos
    Commented Jul 20, 2018 at 15:18
  • You wouldn't have to have server admin rights or a specific module. The module name comes from the URL ($_GET['modules']) and is echoed into the response (even if the module doesn't exist; in the elseif and else cases). But even if you would require both, it's still XSS (though not interesting if only server admins can enter the payload).
    – tim
    Commented Jul 21, 2018 at 7:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .