Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Prevent SQL Injection

by davidj01 (Novice)
on Apr 07, 2008 at 15:00 UTC ( [id://678757]=perlquestion: print w/replies, xml ) Need Help??

davidj01 has asked for the wisdom of the Perl Monks concerning the following question:

Hi, Would converting all meta characters (eg. | . ( ! etc.) to an html representation that is &#[ASCII CODE}; before saving to the mysql table prevent SQL Injection and good way to prevent the use of meta characters in any call using system or open (eg sending email). Example: Thus a single quote will be represented by & # 39; etc. If I need any these characters, lets say to send email, I would simply reverse the conversion for the @ and period. I'm interested in feedback. Thanks David J.

Replies are listed 'Best First'.
Re: Prevent SQL Injection
by moritz (Cardinal) on Apr 07, 2008 at 15:10 UTC
    The right way to prevent SQL injection is to use placeholders and DBI:
    use DBI; my $dbh = DBI->connect(...); # WRONG my $insert = $dbh->prepare("INSERT INTO my_table VALUES(my_col +umn)"); # Thanks Narveson! my $insert = $dbh->prepare("INSERT INTO my_table (my_column) VALUES( ? + )"); my $evil_string = q{"'|?°*;--}; $insert->execute($evil_string); # no problem

    HTML escaping isn't the universal solution because different output formats use different quoting mechanisms, and your example system call wouldn't know that ' is a single quote.

    So for all other applications you have to escape individually, so storing quoted strings in the DB isn't really helpful.

      Shouldn't the example include a placeholder?

      my $insert = $dbh->prepare("INSERT INTO my_table (my_column) VALUES( ? )");
      Hi, >different output formats use different quoting mechanisms, >and your example system call wouldn't know that ' is a >single quote. For example? Thanks so far David J
        For example, one day you might want to produce PDFs from your database instead of HTML, and I suspect PDF has a completely different escaping mode.

        When you escape for the shell you have to insert a backslash before a single quote to escape it.

        Very silly example: You want to use grep (the command) to search for a substring in a large text file. If you search for the numeric entity, while the text file contains the literal character.

        File names have a completely different syntax. If you escape a file name under unix, you have to escape whitespaces - but surely you don't wan to escape all whitespaces in your database? (it would kill a word based full text index, for example). Even when you do HTML escape only, you have to very careful: there's more than one way to escape most characters. Many characters have names, so you can use ä, and numeric Ӓ (and I think also a hexadecimal escape as well). So if your comparisons for text equality should really work, you have to define a canonical form and translate everything into that form. D'oh.

        This is off-topic, but is intended to be helpful to you in the future. You had posted:
        Hi, >different output formats use different quoting mechanisms, >and your example system call wouldn't know that ' is a >single quote. For example? Thanks so far David J
        If you had made use of <blockquote> and </blockquote>, your post would have looked like:
        Hi,
        different output formats use different quoting mechanisms, and your example system call wouldn't know that ' is a single quote.
        For example? Thanks so far David J
        This is slightly more readable. (Remember, if it looks odd to you when you Preview a post, imagine how it looks to us.)
Re: Prevent SQL Injection
by Errto (Vicar) on Apr 07, 2008 at 17:59 UTC

    In general you should store whatever data you receive in its original form, and not encoded for a particular output. For example, what if you need to send that text in a plain text email instead of an HTML email? What if you want to dump a bunch of rows of text into CSV?

    Then when you need to use that text in a particular context, you can encode it appropriately. When you're sending it to the database, you should use placeholders, or if you must, use the quote method in DBI. When you're outputting it as HTML, then HTML-encode it. When you're passing it to a system call, apply shell escapes to it (is there a standard method for that?). If you're using it in a regex, use quotemeta or the \Q escape. And so on.

    Update: andreas1234567's reply below is of course also correct.

      In general you should store whatever data you receive in its original form, and not encoded for a particular output.
      Yes, provided that the data is properly validated, e.g. as described in Data Validation (owasp.org).
      --
      Andreas
      Hi,

      I've been updating my programs to use only place holders. I'm now looking at the next step.

      "When you're outputting it as HTML, then HTML-encode it."

      My question is naive but could you provide a couple of examples in order to clearly define what is meant by HTML-encode and in these examples show how one is handling any insecurities or difficult to display characters (I presuppose the single and dbl quote)

      Thank-you
      David J.
Re: Prevent SQL Injection
by andreas1234567 (Vicar) on Apr 08, 2008 at 07:51 UTC

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://678757]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (4)
As of 2024-04-24 21:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found