Jump to bottom

Topic: Email header injection for Suho (Page 1 of 2) Pages that link to <a href="https://ozoneasylum.com/backlink?for=27650" title="Pages that link to Topic: Email header injection for Suho (Page 1 of 2)" rel="nofollow" >Topic: Email header injection for Suho <span class="small">(Page 1 of 2)</span>\

 
_Mauro
Maniac (V) Inmate

From:
Insane since: Jul 2005

posted posted 03-16-2006 19:38

Ok, I am not a perfect being (quite close though ), so I need informations to help you sort this out.

First things first, this has a bad taste of email injection indeed, looking at the headers.
Email injection is this.

And indeed, what you think may cause your form to be receptive to these attacks.. ~cough.. probably is the cause.

The "probably" is here because, quite frankly, I didn't have time to analyse that regexp yet.
So, something along the lines of your second snippet should help.

The snippets in the sample link I provided above will do the trick, methinks, so, my first tip
is:

Test them.

If they fail like your current snippets, we have to figure out why.
My next tip will be:

Let's debug.

Debugging, in this case, takes two things: a way to see
how your form reacts to inputs, eg. what does it do with inputs? We have to see it.
Only us, not the www.

And the second thing: error messages and warnings, if any.
Again, the more discreet, the better.

There is a precise bit of code which scares me, btw, more than the regexp itself:
it's this (changed the variable names slightly):

code:
"From: $sender <$adress>"))



Jesus Christ! I could put a lot of things in such a construct.
Of course, you'll tell me "but this construct is only called if the message is validated".
Granted, but I strongly think the validation leaves a lot of things out... As you suspected.

That regexp merely makes sure the mail adress is a well-formed, default mail adress.

-------------------------------------------------------------------------------

That was the coder's perspective.
The engineer's perspective, and ask poi his opinion to second mine, is:

K-I-S-S.

Your system is weak because the validation is complex, *way* too complex.
More code makes for more onion sub-layers, if you know what I mean.

An engineer, nowadays, should do *whatever works*, and aim at simple/effective solutions.
(and it's related to OOP and I could rant about why you have to K-I-S-S but it would drift so far
away from our concern...)

