Sanitize contact form?

miguelkp

Member
Messages
304
Reaction score
7
Points
18
Is needed? I don't know too much (near to 'nothing', to be honest) about web security but I heard that SQL injection is only possible in input fields that are used to make SQL connections, like login forms for instance. Thing is: the only part where user can input data is the contact form; my website has no databases, no login system.

Are hackers still able to somehow attack with a simple contact form?

Right now, the only "filter" I'm using is server-side just before the mail is sent (in a PHP file that is called via ajax): strip-tags() function:
PHP:
	$allowedTags='<p><strong><em><u><h1><h2><h3><h4><h5><h6><img><li><ol><ul><span><div><br><ins><del>';  
	$sanitized = strip_tags($formValues->message, $allowedTags);

Would this be enough? Better to use plugins like HTML Purifier to be sure?
 

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
While you can't have SQL injection if SQL isn't used, SQL isn't the only thing vulnerable to injection attacks. Injection happens whenever user-supplied data is interpolated directly into statements in some formal language. As a consequence, you must consider injection for outgoing data, and only for the formats the data will go through until it's back in the same system you're examining (here, PHP). If the data will later be processed further, you shouldn't consider injection until then; for example, don't encode data using HTML character entities if all you're doing is storing it in a database; the HTML entity encoding should only happen when outputting the data in HTML. Similarly, when preparing data from a contact form, it's likely to go through SMTP, then possibly displayed in a web browser, so you'd have to consider injection vulnerabilities in both, but no more. To prevent injection, the user data should be escaped/quoted, or be kept separate (as with prepared statements).

Read Re: Issues regarding Mysql Injection and PDO and Programmatic Mutualism for more on injection in general.

