{"id":157,"date":"2009-02-18T16:36:38","date_gmt":"2009-02-18T21:36:38","guid":{"rendered":"http:\/\/mikeconley.ca\/blog\/?p=157"},"modified":"2023-12-20T16:25:22","modified_gmt":"2023-12-20T21:25:22","slug":"sql-injection-prevention-in-php-tip-1","status":"publish","type":"post","link":"https:\/\/mikeconley.ca\/blog\/2009\/02\/18\/sql-injection-prevention-in-php-tip-1\/","title":{"rendered":"SQL Injection Prevention in PHP &#8211; Tip 1"},"content":{"rendered":"<p>It&#8217;s amazing &#8211; I&#8217;ve been going around, Googling for anything with &#8220;index.php?id=&#8221;&#8230;and that&#8217;s really all it takes.\u00a0 Now, granted, SQL Injection isn&#8217;t new, and a lot of the top hits have taken some steps to protect themselves, but if you go deep &#8211; like, Google search page 23 deep &#8211; you&#8217;ll find ones that break if you put a semi-colon after the id # &#8211; and if it breaks, it&#8217;s vulnerable.<\/p>\n<p>So, here&#8217;s my first tip on preventing SQL Injection &#8211; when you&#8217;re asking for an ID number, make sure it&#8217;s a number, and nothing else.  Also consider using prepared statements &#8211; database wrappers like <a href=\"http:\/\/pear.php.net\/package\/MDB2\">MDB2<\/a> for PHP make this easy.<\/p>\n<p>Check this out &#8211; this might be how I would have done it 3 years ago:<\/p>\n<pre>&lt;?php\r\n  \/\/Assume we're already connected to a MySQL database...\r\n  $id = $_GET['id'];\r\n\r\n  $result = mysql_query('SELECT * from pages where id='.$id);\r\n  if (!$result) {\r\n     die('Invalid query: ' . mysql_error());\r\n  }\r\n  ... \/\/Code to print out my result to the page\r\n?&gt;<\/pre>\n<p>I&#8217;d do it this way now:<\/p>\n<p><strong>Note:<\/strong> My use of MDB2 might be a little rusty &#8211; I haven&#8217;t tested this code, and I usually compose RowDataGateway objects with MDB2 to represent my data.\u00a0 So pay more attention to the structure than the actual syntax.<\/p>\n<pre>&lt;?php\r\n  require 'View.php';\r\n  require 'MDB2.php';  \/\/An excellent DB layer from the PEAR libs\r\n\r\n  \/\/Code to set $mdb2 as our DB connection variable\r\n  \/\/See http:\/\/pear.php.net\/package\/MDB2 for details\r\n  $id = $_GET['id'];\r\n\r\n  try {\r\n    if(!is_int($id)) {\r\n      \/\/ID wasn't an int, it's no good, let's bail\r\n      throw new Exception('Could not recognize the id that you passed');\r\n    }\r\n    \/\/ID was an int, let's see if we can find the record\r\n    $sql = 'SELECT * from pages where id=:id\";\r\n    $statement = $mdb2-&gt;prepare($sql);\r\n    $statement-&gt;bindParam('id', $id);\r\n    $result = $statement-&gt;execute();\r\n    if(PEAR::isError($result)) {\r\n      \/\/Uh oh - our result was an error on the PEAR library level\r\n      throw new Exception('There was an error communicating with the database');\r\n    }\r\n    \/\/Insert the database result into the view, render, and die.\r\n    $content = new View('templates\/page.tpl', array('page' =&gt; $result-&gt;fetchOne()));\r\n    $content-&gt;render();\r\n    die;\r\n  }\r\n  catch(Exception $e) {\r\n    \/\/We must have caught an exception - put this into our\r\n    \/\/error page template with the error message, render, die.\r\n    $content = new View('templates\/error.tpl', array('message' =&gt; $e-&gt;getMessage()));\r\n    $content-&gt;render();\r\n    die;\r\n  }\r\n?&gt;<\/pre>\n<p>Yes, it&#8217;s quite a bit more code.  But I feel safer just looking at it.<br \/>\nDid I miss anything on this?  Please post a comment if you\u00a0 notice that I&#8217;ve left a gaping hole.\u00a0 Learning is good.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>It&#8217;s amazing &#8211; I&#8217;ve been going around, Googling for anything with &#8220;index.php?id=&#8221;&#8230;and that&#8217;s really all it takes.\u00a0 Now, granted, SQL Injection isn&#8217;t new, and a lot of the top hits have taken some steps to protect themselves, but if you go deep &#8211; like, Google search page 23 deep &#8211; you&#8217;ll find ones that break [&hellip;]<\/p>\n","protected":false},"author":4,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[5,44,10,51],"tags":[1209,1211,52,53,54],"class_list":["post-157","post","type-post","status-publish","format-standard","hentry","category-computer-science","category-internet","category-php","category-security","tag-php","tag-security","tag-sql","tag-sql-injection","tag-web-applications"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/prmTy-2x","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/mikeconley.ca\/blog\/wp-json\/wp\/v2\/posts\/157","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mikeconley.ca\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mikeconley.ca\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mikeconley.ca\/blog\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/mikeconley.ca\/blog\/wp-json\/wp\/v2\/comments?post=157"}],"version-history":[{"count":15,"href":"https:\/\/mikeconley.ca\/blog\/wp-json\/wp\/v2\/posts\/157\/revisions"}],"predecessor-version":[{"id":3271,"href":"https:\/\/mikeconley.ca\/blog\/wp-json\/wp\/v2\/posts\/157\/revisions\/3271"}],"wp:attachment":[{"href":"https:\/\/mikeconley.ca\/blog\/wp-json\/wp\/v2\/media?parent=157"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mikeconley.ca\/blog\/wp-json\/wp\/v2\/categories?post=157"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mikeconley.ca\/blog\/wp-json\/wp\/v2\/tags?post=157"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}