Keep me posted.
I got your back until this issue is fixed.
Spammers should get a taste of your finest therapies, methinks (and rot in hell, while we're at it)

Suho1004
Maniac (V) Mad Librarian

From: Seoul, Korea
Insane since: Apr 2002

posted posted 03-17-2006 01:15

Hey, thanks for that link. I will look into that.

One thing I probably should have mentioned in my email is that the code is a variation on kuckus' contact page tutorial over at the GN. I didn't know too much about PHP and email back then (I know a little more now, but not much, to be honest), so I pretty much used it as is and then altered it to suit my needs. Once we get this figured out, it might be a good idea to strengthen the code in the tutorial.

I will test the snippets in that link--in particular, the first snippet, the one that sniffs out new-line characters. If that works, we should be set.

As for the complexity of the validation... yeah, it is rather complex. It took me a while to wrap my head around it when first reading the tutorial. What would you suggest in the way of simplification? Or maybe poi has some ideas? The code for the tutorial is at the GN link above, so we can work with that.

Anyway, I'm going to be busy for much of the rest of the day, so I'll try to work on this tomorrow. And if I ever could get my hands on those spammers... oh, believe me, they would be lighting up like Christmas trees.

Thanks again for the help.

[Edit: I should also mention that the email validation function with the regexp is something I added later and not in the original tutorial code.]

(Edited by Suho1004 on 03-17-2006 01:17)

_Mauro
Maniac (V) Inmate

From:
Insane since: Jul 2005

posted posted 03-17-2006 09:08

You're welcome, I am crossing fingers for these snippets to fix the issue.
Well, the validation is a bit quirky to my taste. Actually, the regexp is a long thing, could do the job with half the complexity.

The problem here is not technical, the problem is that the regexp code gets way to complex for one to be sure
of what it does exactly: add more filtering on the same variables and you get totally lost.

Conceptually, I'd have had a generic filtering function, which receives a string and validates it or dies out,
and I would remove the nested condition tests (if..constructs) to simply pass each field to that function.

It would be a bit drastic but perfect: the script would die out on <any> invalid field.

I'd enforce the scope of each variable, also: a local should be local and should never exist outside it's scope.
The fact of putting the validation in a function could help doing this.

And the odd construct I mentionned above... just don't use variable strings, appended like this, directly
in an attribute you pass to a method.

Steve
Maniac (V) Inmate

From: Boston, MA, USA
Insane since: Apr 2000

posted posted 03-17-2006 17:21

You know - this thread is coming at a perfect time. I'm a victim myself, and the experience of getting hundreds, thousands of bounced e-mails made me furious. I was using a naive version of the basic PHP mail form that's described in dozens and dozens of introductory PHP tutorials. They all have slight variations but most of them are pretty wide open and there must be millions of personal and small business sites that are totally vulnerable because of these tutorials. Most of them were probably written long before anyone realized the harm they were doing by omitting validation of any sort. If they do validate, it's pretty basic: are all required fields filled out, maybe run regex to see if the email follows the correct form, that sort of superficial thing.

So, it being a long time since I last wrote a tutorial I was considering making an improved mail form my next effort and along comes this thread! Perfect timing.

Here are two resources I found helpful. One is a mail address validator that is similar to the one Trib wrote years back in that it actually contacts the mx mail exchange server:
http://www.howtocreate.co.uk/php/
( the "validateEmail" script).

The other is one butcher sent me:
http://www.alt-php-faq.org/local/115/
(you need to remove the call to the log function:
"logBadRequest();"
unless you have a log function! Also note that it is intended to used with a 2-part set up, where the script that validates and sends mail is a different php document that the page that the form is on. Some contact pages have it all in one file.)

So I'll be following this thread and hopefully can aggregate into one place a bunch of useful mail form security techniques that currently are scattered all around the internet.

_Mauro: I really appreciate your expertise here. Also the advise to use less rather than more. Can yo expand on that some? Thanks.

(Edited by Steve on 03-17-2006 17:37)

_Mauro
Maniac (V) Inmate

From:
Insane since: Jul 2005

posted posted 03-17-2006 17:57

No prob, and glad to see you, Steve, long time no see.

* A side note: Am I finding a way to communicate which works, without a hassle, helping around a lot, sharing my expertise,
without losing my temper, causing havoc or feeling I am wasting time? Jesus Christ, it sounds like I am finally really starting to walk in my shoes, and it just gets better and better *

It's hard to expand on this without getting "deep" into programming concepts.
Let's give it a try....

Each programming language has built-in security features.
The data types, and rigidity of those types, is one of those features.
The scope of variables, and control of this scope, is another security feature.

They are intended to prevent injection.

But scripting languages like php trade strict data types and scope for ease-of-programming: you get very loosely typed
variables, and flexible scopes, which makes it easy to script-a-lot... and easy to make security mistakes.

Dig the forums for another thread full of security info, started by Grumble, regarding php & security considerations.
Or the wiqi for that matter.

-------------------------------------------

Please guide me with precise questions btw, otherwise I'll rant 'til I get old.

-------------------------------------------

Another interesting concept is the notion of "defensive programming".
In the past (the eighties), software engineers tended to make sure each and every function
verified all of it's inputs twice before doing any processing.

Which is soundly stupid.

Because it doubles the amount of work of each function.
For nothing in most cases: not only defensive programming failed at preventing all the possible "wrong inputs",
but it also doubled the complexity of the code produced.

And therefore, doubled the error-proneness: this simply is statistics.
Double the amount of instructions, and you get twice the amount of possible failure causes, it just is straightforward.

OOP killed defensive programming: nowadays, a function expects a default system state, and cartain parameters, strongly or loosely typed,
and if it doesn't get them, it stops working.

Functions, and Objects, and programs nowadays act as...

Servers to clients, given a "contract"

Makes sense so far?

The problem of this approach is that best security practices should compensate for the lack of double-checks.
Which leads us to encapsulation, and my tip about putting the validation in a function.

Encapsulation is: properties of a given class, or global variables of a given code module in our case, should never, never -ever-
be accessible directly outside the class/module.

Never.

They should be access in read mode through getters, and in write mode through setters (methods, known as accessors to a given property).



In php, any variable that has a global scope to the current script is publicly accessible, and accessible to the www
(unless specified otherwise - hence the register_global issue).

So in Suho's case, well... I don't want to give out details, but the script pretty much was sequential (little or no functions),
exposed a lot of globals as well, in other words, it violated the principles of encapsulation in many ways.

If you want more, or more specific info, it's simple: ask, precise questions make for precise answers,
and check that thread about security in php by Grumble.

(Edited by _Mauro on 03-17-2006 18:01)

Steve
Maniac (V) Inmate

From: Boston, MA, USA
Insane since: Apr 2000

posted posted 03-17-2006 21:05

_Mauro;
Thanks. I'll look for the security thread you mentioned. I'm thinking that your slant on programming is a lot more rigorous than anything I'm contemplating doing. Anything I write is going to be geared toward someone like me - NOT a professional programmer but a reasonably committed amateur who is motivated to invest time but unwilling to jump into the REALLY deep water. I know this is awfuly close to the sadly superficial tutorials that many of us based our (compromised) mail forms on, but I think there are enough resources available to make a significantly more tamper-resistant contact form without needing an advanced degree in programming (though that of course would help!). The very tentative outline I have going in my mind first identifies the problem (specifically injection hacks due to lack of or improper examination of user input) because the programmer of the class I'm targeting never even stops to consider that someone might use their form in any way other than the way they expect it to be used!

Yep - it's naive, but there are a LOT of us who do this for fun or as an avocation and don't have a clue what sort of doors we have opened.

So. I haven't even typed a word of this thing yet and have a lot to learn before I start, but I certainly will "guide you with precise questions"!

Thanks.

_Mauro
Maniac (V) Inmate

From:
Insane since: Jul 2005

posted posted 03-17-2006 21:41

Please bear in mind that I don't mean to "impress" (about being an ubber-geek, some kind of pride), it's more, like, "give a man a fish..."
The security thread and security faq entries sum up a lot of simple info and code already, all the basics.

AND.

You mentionned you don't bave a clue what sort of doors you have opened.
I can't even try to show you the walls without some general principles.

In other words, the small details don't make a lot of sense without a glance at the big pic.
And I don't pretend to have half of such an overview, but I know a lot of the -core- stuff now.

That other thread took the example of "systems being made of onion layers", and security flaws as gaps between layers.
If you look at security, and the post above, from that perspective, it should start to make sense.

(Edited by _Mauro on 03-17-2006 21:42)

_Mauro
Maniac (V) Inmate

From:
Insane since: Jul 2005

posted posted 03-17-2006 21:58

Ah, and also: I consider php a great language. I mean, scripting languages have been conceived as "play things", easy to use, powerful, so play around.
But be aware there are nasty hackers out there who cheat, beat them.

Ask the Asylum in case of doubt. That's all.

OpticBurn
Paranoid (IV) Inmate

From: Lower City, Iest, Lower Felda
Insane since: Sep 2000

posted posted 03-17-2006 22:32

You want KISS?

$to = "myaddress@home.com"
$headers = "From: dont-reply@home.com";
$message = "From $_POST['from']" . $_POST['message'];

_Mauro
Maniac (V) Inmate

From:
Insane since: Jul 2005

posted posted 03-17-2006 23:51

No, you got the simple and stupid, but you're missing the "keep it" part.
This is the opposite of a secure system, and exactly what is recommended to avoid by my first link.

Try again.

OpticBurn
Paranoid (IV) Inmate

From: Lower City, Iest, Lower Felda
Insane since: Sep 2000

posted posted 03-18-2006 00:10

What's the insecure part?

I don't think you are looking at my code fully...

There are two issues here, one is allowing unvalidated input and one is allowing access to a 'secure' area, the article just talks about validation of input but doesn't address the underlying issue, there is no need for the user to have any access to the headers field.

(Edited by OpticBurn on 03-18-2006 00:19)

_Mauro
Maniac (V) Inmate

From:
Insane since: Jul 2005

posted posted 03-18-2006 00:43

It strikes me as so easy to insert other mail headers into your $headers variable. Like a BCC field.

With 10000 entries.

Separated by commas

Fun stuff.
And you get the blacklisting, and complaints.

_Mauro
Maniac (V) Inmate

From:
Insane since: Jul 2005

posted posted 03-18-2006 01:14

Actually, I found a paper that shows you things I am too lazy to code myself.
The $headers variable is secure, but the rest..... ~shivers. This page tells you why:
http://www.nyphp.org/phundamentals/email_header_injection.php

And this seems to be a great resource about php security:
http://securephp.damonkohler.com/index.php/Email_Injection

The problem with the mail forms when you don't do any filtering,
as I suspected without even be certain or having tested, is what I've been saying from the beginning:
the problem is MIME.

I am just too lazy to dig deeper in the MIME RFC, but it seems that someone who can submit a custom form to such a form mail script
and control any field that is feeded to the php....

Can abuse the multipart capabilities of MIME and insert disguised sub-parts in the email.
Thus getting back to the issue of header injection.

And it is, indeed, possible with the sole content field.

<hint: pass everything you receive, even submit fields, to a validation function>

OpticBurn
Paranoid (IV) Inmate

From: Lower City, Iest, Lower Felda
Insane since: Sep 2000

posted posted 03-18-2006 02:35

This is getting old fast Mauro, I can understand that this is confusing and time consuming to try to understand but at least you could make an attempt before you belittle me with your condescending comments.

Here's a hint for you: How many of those sites do validation on the body of the text message? You think a regex for \n would pass a message body?

I'll give you a clue: the answer is none, because this is email HEADER injection attacks. If you understood the rfc on internet text messaging and how email is parsed and exactly why email header injection attacks work, you would understand, but it's clear that your understanding of this subject is topical at best.

So let's try it again:

$to = "myaddress@home.com"
$headers = "From: dont-reply@home.com";
$message = "From $_POST['from']" . $_POST['message'];

What's going on here? I know it's subtle but there is a difference.

DL-44
Lunatic (VI) Inmate

From: under the bed
Insane since: Feb 2000

posted posted 03-18-2006 02:40

That latest header injection page a great link, Ini, thanks =)