Cross-site scripting is a form of HTML injection, which (as you've at least partially realized) is a concern. As stated in the docs, strip_tags doesn't alter any attributes, so the contact form could still be vulnerable to XSS. This vulnerability should be mitigated by the protection against XSS provided by most webmail readers; however, that security isn't guaranteed. Safer approaches would be to use a parsing HTML sanitizer (as you mention) or quoting with (e.g.) htmlspecialchars. In addition, you can use an alternate markup language (Markdown, for instance) to allow for formatting.
 

bulletcleaners25

New Member
Prime Account
Messages
19
Reaction score
1
Points
0
There are a few things when looking at websecurity especially when your using MySQL and Cookies for Login. Not only do you need to look out for SQL Injection but XSS (Cross Site Scripting), so sanitizing any data you OUTPUT on a page that might not necessarily be user inputted. ANY $_GET data should be sanitized and ALL $_POST data from forms should be sanitized, not just custom data from users, because using tools such as Tamper Data (firefox addon) you are able to change any value (select boxes, check boxes etc.) or even creating false POST data to send to your server is relatively easy if you know what your doing.
 

descalzo

Grim Squeaker
Community Support
Messages
9,373
Reaction score
326
Points
83
1 If you are going to use any user input in any part of the headers, be careful. ie, don't do it. Don't use the input for "To", "From" or "Subject".

2. Just the body of the message? You want them to send you HTML? Why? If not, strip out all HTML markup and then remove any occurrences of '&#' in what remains.
 

miguelkp

Member
Messages
304
Reaction score
7
Points
18
Thanks, misson. I've carefully read your entire post (worth its weight in gold) and the links you put, except the 'Programmatic Mutualism' one :( It's in a .co.cc domain and my antivirus block it. Maybe later I'll give it a try, temporarily disabling the AV.

So, I'm forgetting about SQL injection in order to concentrate on possible cross-site scripting attacks.
If I understood it well, the main problem when someone try any kind of injection is not storing the injected input, but reading that injected info and outputting it in the browser, isn't it?
Right now, my website doesn't pass parameters between PHP pages. So I think we can also forget those 'Reflected XSS Attacks', according to what I could read in the owasp.org link.
In my particular case, the problem appears (if I don't filter at all the input data) when I open the 'infected' mail sent by the user in my mail client. That is, 'Stored XSS Attacks', right?

Now that (I think) we're delimiting the problem, this portion of your post got my attention:
Cross-site scripting is a form of HTML injection, which (as you've at least partially realized) is a concern. As stated in the docs, strip_tags doesn't alter any attributes, so the contact form could still be vulnerable to XSS. This vulnerability should be mitigated by the protection against XSS provided by most webmail readers; however, that security isn't guaranteed.

The contact form that we are talking about send emails to a GMail account in HTML format. Then I supposed GMail has its own filters (it's Google, for Kobol's sake! XD) and wanted to try some kind of XSS attack without sanitizing anything. So in the 'message' field I put this, reading various XSS guides including the one you put:

HTML:
<div style="background-image: url(javascript:alert('XSS_1'))">
	Testing, <strong>testing</strong>
</div>
<script>alert('XSS_2');</script>
<span onLoad=alert('XSS_3')>Span testing</span>

Then I opened the sent email and the output was simply:

Testing, testing

alert('XSS_2');

Span testing

Not even a single JS pop-up alert window. Can I be sure that we are safe from most common direct XSS attacks? Or did I make it the wrong way and the experiment is not valid?



There are a few things when looking at websecurity especially when your using MySQL and Cookies for Login. Not only do you need to look out for SQL Injection but XSS (Cross Site Scripting), so sanitizing any data you OUTPUT on a page that might not necessarily be user inputted. ANY $_GET data should be sanitized and ALL $_POST data from forms should be sanitized, not just custom data from users, because using tools such as Tamper Data (firefox addon) you are able to change any value (select boxes, check boxes etc.) or even creating false POST data to send to your server is relatively easy if you know what your doing.

Thank you too for your comment.
Fortunately, I don't echo neither $_POST nor $_GET info in the website. The only part where that type of parameters are even used is the contact form and it's used through jFormer (jQuery form plugin) via ajax I think. Direct from user input (or "other" ways) to my e-mail. That info is not printed anywhere.
I think (and hope) that this kind of reflected attack will not affect my website, as I stated before.




1 If you are going to use any user input in any part of the headers, be careful. ie, don't do it. Don't use the input for "To", "From" or "Subject".
2. Just the body of the message? You want them to send you HTML? Why? If not, strip out all HTML markup and then remove any occurrences of '&#' in what remains.
1. :S Right now, "From" and "Subject" are user input. Anyway, "From" is supposedly validated client-side and server-side, and has to be a string in a "user@domain.com" style. "Subject" is right now 'sanitized' via strip_tags, so I'm still vulnerable to attacks via tag's attributes as misson mentioned. I'm planning to make it only alpha-numerical + spaces. No punctuation, no symbols. Or directly getting rid of it, it's not neccessary at all, now that you mention it.
2. The body is in HTML right now just because I'm planning to use a WYSIWYG editor that automatically converts input to HTML. What I don't know right now is if it sanitizes input data in any way. If it doesn't I would plan to use HTML Sanitizer.



Unless, of course, you tell me that the small experiment I did before (see above, in response to misson) means we are safe.



Thanks for all your informations and comments. I'm learning a lot.
 

bulletcleaners25

New Member
Prime Account
Messages
19
Reaction score
1
Points
0
You should try multiple examples to see how they filter it cause at the moment they are either removing certain html tags or between < and > so if I was trying to find an exploit in your site I would do things like

HTML:
<scr<script>ipt> - Removes <script> and you are left with <script> still.
<ScRiPt> - deals with case insensitive defense
<body onload="javascript:alert('test');"> - this can be used with alot of tags and you can try it multiple ways, without quotations, semi colon. Should also try JaVaScRiPt for case insensitive defense 
<img src="javascript:alert('test')">
Also check for iframe
<iframe src="http://www.somesite.com.au/xssattack.php"></frame>

These are pretty old and probably not supported with most browsers these days but it's still good to check. IF you don't know much about XSS and SQL Injection look up Cheat Sheets on google and look for newer methods and check to see if you can bypass your filters.
 

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
Thanks, misson. I've carefully read your entire post (worth its weight in gold)
Considering that the internet doesn't weigh anything...

and the links you put, except the 'Programmatic Mutualism' one :( It's in a .co.cc domain and my antivirus block it. Maybe later I'll give it a try, temporarily disabling the AV.
I wrote the second mostly to focus and expand on the concept of host vs embedded languages from the first link. About the only new information is a section on the problems of "</script>" embedded in JS embedded in HTML. It also has a few more examples and tries to distinguish things more clearly. You can give it a pass.

If I understood it well, the main problem when someone try any kind of injection is not storing the injected input, but reading that injected info and outputting it in the browser, isn't it?
For HTML injection, exactly. In general, injection issues arise when outputting data in a particular format, not when storing the data, and the injection occurs when the malformed data is consumed. You want to protect the consumer and not pass it bad data. You could consider injection protection to be a consequence of Postel's Robustness Principle (data validation and sanitization are more obviously consequences).

In my particular case, the problem appears (if I don't filter at all the input data) when I open the 'infected' mail sent by the user in my mail client. That is, 'Stored XSS Attacks', right?
Right again, along with the potential e-mail header injection that I hinted at and descalzo specifies.

The contact form that we are talking about send emails to a GMail account in HTML format. Then I supposed GMail has its own filters (it's Google, for Kobol's sake! XD) and wanted to try some kind of XSS attack without sanitizing anything. [...]
Not even a single JS pop-up alert window. Can I be sure that we are safe from most common direct XSS attacks? Or did I make it the wrong way and the experiment is not valid?
Google may have a lot of money, talent and experience to produce a very safe webmail service, but that's not a guarantee of security. Your contact form needs to be secure by design, which means (in part) limiting what is considered trusted to only what you can actually trust, only what is provably secure. There may be an as-yet undiscovered (or unpublished) vulnerability in Google mail that allows for XSS in e-mails. It's been vulnerable in the past.

1. :S Right now, "From" and "Subject" are user input. Anyway, "From" is supposedly validated client-side and server-side, and has to be a string in a "user@domain.com" style.
As an abuse prevention measure, the "From" address for any e-mail sent via the X10 servers should be a valid local e-mail address, else it will get blocked. If you're using Google's mail server to send the e-mail, this restriction doesn't apply. However, it's still be a good idea to use an e-mail address on the sending mail server for the "From" address, and use the address supplied by the person in a "Reply-to" header.

"Subject" is right now 'sanitized' via strip_tags, so I'm still vulnerable to attacks via tag's attributes as misson mentioned. I'm planning to make it only alpha-numerical + spaces. No punctuation, no symbols. Or directly getting rid of it, it's not neccessary at all, now that you mention it.
As far as I know, the "Subject" header isn't a vector for injection vulnerabilities, since it can only hold plain text (in contrast to the message body). However, stripping tags shouldn't generally hurt (unless someone is sending feedback about broken HTML), and there could always be an incredibly broken webmail client that allows HTML in subject lines (which is problematic beyond injection vulnerabilities). I'm on the fence about his one, myself.

Disallowing all punctuation goes too far. It's not a very usable design, and doesn't gain you anything in terms of security over other approaches.
 
Last edited:

miguelkp

Member
Messages
304
Reaction score
7
Points
18
Hahaha, The IT crowd's best moment ever.

I'm going to study everything you have posted, dudes.

My conclusion right now is that probably my final approach will be let users put whatever they want (I actually liked that: "Be liberal in what you accept, and conservative in what you send.") in name, subject and message (message will be a WYSIWYG textarea with HTML support; don't know which one yet but probably lwrte) and only 'pre-validate' the e-mail input field.
Just before sending the message, sanitize name, subject and message with HTML Purifier, since it seems pretty robust and it's specifically designed to counter XSS attacks, as far as I know.

BTW, I made some tests and a good bunch of the e-mails went directly to spam folder so "From" header will be the same GMail account as the recipient (both hardcoded). Then, the e-mail that user inputs will be programatically added to the mail's body before sending it (or maybe the 'Reply-to' header you mentioned; I'll try different things here)

Thanks again. Tomorrow will be a long day XD
 
Top