[thelist] Form Security

Bill Moseley moseley at hank.org
Mon Jul 19 13:32:22 CDT 2010


On Mon, Jul 19, 2010 at 7:29 AM, DAVOUD TOHIDY <dtohidy at hotmail.com> wrote:
>
>  >> Maybe I should be doing the strip tags and slashes too...hmm
> >>> As far as I know yes it is a good idea to use both you mentioned.
> >>>>No, it's not a good idea, because it changes the original data.
>
> I am using php, mysql. So by changing data for example in a search input or
> in a contact form by the user what do you mean happens? why it should be a
> problem? Is it NOT o.k if i get only the text from an input by the user with
> markup?
>

The concepts are the same regardless of programming language and database.

Sure, it's ok to change user data.  For example, if you accept credit cards
it's ok to strip out non-digits if you need only digits (I find it a bit
silly when I enter 1234-2345-3456-4567 and have the site return "Please only
enter only digits".  Just filter out all the non-digits *then* validate that
the number is valid for the credit card type.

But, my comment is if you are stripping things like "DROP TABLE" or "rm -rf"
from user input then you have bigger problems.  If you are worried about "rm
-rf" in user data that means you are not 100% sure that user-supplied data
is NEVER used in a way that might be dangerous.  That is, you are allowing
user data to pass though the shell or have a SQL injection problem.

Likewise, if you are stripping things like <script> then you are not
correctly html-escaping user-data before sending it back. (The exception is
if you allow someone to enter html -- but then things are a bit more tricky,
and best avoided.)

There's room for debate.  I tend to lightly "validate" email addresses  --
but if your goal is to accept only valid email addresses then honestly the
only way to validate them is to actually send mail to the address and get a
confirmation that the user received the mail.  So, for things like that I
would use javascript to say "Hey, this doesn't look like an email address.
 Continue anyway?" to allow the user to fix typos.

Sure, every extra bit of security is probably good, but my argument is that
filtering to remove things like "DROP TABLE", rm -rf, "<strong>", etc. is
misguided and, in my experience, is an indicator that the programmer doesn't
understand the real security issues.

Also, forget about the client side.  That is, forget about how the form is
rendered on the browser -- doesn't matter if you use a drop-down list vs. a
text field.  Hackers need browsers to attack your site.

Your job on the server is to process requests.  That means 1) authenticate
the user, 2) check access to make sure the authenticated user can do the
thing they are asking to do, and 3) validate that the request contains the
data required for the request and is validated.  And by validated I mean if
they user makes a http request of "DELETE /thing/$id" that $id is a thing
that the user has the ability to delete and that $id is a valid format and
expected range of valid ids for "thing" objects.  (My opinion is that DELETE
/thing/;DELETE from users;/  or even /thing/999999999999999999999999/ should
not generate a 500 error because you passed that "key" in a database call,
but returns a 400 or 404 (404 since we know that the id passed is invalid
and thus cannot exist for the user).


> could you provide your suggestion for the code I provided in my original
> post please? with explanation as to why it is better thatn the code I have
> provided please.
>

Oh, my apologies for the discussion above.  Nothing worse than a discussion
of programming w/o any code examples.  The code in your original post:

$name =
> mysql_real_escape_string(strip_tags(stripslashes(htmlentities(trim($_POST['name'])))));


just seems to mangle the poor user's name and has little to do with
security.  What if you create SQL like this?:

   $sql = "select id from user where name = $name";

It's not that you forgot to also strip out all the too-many-to-count
SQL-injection possibilities, it's that you used user-supplied data in a
dangerous way.


Unfortunately, I also do not use PHP.   And I think what you are after is
examples of good way to handle user input and render output, which I don't
know for PHP.  What I suspect is that there are quite a few PHP frameworks
that handle a lot of this including:


   - convert all http requests into valid utf8 (based on the charset of the
   request)
   - manage sessions, authenticate and access control lists
   - a central way to manage input data -- i.e. form validation.  You should
   say "for a POST to this URL a 'name' field is required and it must be of
   type 'text'.  I would think that using $_POST[$field_name] should be handled
   in one place for the entire application not explicitly for every POST URL.
    (Data might not always come in via a $_POST.)
   - Use some kind of database abstraction (ORM, maybe) where you can do
   something like sql( "update users set name = ? where id = ?", $user_id,
   $name )  and not have to worry if $name includes ";drop table users;".
   - Have a way to render output (a View) -- typically this is some kind of
   template engine that provides a way to escape user data.  A request might
   come from a browser or might come from a phone or maybe some day from an API
   request that expects json output so you may want to render the same response
   in different formats.


I'm sure the list goes on but the coffee is wearing out.

Can any of PHP programmers here suggest a nice PHP web framework?


-- 
Bill Moseley
moseley at hank.org


More information about the thelist mailing list