Nico's hax0r blog

It’s time again… exit;

As most of you probably don’t know, I work in a real estate agency. So every now and then I search for new websites where I can upload our properties to.

Recently I came across bancodecasas.com

When I first saw the site, I already had the feeling that something wasn’t quite right with it.

The site allows you to upload up to 8 images per property. So basically, you have 8 steady slots for images, whether they contain images or not, they’re there. If one of the slots is empty, the site shows a default image, which is just a placeholder. Well that was the idea, but the paths to the default images were wrong, so Firefox was unable to display these images. Not very professional, I thought to myself. There are also buttons to delete the images. If I click the button, I get a PHP error:

Warning: unlink(../images/mgrafico/noimagen.jpg) [function.unlink]: No such file or directory in /home/xxxxxxxxxx/xxxxxxxx/xxxxxxxxxx.xxx/public_html/userspanel/eliminarimg3.php  on line 17

That, is what I call a major logic error in the script. First off, there shouldn’t be a “delete button” if there’s no image. And second, I (as user) shouldn’t be able to delete any images except my own. They also had a separate PHP file for each image. Meaning, “eliminarimg1.php” would delete the first image, “eliminarimg2.php” the second, etc… I found this fairly unprofessional too, from a technical point of view.

This is where it started getting suspicious. If there are silly errors like this, there must be some security related errors as well.

I went to the page where you can modify your uploaded properties. The URL in the address bar held the ID of my property. My first thought was, okay, what if I change the ID to some other ID, which would be the one of a property that I didn’t upload.

I picked a random ID and tried it out, but the site redirected me to the main page instead of showing me the property. I was a little surprised they thought of checking for this at all. But I went a step further…

What if I disabled HTTP redirects? I’m assuming they’re simply using a header(‘Location: xxx’) redirect if the property doesn’t appear to be mine.

I disabled redirects, and voila, I was able to see and edit other properties.

Wait, what happened here?

They verify if the property with ID (given by URL) belongs to the current user (they’re using simple PHP sessions to identify them). If the property doesn’t belong to the user, they send a new Location header which redirects the browser to a new page.

Something like this:

if ($property['userid'] != $_SESSION['userid'])
{
header('Location: xxxxx');
}

The header() function only sends a new location to the browser. But the browser behaves the way I want it to, and I can tell it to stop following those redirects.

Besides, header() does not stop the code execution. The rest of the code continues running after sending the header. Usually the browser redirects fast enough, before anyone would notice, though.

So I think what I’ve done here is getting obvious. I disabled HTTP redirects on my browser, and was able to see the actual page because nothing prevented the code from continuing after sending the redirect.

What they should have done is as simple as an exit() or die() call after the header() call. Yup, it’s that easy.

http://www.php.net/exit

WAIT, I’m not done yet with this site!

They have one of those fancy WYSIWYG editors for the description of the property (TinyMCE, if you must know). Next, I checked if I was able to inject JavaScript code somewhere. I typed some code into the editor, saved, and checked what happened. Looks like my input is being converted to HTML entities, and therefore useless once saved.

But I didn’t give up here. I figured that perhaps TinyMCE is actually the guilty converter. I popped up Firebug, and changed the fancy editor back to a regular <textarea> field. Once again I typed in some code, hit save, and… SUCCESS! I’m now able to inject an unlimited amount of JavaScript code!

I mentioned once before that trusting the user when it comes to input, isn’t a good idea. And this post confirms it.

Don’t. Ever. Trust. The user.