Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

PHP - thorough form validation/security?

Options
  • 03-05-2011 2:51pm
    #1
    Closed Accounts Posts: 27,857 ✭✭✭✭


    Hey folks,

    I'm working on a site at the moment which relies on user submissions, and I want to make sure that I have everything covered regarding security vulnerabilities here.

    I'm going to implement some sort of JS/jQuery form validation on the front-end to ensure that values are entered and valid, but once it's submitted to the server, I'm wondering what PHP functions should I use that would pretty much ensure that it's not possible to screw up the site with SQL injection, etc.?

    If for example I just used the following, would it be okay?
    $name = mysql_real_escape_string(addslashes($_POST['name']));
    

    Should I use htmlentities() too? What about htmlspecialchars() ?

    Basically I'm wondering what best practice/industry standard is... If your manager asks you to develop a site that relies on user submissions, what are the minimum validation functions you use to ensure the site is secure? Which function, if omitted from your code, would you be sacked for? :D

    Cheers!

    D


Comments

  • Closed Accounts Posts: 27,857 ✭✭✭✭Dave!


    No PHP developers around??? :D


  • Registered Users Posts: 3,140 ✭✭✭ocallagh


    I think those two functions are fine - do you need them both though?

    I generally use mysql_real_escape_string(trim($data))

    If you want to be 100% thorough, http://pastie.org/1682584


  • Closed Accounts Posts: 27,857 ✭✭✭✭Dave!


    ocallagh wrote: »
    I think those two functions are fine - do you need them both though?

    I generally use mysql_real_escape_string(trim($data))

    If you want to be 100% thorough, http://pastie.org/1682584
    Mind me asking if you work with PHP professionally? I would have thought that those two would be fine, but I want to make sure really, because I don't know much about security.


  • Registered Users Posts: 68,317 ✭✭✭✭seamus


    Yeah, you don't need both addslashes() and mysql_real_escape_string(), the latter on its own works just fine.

    What I would advise is to write your data validation without the javascript. It's prone to errors on the client side (corrupt caches, etc) and can be switched off and used to send nonsense to your script.

    Data validation isn't necessarily just about protecting the integrity of your data, but also the accuracy of it.

    For example, if your form has a date field in it, how do you ensure that the user has entered the likes of 04/05/2011 and not, "Mary had a little lamb"? When that submission is reviewed in six month's time, the database will have a date value of 01/01/1970 and it will be your application's fault for not collecting the information correctly. :)

    Javascript will capture 99% of cases, so that in the date field, you could use a JScript calendar to force the selection - or use drop-downs for the Day/Month/Year rather than a text field. But if the javascript fails or someone decides to act the mick, then you could end up with garbage in your database.

    I use regular expressions primarily. So if I have a free-form text field that is mandatory, the regexp /^s*$/ will match any entry which is empty or which only contains whitespace - some people will try to bypass a required field by hitting space or return a couple of times.

    How strict you get on your regular expressions is up to you. If something is a free-text field, there's only so much validation you can do.

    My general rule is to check everything. Drop-downs have a finite set of values, so users can only submit a valid option right? Wrong! :) Simple tools allow drop-down lists to be edited before submitting a form. If the value should be part of a fixed list, always ensure that the value submitted is in that fixed list.

    If you're using hidden fields to include additional fixed data in your form, these too should be checked, because the user can edit it. You could have a form where users edit their own profile, and a hidden field in that form is the userid. Malicious person changes the value in the hidden field to "1", your script doesn't check what's been submitted, and bam, the user now owns your site's administrator account. :)

    What I do is maintain an array of errors. Declare an empty array at the top of the script. Then check all your inputs. For every input which has an error, add a new item to the array containing the error text.

    Then when you've finished checking, if the array is empty, you have no errors and you can proceed. If the array isn't empty, you go back to the form and print out all of the errors. No javascript required.


  • Closed Accounts Posts: 27,857 ✭✭✭✭Dave!


    Secretly I was hoping that you'd post, seamus :p Nice one

    I'm just using the JS to check that all the mandatory fields have data in them, and to check (using a regular expression) that a valid email address is entered. Should I not bother with this? It seems to be used fairly extensively on most sites. I'll verify the integrity of the input once it's submitted to the server.

    Do you happen to have any code that you could copy and paste for me? :D I'd like to have some sort of template which I could tweak, which is as secure as a manager would expect it to be before being released.


  • Advertisement
  • Registered Users Posts: 68,317 ✭✭✭✭seamus


    Nothing that I would be happy to release to the scrutiny of professional coders, which I am not. :)

    On javascript, I still largely maintain that your site should work without it, it should only be used for "nice to have" features and the like. This depends of course. The likes of Google have the resources to develop multiple versions of their site depending on the speed of connection, with/without javascript, etc.

    I would say that it's acceptable in this day and age for a site to simply not work unless javascript enabled - but it should be 100%. If javascript is off or broken and is critical to the site, then the site should kick the user out.* But if it's not critical, then the site should incorporate server-side functions to account for those situations where javascript falls down.

    Javascript is good in that it can tell you immediately if there's an error and can check data on-the-fly. But doing the check on submit with javascript doesn't really provide any benefit to the user except maybe to be slightly quicker than waiting for a submit-return from the server.

    One internal site we have here has two forms, one is the earlier version with only javascript checks (I didn't write it!) and one is the later version, where I removed javascript checks completely. Aside from the errors that the earlier version keeps plonking into the database, the non-javascript check has one major benefit:
    In javascript, you can really only display one error at a time. So the user hits "Submit" - "The field 'Name' cannot be blank". They correct it, Submit, "This does not appear to be a valid email address", etc.
    Irritating. With the server-side check, they submit once and then get shown all of the errors at the same time.

    To make a site look modern and quite professional, do javascript checking on the fly. You know those sites where you enter a value into a field and immediately shows a tick or a cross for valid/invalid data? Like that. It's unintrusive, clean and shows the user which fields are incorrect without error pop-ups boxes or the like.

    *I might get slated for that, but in reality it's only a tiny niche of hard-nosed nerds who suf the web with javascript defiantly disabled


  • Closed Accounts Posts: 27,857 ✭✭✭✭Dave!


    seamus wrote: »
    Nothing that I would be happy to release to the scrutiny of professional coders, which I am not. :)

    ...

    To make a site look modern and quite professional, do javascript checking on the fly. You know those sites where you enter a value into a field and immediately shows a tick or a cross for valid/invalid data? Like that. It's unintrusive, clean and shows the user which fields are incorrect without error pop-ups boxes or the like.

    You can PM me, I'm no professional! :p ...yet

    The JS checking I'm doing is on the fly and it's working decent enough. The code is a bit messy (something I'll have to work on), but I'm using the jQuery .blur() function, which triggers a validation function when the element loses focus/is deselected.

    Some food for thought above, thanks for that!


  • Closed Accounts Posts: 7,145 ✭✭✭DonkeyStyle \o/


    Read up on prepared statements, it's a barrier to people sticking their own sql into your queries. Also +1 on regular expressions.


  • Registered Users Posts: 3,140 ✭✭✭ocallagh


    Dave! wrote: »
    Mind me asking if you work with PHP professionally? I would have thought that those two would be fine, but I want to make sure really, because I don't know much about security.

    Yes I do work with PHP professionally. In regards Javascript, I would never rely on it for any proper validation. It should be used for the user's convenience and to minimize trips to the server, but your site (and more importantly your server side validation) should work without it.

    On the server, as Seamus said, it really depends on the data but my general rule of thumb is to filter out most stuff first (this depends on the data type, but mostly only allow certain characters), then validate it (dropdowns, emails, integers etc) and then escape dangerous chars that you allow like comma's.

    If you are storing html from a rich text editor you need to do be very careful. Filter it as best you can for XSS and then only allow certain tags, and then convert them to html entities with htmlspecialchars.

    Or the ultimate security hole is accepting uploads and processing them. The dompdf library, specifically import.php springs to mind as something I won't forget too soon!


  • Registered Users Posts: 981 ✭✭✭fasty


    Oh god, the domdpf library... That's gonna give me a flashback...

    What do you do about file upload validation ocallagh?

    I learned from my dayjob that you should never trust user input. I'm also glad that people thing SQL injection can only happen on websites :D

    Generally if you escape everything, use prepared statements in SQL and validate inputs against their expected type, i.e. a number, a date, an email, you're well on the way.


  • Advertisement
  • Registered Users Posts: 3,140 ✭✭✭ocallagh


    fasty wrote: »
    Oh god, the domdpf library... That's gonna give me a flashback...

    What do you do about file upload validation ocallagh?

    I learned from my dayjob that you should never trust user input. I'm also glad that people thing SQL injection can only happen on websites :D

    Generally if you escape everything, use prepared statements in SQL and validate inputs against their expected type, i.e. a number, a date, an email, you're well on the way.
    I actually haven't done this in a while, but a bit of googling and past experience would lead me to the following:

    Filter on file type/size/extnesion (eg allow only doc, jpg, png etc).

    Rename file with encrypted filename and .dat extension.

    Set read permissions only.

    Stick files in dir outside wwwroot (or on separate partition with no-exec) and set htaccess to restrict execution again.

    Insert original filename, original extension and path to physical file into DB.

    Create download.php which accepts original filename as parameter. Check DB for filename. If valid, fetch the file from the disk and force a download (setting original filename/extension) with htaccess and PHP headers. You might also be able to do something with CGI here if you have it enabled

    Also, in download.php I wouldn't start any sessions or anything else.

    You could also manually check uploads before setting a 'valid' flag in the DB.


  • Registered Users Posts: 3,140 ✭✭✭ocallagh


    fasty wrote: »
    Oh god, the domdpf library... That's gonna give me a flashback...
    Yeah, the script that got uploaded through dompdf was actually harmless enough. It was encoded with base64 and wrapped in an eval() function. It was placed in public_html and was executed a number of times. When I decoded the string, it emailed a hotmail account with title 'hacked by xyz'. It had the server IP and a few other details. I assume the hacker has a bot which does all this. They prob wait for such emails and if an IP resolves to a domain which might contain valuable data they go in with the full artillery..


  • Registered Users Posts: 6,501 ✭✭✭daymobrew


    seamus wrote: »
    Data validation isn't necessarily just about protecting the integrity of your data, but also the accuracy of it.
    I used the PHP filter functions in a recent script.
    [PHP]$email = filter_var($_POST, FILTER_SANITIZE_EMAIL);
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
    // email address is okay
    }[/PHP]
    You can use a regex filter too.


  • Closed Accounts Posts: 27,857 ✭✭✭✭Dave!


    Just discovered/realised that I could use AJAX to do some server-side validation! :) Didn't occur to me before

    DOY!!!


  • Registered Users Posts: 297 ✭✭stesh




  • Registered Users Posts: 297 ✭✭stesh


    Dave! wrote: »
    Just discovered/realised that I could use AJAX to do some server-side validation! :) Didn't occur to me before

    DOY!!!

    Don't rely too heavily on using JavaScript for validation on the local side - it is easily disabled in most browsers.


Advertisement