September 11, 2016

Why RCE Ruins Days, Weeks, and Products


I was recently testing a product (sorry, can't disclose that part) when I found an issue I've personally never come across before. I've dealt with HTML Injection and SQL Injection (way more common than it should be) before, but I never figured I'd find a project that'd actually give me Code Injection especially in 2016. Oh how wrong I was...

What even is Remote Code Execution/Code Injection?

For the uninitiated, Code Injection or Remote Code Execution (RCE) is the ability to run commands on the server via a malformed request. Typically, a parameter is passed to a local program and that parameter is not checked or sanitized before being run with the local program. An example:
You have a web application that will send an email to a user when specific events occur. A malicious user chooses the email address test@test.com;sleep 45 You handle email by running a local batch job using a local program called sendmail. Your malicious user just signed up, and your web application prepares to fire off an email. The following command is run:
$/bin/sh sendmail email_template test@test.com;sleep 45
Your application now has sent off an email to test@test.com and run the command sleep 45.
The implications of being able to run commands on the server itself are huge. A malicious user can wget a reverse shell, execute that shell, and then have a remote shell session on your server. A whole new level of horrible, right?

Fun Filter Bypasses

During my product testing, I was able to identify a few different locations where I thought RCE was possible. I ran into some immediate trouble though. My semicolons (;) were being stripped away and additional spaces were being replaced with underscores (_). How rude of this application to make my life difficult.

Enter my new friends: the pipe (|) and the double ampersand (&&). Anyone who has ever used a bash shell has likely used these operators to chain commands together. And to my luck, the pipe worked in one field and the double ampersand worked in another field. SCORE.

Next problem, spaces were being trimmed, removed, or weirdly replaced with other characters. That's kind of a roadblock when you need to space delimit commands and parameters. NOT SCORE. Back to the drawing board...

I stumbled across a blog post from the CTO/Co-founder of Duo Security (https://jon.oberheide.org/blog/2008/09/04/bash-brace-expansion-cleverness/) that literally solved the last bit of my problem. Evidently with bash, you can make a list of comma delimited commands surrounded with curly brackets. Who friggin' knew!  And of course, the final payload. Quite literally my favorite payload thus far.

Quick Note: My forward slashes were also being removed, so that's why this is extra messy.
{cd,..}&&{cd,..}&&{cd,..}&&{cd,..}&&{cd,..}&&{cd,var}&&{cd,tmp}&&{touch,owned}

That disgusting collection of ampersands changes directory (eventually) back to / where it then navigates to /var/tmp and creates a new file titled owned.

Concluding Remarks

Writing software is hard. This is nothing new. Letting user input touch system commands is a horrible idea, and I don't even care if you sanitize. The risk for me is just too high. But, always keep in mind the command you're running and the potential to escape from that command and injection additional commands. There is an obvious list of special characters that should always be stripped (pipe, semicolon, and double ampersand). Consider environment variables that can be read and other potential avenues for exploitation if you absolutely must run a system command with user-defined input. Thanks for reading!

2 comments:

  1. Fascinating. Would you mind writing a blog post about how dank memes inform your pen-testing efforts?

    ReplyDelete

The S3 Bucket Problem - The Latest Vuln to Become Popular

Yes, yes, I'm late to the party, I know. Poorly secured Amazon S3 buckets have been a thing for a while now, but recently there's...