Sanitize contact form?

Discussion in 'Scripts, 3rd Party Apps, and Programming' started by miguelkp, Apr 19, 2012.

  1. miguelkp

    miguelkp Member

    Messages:
    306
    Likes Received:
    7
    Trophy 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?
     
  2. misson

    misson Community Paragon Community Support

    Messages:
    2,572
    Likes Received:
    72
    Trophy 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.
     
  3. bulletcleaners25

    bulletcleaners25 New Member Prime Account

    Messages:
    19
    Likes Received:
    1
    Trophy 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.
     
  4. descalzo

    descalzo Grim Squeaker Community Support

    Messages:
    9,375
    Likes Received:
    327
    Trophy 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.
     
  5. miguelkp

    miguelkp Member

    Messages:
    306
    Likes Received:
    7
    Trophy 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:
    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:

    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?



    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. :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.
     
  6. bulletcleaners25

    bulletcleaners25 New Member Prime Account

    Messages:
    19
    Likes Received:
    1
    Trophy 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.
     
  7. misson

    misson Community Paragon Community Support

    Messages:
    2,572
    Likes Received:
    72
    Trophy Points:
    48
    Considering that the internet doesn't weigh anything...

    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.

    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).

    Right again, along with the potential e-mail header injection that I hinted at and descalzo specifies.

    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.

    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.

    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: Apr 19, 2012
  8. miguelkp

    miguelkp Member

    Messages:
    306
    Likes Received:
    7
    Trophy 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
     

Share This Page