DL-44
Lunatic (VI) Inmate

From: under the bed
Insane since: Feb 2000

posted posted 03-18-2006 02:45

Hmm...seem to have missed a couple of posts

Perhaps, for the rest of us, we could forego the arguing and explain what's going on with that method?

=)

OpticBurn
Paranoid (IV) Inmate

From: Lower City, Iest, Lower Felda
Insane since: Sep 2000

posted posted 03-18-2006 03:05

It's simple, it doesn't allow the user to input anything to the header files and sends the email to a specific address with the return address of 'don't-reply@home.com' The actual return email and message are included in the body of the email, this is the only user input and it can do no harm from the message body despite however deformed it is. It's just a different approach to a contact form that eliminates the need for user input validation.

Steve
Maniac (V) Inmate

From: Boston, MA, USA
Insane since: Apr 2000

posted posted 03-18-2006 03:13

_Mauro;

Thanks for those 2 links. the nyphp one was new to me. Added to the research bin.
I read the securephp last fall when I first started to be pestered with the problem. In fact I cited it in a question I asked at the GN in September (I only know that because I just looked it up again just today). It's one of the clearest descriptions of the problem I have come across but, sadly, after that great description of the problem it offers a part-time coder like me virtually no solutions.

OpticBurn - what's with the attitude?

