Page 1 of 1

Content Form Hacked - Mangaged to Create Files With It

Posted: Sun Feb 27, 2011 3:44 pm
by Skara
Ok, so I had a meager little contact form that got hacked. This is the slightly updated version. Somehow they managed to create a folder within the contact/ folder and upload files into it. I realize it's not in great shape.. I can see a few issues with it now--namely, I need to check for newlines within everything but the message variable. But I'm pretty sure there's something else related to newlines other than just checking for \n and \r? It seems like I've seen something like that.
What else sticks out? How exactly would something like this be used to create files of all things? Send spam, I get..

Code: Select all

<?php
require_once('../config.php');  //just defines a couple of things.. not really used in this file.

$_title = 'Contact';
$_content = '<table><tr><td>';

$_msg = '<img src="../images/c_line.png" alt="Something to say? Questions? Drop me a line." />';
$_msg2 = '<img src="../images/c_sent.png" alt="Email sent. Expect reply within 2-4 business days." />';
$_name = 'my name';
$_email = 'myemail@mydomain.com';
$_subject = 'Subject Prefix';

function printform($e='') {
	global $_msg,$_content;
	$_content .= "<div style='padding: 40px 20px 20px 60px;'><p>{$_msg}</p><form method='post'><table id='contact'>";
	if ($e) $_content .= "<tr><td colspan='2' style='padding-bottom: 14px;'><b style='color: #500;'>Error:</b> {$e}</td></tr>";
	$_content .= "<tr><td><img src='../images/c_name.png' alt='Name:' /></td><td><input type='text' name='name' size='20' ".(isset($_POST['name'])?"value='".htmlentities($_POST['name'])."' ":'')." /></td></tr>
<tr><td><img src='../images/c_email.png' alt='Email:' /></td><td><input type='text' name='email' size='30' ".(isset($_POST['email'])?"value='".htmlentities($_POST['email'])."' ":'')." /></td></tr>
<tr><td><img src='../images/c_subject.png' alt='Subject:' /></td><td><input type='text' name='subject' size='40' ".(isset($_POST['subject'])?"value='".htmlentities($_POST['subject'])."' ":'')." /></td></tr>
<tr><td style='padding-right: 10px;'><img src='../images/c_message.png' alt='Message:' /></td><td><textarea cols='50' rows='8' name='message'>".(isset($_POST['message'])?htmlentities($_POST['message']):'')."</textarea></td></tr>
<tr><td></td><td><input type='submit' name='contactme' value='Send' /></td></tr>
</table></form></div>";
}

if (isset($_POST['contactme'])) {
    if (empty($_POST['name']) || empty($_POST['email']) || empty($_POST['subject']) || empty($_POST['message'])) {
        printform("All fields must be filled.");
    }
    elseif (!preg_match('/^[a-zA-Z][\w\.-]*[a-zA-Z0-9]@[a-zA-Z0-9][\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]$/',$_POST['email'])) {
        printform('Email does not appear to be valid.');
    }
    else {
        $injection = '/(subject:)|(to:)|(bcc:)|(cc:)|(content\s*-\s*disposition)|(content\s*-\s*transfer\s*-\s*encoding)|(mime\s*-\s*version)|(multipart\s*\/\s*mixed)|(multipart\s*\/\s*alternative)|(multipart\s*\/\s*related)|(reply\s*-\s*to)|(x\s*-\s*mailer)|(x\s*-\s*sender)|(x\s*-\s*uidl)|(content\s*-\s*type)/is';
        if (preg_match($injection,$_POST['name']) || preg_match($injection,$_POST['email']) || preg_match($injection,$_POST['subject']) || preg_match($injection,$_POST['message'])) {
            printform('Header injection detected.');
        }
        else {
            $to = '"'.$_name.'" <'.$_email.'>';
            $from = "\"{$_POST['name']}\" <{$_POST['email']}>";
            $headers = "From: {$from}\r\nReply-To: {$from}";
            if (mail($to, $_subject.' :: '.$_POST['subject'], $_POST['message'], $headers)) {
                echo "<div style='padding: 40px 20px 20px 80px;'>'.$_msg2.'</div>";
            }
            else {
                printform("Server error. Please try again.");
            }
        }
    }
}
else printform();

require_once('../main.php'); //does little more than echo $_content
?>

Re: Content Form Hacked - Mangaged to Create Files With It

Posted: Sun Feb 27, 2011 8:33 pm
by califdon
I think if you just use mysql_real_escape_string() on all your Post variables, you'll be better off than what you have there.

Re: Content Form Hacked - Mangaged to Create Files With It

Posted: Mon Feb 28, 2011 3:09 am
by Mordred
califdon wrote:I think if you just use mysql_real_escape_string() on all your Post variables, you'll be better off than what you have there.
I strongly disagree. This function is for MySQL queries, of which here there are none. For email header injection it might incidentally help, because it would add slashes to the newlines, but this doesn't mean it's correct to use it.
Skara wrote:I can see a few issues with it now--namely, I need to check for newlines within everything but the message variable.
Yes, that's right, and when you do this right you can dispense with the $injection regexp horror.

You also have some XSS in printform() because you're not calling htmlentities correctly, you always need to specify ENT_QUOTES and the correct page encoding, best done with a proxy function.

What you don't have in this function is code that would cause files to be uploaded. Must be in another file, most probably one that deals with file uploads.

Re: Content Form Hacked - Mangaged to Create Files With It

Posted: Mon Feb 28, 2011 12:40 pm
by califdon
I stand corrected. I jumped to a conclusion. Thanks, Mordred.

Re: Content Form Hacked - Mangaged to Create Files With It

Posted: Mon Feb 28, 2011 6:05 pm
by Skara
Hm. If I'm not checking for newlines in the message itself, would I not still need the regex horror for it at least?

I've actually never heard of running htmlentities differently, but I see the quotes point sure enough. I'll get that fixed up too.

I was thinking there wasn't any upload anything here, but I don't have any upload form on my website. What I do have is a single upload script on another website with the same hosting. Bizarre. I've disabled that upload script for now until I can look it over.

Thanks!

Re: Content Form Hacked - Mangaged to Create Files With It

Posted: Tue Mar 01, 2011 2:03 am
by Mordred
What you also appear to have is write permissions in the contact/ folder, which you don't actually need. Or a weak/stolen FTP password (do change it just in case).
Skara wrote:If I'm not checking for newlines in the message itself, would I not still need the regex horror for it at least?
Newlines are special when they are used in the header portion, since they start a new header line. This is why they are dangerous in the to, subject and header lists, the attacker can use them to inject additional headers or prepend/replace his own data in the email body. Strip them and check for them in these parameters of mail() and you'll be fine. Email bodies on the other hand are perfectly okay with newlines.