OpticBurn
Paranoid (IV) Inmate

From: Lower City, Iest, Lower Felda
Insane since: Sep 2000

posted posted 03-18-2006 03:40

I'm not sure what you mean by attitude? I guess I'm a little peeved that Mauro won't even give me the minute it would take to read my original post and think about it before writing three posts which are to me condescending when I'm just trying to help him out. =)

I just looked back through some of Mauro's other posts and it's not just me that feels this arrogant attitude.

Steve
Maniac (V) Inmate

From: Boston, MA, USA
Insane since: Apr 2000

posted posted 03-18-2006 05:12

So let's try to keep "other posts" out of this one. I've heard what you refer to, but not in this thread so far and I'd like to keep this one on task.
'kay?
You probably have a valid point in your code. Press your case if you want but keep it light. That's all.

OpticBurn
Paranoid (IV) Inmate

From: Lower City, Iest, Lower Felda
Insane since: Sep 2000

posted posted 03-18-2006 05:54

I'll try =)

Suho1004
Maniac (V) Mad Librarian

From: Seoul, Korea
Insane since: Apr 2002

posted posted 03-18-2006 06:58

OK... there's a lot for me to try to digest here. Like Steve (hi Steve!), I am a "NOT a professional programmer but a reasonably committed amateur who is motivated to invest time but unwilling to jump into the REALLY deep water." I'm trying to get a handle on things, but sometimes I can feel it slipping. That is, I understand the basic principles and concepts, but sometimes I get fuzzy when it comes to actually applications.

So let's see if I can get a few things straightened out here:

Simplifying the code (for _Mauro)

I have to admit, the nested if/thens did seem like a bit much to me when I first looked at the tut, but I couldn't see another way to accomplish the goal. Each of the nested ifs performs a specific function, and I was under the impression that these had to be carried out in order. It is, as you say, sequential:

quote:
So in Suho's case, well... I don't want to give out details, but the script pretty much was sequential (little or no functions),
exposed a lot of globals as well, in other words, it violated the principles of encapsulation in many ways.



OK, so, speaking in general terms here, the things I want to accomplish here are: a) make sure that all the fields are filled in, b) make sure that the return email address validates, and c) weed out header injection attacks (via methods discussed above, namely weeding out newline characters and header-specific strings where they do not belong).

Now, a better way to go about this would be to create a set of validation functions and then run the data through these before sending, yes? But I would still be using the nest if/thens, just calling functions at each step, right? I'm not sure if I'm getting this right. I think I might be a little confused. I would definitely like to make the script simpler and more encapsulated, but I'm not sure if I'm going about this the right way. I'd like to ask specific questions, but most of these specific questions would involve direct code snippets. Would it be better to do this via email?

Hard-coding the headers (for OpticBurn)

I think I understand what your snippet is doing, but is it completely secure against injection? It seems to me that, without any validation, any script is vulnerable. For example, what would prevent someone from injecting a header into the open fields, like "from" or "message"? My understanding of header injection attacks is that simply defining header information is not enough to prevent someone from redefining it later on. That is, the injected headers will override whatever headers were there in the first place. As an example, my own contact form hard-codes the subject line, but when header injection attacks come in they have a second subject line, and this is the one that gets displayed. My original subject line is still there in the full headers, but the second one is the one that gets recognized.

quote:
The actual return email and message are included in the body of the email, this is the only user input and it can do no harm from the message body despite however deformed it is. It's just a different approach to a contact form that eliminates the need for user input validation.



So what prevents an injection attack in the actual return email address? If it's not validation, what is it? I don't understand this, and I would appreciate a fuller explanation. Thanks.

-----

OK, whatever the answers to the above questions may be (and I do look forward to learning more), the first thing I need to do is get a working validation function that will stop the attacks. The simple function I have in my script now is apparently not working, so I am going to attempt to test the functions in that first link _Mauro posted way up there. I will post the results of my testing when I am finished.

[Edit: Joy and jubilation! After only minor stupidity on my part, I have been successful. The functions for both single-line inputs and multiple line inputs both work flawlessly. I have been unable to slip a header injection attack by them on my local server. So, I'm going to make these changes to my contact page, and then I guess I'll just sit back and wait for the spam to not roll in.



Still would like to tighten up the code, make it more modular, though. I'll (we'll) have to work on that.]

(Edited by Suho1004 on 03-18-2006 07:18)

OpticBurn
Paranoid (IV) Inmate

From: Lower City, Iest, Lower Felda
Insane since: Sep 2000

posted posted 03-18-2006 08:00

Okay let's take a look at the basic format of email. It's just a string of text that is parsed in a linear fashion from start to end. Basically you have a string of text that is the headers and then a message body. The headers are the part of the string that are interpreted by the smtp server and translated into commands, once the smtp server reaches the special characters that end the header section it stops parsing the text as commands and simply appends the rest of the text as the message body. This is what makes it possible for me to send an email with header information in the message body. Here is an example email taken from the site http://rfc.sunsite.dk/rfc/rfc2822.html which is one mirror of one of the rfcs with regards to email:

From: John Doe <jdoe@machine.example>
To: Mary Smith <mary@example.net>
Subject: Saying Hello
Date: Fri, 21 Nov 1997 09:55:06 -0600
Message-ID: <1234@local.machine.example>

This is a message just to say hello.
So, "Hello".

You can see that the headers are separated from each other with a \n character, the new line. The headers are seperated from the message body with a \n\n, two returns. Once you are past the \n\n you are in the clear and smtp will simply pass the rest of the information as text.

We can see that the subject line and the from field are part of the header information, if we allow a user to pass input to any field inside the headers they can pass malformed information and in this way append their commands into your normal string of text. These commands will be parsed by the email servers just like a real command. So you can see that any input you allow into the headers must be cleansed of any possible commands. This is an extremely difficult task as you must allow for all possible combinations of characters and symbols that can be parsed as commands by the email servers. This is a huge task as data can be hidden in all manner of unlikely character combinations and to build a regular expression that can capture all this data will require a comprehensive understanding of the email rfcs and also the international symbols and characters that can be interpreted by your smtp server or ignored. Basically you have to check for malformed data that is being pass to avoid your regex as well as checking for malformed text that is being passed to take over your email form.

I look at that and I say: I don't know how to do that. It's that simple, I don't understand regex well enough and I don't understand the email rfcs well enough to recognize all forms of possible attack. There is no way I can build a validator strong enough to pass only clean information 100% of the time, I bet I can get 95+% of the attacks but there are always new attacks coming out.

My solution is to simply preform all the header information with static information or preset data and allow all the user input to fall into the message body, where it can do no harm.

OpticBurn
Paranoid (IV) Inmate

From: Lower City, Iest, Lower Felda
Insane since: Sep 2000

posted posted 03-18-2006 08:08

I'd like to see your code and try to take it apart without having to work on your live site too btw, can you post which php you are using here?

Also please note that my comments regarding the \n\n separating the headers from the message body can be confusing in multipart emails, you'll really have to read through this stuff and figure it out.

_Mauro
Maniac (V) Inmate

From:
Insane since: Jul 2005

posted posted 03-18-2006 13:02

Opticburn, I've read, weighed, and considered your code at first glance. After my last post yesterday, it took me 20 minutes to manage to inject headers in it.
What's up with the ego? I mean, I can waste time to prove your moot point wrong, but I'd really like to focus on progress.

quote:

I think I understand what your snippet is doing, but is it completely secure against injection? It seems to me that, without any validation, any script is vulnerable. For example, what would prevent someone from injecting a header into the open fields, like "from" or "message"?



Nothing could be more accurate to describe the issue.
And all there is to injecting inside a snippet like yours is sending the data as multipart/mixed and figuring out the mime separator (yeah, yeah, it's unique when generated by the php mail function,
as if it was hard to "guess" a random/unique identifier: all it takes is reversing the hash function in use, a few hours at worst), but frankly, I just don't want to waste the energy.

btw, the body and header of a mime message are separated by a generic separator, which is defined in the top level headers.

Please, this emphasis on a solution which does not work probably is even more confusing to readers of a topic which is difficult already.
Think it over: what Suho said makes perfect sense.

quote:

Now, a better way to go about this would be to create a set of validation functions and then run the data through these before sending, yes? But I would still be using the nest if/thens, just calling functions at each step, right?



Pretty much yeah. Basically, I proposed one way, but what really matters here is removing the validation from the sequence.
Encapsulating all operations that validate and test input.

Cause if the validation occurs at the top-level of the script, then it is subject to attacks.
If it occurs inside a function, then it is protected, and can't be altered.

If the validation is correctly done, then the if bits will at least get less intricated, or they would be encapsulated in the validation functions.

Like:

code:
function preventInjection($string){

}

function fieldEmpty($string){

}

if(!fieldEmpty($email)){
    $email = preventInjection($email);
}



The issue here is not the general code layout, it's not the "shape", it's the structure and the concepts behind (eg. encapsulation and readability/maintanability/completion for validation operations).
The rest really is up to you.

My personal preference would be to do all the validation processing inside the validation function, or functions, and loose all the top-level, nested ifs, but do what works for you, as long as it respects the general principles I've given.
(and the ifs are not a concern per themselves).
(and you seem to have understood quite a bit of what I was saying, your views are correct).

Unfortunately, I am still waiting to recover the pass to beyondwonderland.com, after my recent comp and connection issues, but I'll try to put together my own recipe for mail validation,
locally, as soon as I get some time.

Guys, it'll take me a moment to read through all your new posts and questions and come up with a clear/comprehensive/coded final word.

And one more thing, Suho: please don't post your code. Send it away through email if you want (although I would not do that either), but just don't post it.
TTy in a moment...

_Mauro
Maniac (V) Inmate

From:
Insane since: Jul 2005

posted posted 03-18-2006 13:10

Oh, and I was a bit condescending indeed, but I couldn't help the kiss joke, it was for fun, not to do harm, and I did it because most of the links I posted stress the "do not leave out any possibility to inject code in a php mail field",
there *has* to be a reason for that. I appreciate your trying to help, and am sorry if I sounded like a bitch.

But.

I AM a bitch, at times

DmS
Maniac (V) Inmate

From: Sthlm, Sweden
Insane since: Oct 2000

posted posted 03-18-2006 14:14

This is a good thread and ties in perfectly with an issue I recently had with exactly this on an old clients oscommerce installation.

The hosting company alerted us in a nice way, they renamed the contact script, told us what happened and where to look for tips on the solution which happened to be submitted as a patch to oscommerce. It could have been a lot worse.

Anyways it once again strengthes my notion that it is a LOT better to presume all input is malicious and invalid and just let through validated and approved things than trying to stop things as they pop up.

Defensive programming can be done in sequential code that uses globals, but it's a lot harder since there are so many ways to sneak something in there.
The benefits here of using procedural or even better OOP is just too big to overlook.
If nothing else you can keep your validation rules in one or two places and just re-use it where you need it as opposed to having to update and patch in multiple places which is a lottery at best.

Steve, think about the RSS proxy we did a while back, that is both defensive thinking and reusable. Apply that type of thoughts to other types of userinput and you are on the right way.

And _Mauro, good tips and thoughts from you, both here and in the other security thread.

/Dan

{cell 260} {Blog}
-{"Theories without facts are just religions...?}-

Suho1004
Maniac (V) Mad Librarian

From: Seoul, Korea
Insane since: Apr 2002

posted posted 03-18-2006 15:48

_Mauro: Thanks for that clarification. Unfortunately, I have to get to bed now, but I will try to do some more work on my code tomorrow. I think I have a fairly good handle on what you're talking about now.

OpticBurn: I'm not really knowledgeable enough to argue the case, but it seems to me that validation is a safer way to go than trying to get by without validation. That's pretty much where I stand right now. I do appreciate the input of ideas, though.

Steve
Maniac (V) Inmate

From: Boston, MA, USA
Insane since: Apr 2000

posted posted 03-18-2006 15:56

"The benefits here of using procedural or even better OOP is just too big to overlook."

OOP is no doubt the safest approach and it is what I would expect a pro at an enterprise or commercial level to implement. But I fear an OOP approach is going to scare off the reader I have in mind. The consequence will be that they just throw up their hands and continue with the unsecured code they had before.

I want to offer them something that is significantly more secure (than the basic mail form presented in so many intro tutorials) that is maybe significantly but *not* exponentially more difficult to understand and write.


So I'm going with a procedural approach at the moment. Slowly.

"it is a LOT better to presume all input is malicious and invalid" - this WILL be a blockquote on page 2!

OpticBurn
Paranoid (IV) Inmate

From: Lower City, Iest, Lower Felda
Insane since: Sep 2000

posted posted 03-18-2006 22:23

It's perfectly obvious that you have no understanding of email header injection attacks and are simply parroting what you've read before, Mauro. I'll give you $200 if you can perform an email hijack from the body field of mail(). Dead serious, my email is info@bearwoodproducts.com and if you can prove it and show me how you do it I'll paypal you the money or send you a check or cash, whatever you want. That should make it worth your time to spend an hour or two working on it.

I'll repeat it again because it's clear you truly do not understand:

How many of those webpages you've read perform input validation on the message field?

OpticBurn
Paranoid (IV) Inmate

From: Lower City, Iest, Lower Felda
Insane since: Sep 2000

posted posted 03-18-2006 22:32

I've set up a simple website at http://bearwoodproducts.com/test/emailtest.php. The webpage body is this:

code:
<html>
<head>
	<title>Email Injection Test</title>
</head>

<body>

<?php
	
	if( isset( $_POST['from'] ))
	{
		$to = "omnitriangulated@gmail.com";
		$from = $_POST['from'];
		$subject = $_POST['subject'];
		$message = $_POST['message'];
		$newmessage = "From: $from \nSubject: $subject \n\n" . $message;
		
		if(mail( $to, "Mail from WebPage", $newmessage, "From: do-not-reply@somewhere.com" ))
			echo "Mail Sent.";
		else
			echo "Mail not sent.";
		
	}
?>
	<form method="post" action="emailtest.php">
		<p>From: <input type="text" name="from">
		Subject: <input type="text" name="subject"><br>
		Message: <textarea name="message" rows="20" cols="80"></textarea>
		<input type="submit">
	</form>
</body>
</html>



You can see I perform no input validation on any of the inputs from the form. If you can redirect this form to send an email to any account and show me how you did it, I'll give you $200 bucks, anyone. I'm dead serious about the money.

Edit I took out the 'else' statement so you can just keep submitting emails for testing.

(Edited by OpticBurn on 03-18-2006 23:39)

OpticBurn
Paranoid (IV) Inmate

From: Lower City, Iest, Lower Felda
Insane since: Sep 2000

posted posted 03-18-2006 22:36

Here are the headers from an example mail sent through this form. You now have a complete understanding of this system, which is much more than any random spammer would have.

code:
X-Gmail-Received: 1a0ffb17a45bc027f6849df6d2f3c5f8ce33329f
Delivered-To: omnitriangulated@gmail.com
Received: by 10.35.63.11 with SMTP id q11cs13411pyk;
        Sat, 18 Mar 2006 13:28:12 -0800 (PST)
Received: by 10.35.37.18 with SMTP id p18mr924290pyj;
        Sat, 18 Mar 2006 13:28:10 -0800 (PST)
Return-Path: <www@localhost.localhost>
Received: from localhost (69-1-118-214.generic.webformix.com [69.1.118.214])
        by mx.gmail.com with ESMTP id w76si1466890pyd.2006.03.18.13.28.09;
        Sat, 18 Mar 2006 13:28:10 -0800 (PST)
Received-SPF: neutral (gmail.com: 69.1.118.214 is neither permitted nor denied by best guess record for domain of www@localhost.localhost)
Received: by localhost (Postfix, from userid 70)
	id CB9CF12AF18; Sat, 18 Mar 2006 13:28:08 -0800 (PST)
To: omnitriangulated@gmail.com
Subject: Mail from WebPage
From: do-not-reply@somewhere.com
Message-Id: <20060318212808.CB9CF12AF18@localhost>
Date: Sat, 18 Mar 2006 13:28:08 -0800 (PST)

From: luke@webpage.com
Subject: Email test

Checking, one two.

OpticBurn
Paranoid (IV) Inmate

From: Lower City, Iest, Lower Felda
Insane since: Sep 2000

posted posted 03-19-2006 00:23
quote:
And all there is to injecting inside a snippet like yours is sending the data as multipart/mixed and figuring out the mime separator (yeah, yeah, it's unique when generated by the php mail function,
as if it was hard to "guess" a random/unique identifier: all it takes is reversing the hash function in use, a few hours at worst), but frankly, I just don't want to waste the energy.



Do you have any idea how stupid this makes you look? This is so clueless it's painful, it's embarassing, you should be ashamed of yourself really for promoting 'security' ideas you have no understanding of.

You are spreading insecurity, you are doing harm to people here Mauro, please stop.

(Edited by OpticBurn on 03-19-2006 00:25)

_Mauro
Maniac (V) Inmate

From:
Insane since: Jul 2005

posted posted 03-19-2006 00:59

Up to version 4.2.2, using control chars from within the message body can, in a lot of circumstancies on a lot of php servers,
lead to this:

http://www.securiteam.com/unixfocus/5SP0M2080W.html

I AM not the one to say it, indeed, and I am not parotting: it's the first time this link comes up in this thread. I dug it to confirm my suspicions and ~surprise~ it existed and was waiting for me.
Plus yeah, the nyphp link urges you to even filter your _submit fields.
So long for two of your cleverly laid out arguments.

I am sad you take it so deeply at heart, deeply enough to contribute four pieces of filth, but your snippet leaves a gap open, everything of all security best practices
shows it.

And according to the games I've played with my newly installed local smtp server (not IIS) and the latest version of php, ascii control chars injection is still possible as of today,
and some amazing things are possible with the sole email message, yeah.
...

I said it before, though, and I won't let your preteen challenge have me drift from my personal goals: I have -a ton of things- on my plate, including three assignments due this week, aside my daily activities
and some personal things as well.



But I'll get back to your case for the sake of showing you how.
And in the meantime, hopefully, you'll be calm enough to consider you could have missed something.

...And, what really matters here, Suho and others will have taken advantage of my "parotting" to secure theyre form mails cleverly, without leaving out any field.

Suho1004
Maniac (V) Mad Librarian

From: Seoul, Korea
Insane since: Apr 2002

posted posted 03-19-2006 02:32

Um, OK, I think things might be getting a little heated in here. We have two people accusing each other of spreading misinformation, and honestly I'm not enough of an expert to tell who is right. But I will say this: validation is a fundamental principle of secure coding. How is promoting validation "spreading insecurity"? How is it "doing harm to people"?

OpticBurn, maybe your method works. I'm not knowledgeable enough to pick it apart and try to find flaws in it. I can only go by my own experience and the advice of those with more knowledge and experience than myself. And it seems to me, simply from a logical standpoint, that it is better to be safe than sorry--that is, it is better to validate than to not validate. If your method does work, then that would be great. But if it does not, then it opens gaping security holes by leaving out any sort of validation.

On the other hand, I have tested the functions that Mauro has kindly pointed me to, and they have worked for me. And, as they say, the proof is in the pudding: since implementing the new validation, I have not received any header injection spams. I think a few more days are needed before I can proclaim complete success, but so far everything seems to be working. So until you can show me how Mauro's methods are dangerous, I'm going to follow his advice. This is nothing against you personally, but I would prefer to err on the safe side.

poi
Paranoid (IV) Inmate

From: Norway
Insane since: Jun 2002

posted posted 03-19-2006 03:30

OpticBurn: I'm no security/hacking overlord but in regard of the PHP Mail Function ASCII Control Character Header Spoofing Vulnerability it seems pretty obvious that one could spoof the mail header in your script via the from or subject fields. You might reconsider your choice of not validating the inputs after reading Secure PHP wiki - Email Injection ( which is, I just noticed, also linked to from one site provided by Mauro )

_Mauro
Maniac (V) Inmate

From:
Insane since: Jul 2005

posted posted 03-19-2006 03:57

Actually, this vuln is what has been discussed throughout the whole topic, I think it's now obvious that the from and subject fielsd are individually vulnerable, and it requires the ascii control char "\n",
but OpticBurn's point is that these are the only vulnerable fields.

And my undocumented point is no, they aren't. Any field which hasn't been validated is.

The vuln I just posted says that "a special control char may break a field" when passed to the mail function, and what I have in my hands now, code-wise,
does exactly this on a Mercury Mail Transfer system, as the MTA, affecting only the body.
I don't know how to use that yet, and it all depends on the MTA in use, but I'll find out, and I strongly think it leads to more headers spoofing.

Not the now obvious "inject stuff in mail headers directly" way, but something like pushing the system to do things against it's will, and alter the smtp input stream
which contains our mail() message. (buffer overruns, underruns, for given Mail Transfer Agents, other ways to alter the stream - as it stands now, the output
of the php mail message command is an ascii-encoded string, carrying smtp/mime information, in which control chars can be inserted. Those control will behave differently on different OS
and php / mail agent setup, and I also think some systems will, for example, process backspace chars when passing the output of the mail function, causing
a possibility to completely reformat the email and mime headers.. and that's one in a million ways and tracks to a probable injection using only the body field)

And I seriously had these intuitions a few minutes after having read your post, OB, and they derive from the generic security principles I exposed.
(hence the fact I think a little more work, when I have the time, will prove you wrong).

---
Glad to hear it works btw, Suho.

_Mauro
Maniac (V) Inmate

From:
Insane since: Jul 2005

posted posted 03-19-2006 04:11

Or at least, that it is likely to work. One more post before I get off for some time, a link, very interesting,
which shows many other undocumented php features. Pay attention to the way he confirms many things I described here:
http://www.securereality.com.au/studyinscarlet.txt

Steve
Maniac (V) Inmate

From: Boston, MA, USA
Insane since: Apr 2000

posted posted 03-20-2006 00:42

"Um, OK, I think things might be getting a little heated in here."
You think?

I'm losing interest in this thread. Not in the topic but in the thread.
Nice job OpticBurn! Took an interesting and potentially helpful thread and turned it into your own tantrum

schmuck...

DL-44
Lunatic (VI) Inmate

From: under the bed
Insane since: Feb 2000

posted posted 03-20-2006 03:13

On the other hand, I would be very interested in knowing if someone manages to fulfill his challenge.

I am completely in support of validation regardless of what else in place, but I think Ob's challenge is perfectly valid.

Also, let's not forget before coming down too hard, that his initial post was pretty much called "stupid" right off the bat. Joking or not, that's bound to get things off on the wrong foot...

FWIW

[1] 2Next Page »



Post Reply
 
Your User Name:
Your Password:
Login Options:
 
Your Text:
Loading...
Options:


« BackwardsOnwards »

Show Forum Drop Down Menu