{"id":2459,"date":"2016-05-13T10:03:04","date_gmt":"2016-05-13T17:03:04","guid":{"rendered":"http:\/\/www.wellgolly.com\/?p=2459"},"modified":"2016-05-13T10:03:04","modified_gmt":"2016-05-13T17:03:04","slug":"more-thoughts-on-sql-injection-attacks","status":"publish","type":"post","link":"https:\/\/www.wellgolly.com\/?p=2459","title":{"rendered":"More Thoughts on SQL Injection Attacks"},"content":{"rendered":"<p>As I discussed in an earlier post, my sites are frequently attacked by malicious actors trying to get into my database by using SQL injection techniques. I stopped most of them by doing input validation and if the input fails validation, returning a 404 not found. I didn\u2019t do this on all of my pages so from time to time they find a page that does\u201dt fail with bad input and send thousands of page requests to it.<\/p>\n<p>I recently updated my sites and took the opportunity to familiarize myself with the latest best practices for mitigating attacks. I added a line to my database initialization script, sanitize all inputs, and use either prepared statements or queries that use whitelisted terms. Here\u2019s my current initialization script.<br \/>\n<pre><code class=\"preserve-code-formatting\">\n&lt;?php\n\n$user = &#039;mysql_user&#039;;\n$pass = &#039;supersecurepasswors&#039;;\n$host = &#039;localhost&#039;;\n$db_name = &#039;website_database&#039;;\n\ntry {\n&nbsp;&nbsp;&nbsp;&nbsp;$dbWG = new PDO(&quot;mysql:host=$host;db_name=$dbname&quot;, $user, $pass, array(PDO::MYSQL_ATTR_INIT_COMMAND =&gt; &quot;SET NAMES utf8&quot;) );\n&nbsp;&nbsp;&nbsp;&nbsp;$dbWG-&gt;setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );\n&nbsp;&nbsp;&nbsp;&nbsp;$dbWG-&gt;setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);\n&nbsp;&nbsp;&nbsp;&nbsp;$dbWG-&gt;setAttribute(PDO::ATTR_EMULATE_PREPARES, false);\n}\ncatch(PDOException $e) {\n&nbsp;&nbsp;&nbsp;&nbsp;$e-&gt;getMessage();<\/code><\/pre><\/p>\n<p>The only way I found to get attacks to stop is to return a 404 not found message to the bot. After a few tries they usually give up. Otherwise they will try thousands of times. <\/p>\n<p>So first I sanitize the input. Here\u2019s a simple one where the input has to be a digit:<br \/>\n<pre><code class=\"preserve-code-formatting\">\n$number_of_letters = (isset($_GET[&#039;n&#039;]) ? $_GET[&#039;n&#039;] : 1);\nif ( !is_numeric($number_of_letters) ) {\n&nbsp;&nbsp;&nbsp;&nbsp;include_once(&#039;dieInAFire.inc&#039;);\n}<\/code><\/pre><\/p>\n<p>I have a $showError variable in my header that lets me turn off and on information on attacks. I usually leave it on and peruse the error log to make sure legitimate requests aren\u2019t accidentally blocked. I wrote this include file to use after sanitizing inputs fails.<br \/>\n<pre><code class=\"preserve-code-formatting\">\n&lt;?php\n$url = isset($_SERVER[&#039;REQUEST_URI&#039;])&nbsp;&nbsp;? $_SERVER[&#039;REQUEST_URI&#039;]&nbsp;&nbsp;: &#039;&#039;;\n$ref = isset($_SERVER[&#039;HTTP_REFERER&#039;]) ? $_SERVER[&#039;HTTP_REFERER&#039;] : &#039;&#039;;\n$ip&nbsp;&nbsp;= isset($_SERVER[&#039;REMOTE_ADDR&#039;])&nbsp;&nbsp;? $_SERVER[&#039;REMOTE_ADDR&#039;]&nbsp;&nbsp;: &#039;&#039;;\n\nif ($showError == TRUE) {\n&nbsp;&nbsp;&nbsp;&nbsp;error_log(&quot;Long string in $calledFileName: URL is $url and IP is $ip &amp; ref is $ref&quot;);\n}\nheader(&quot;HTTP\/1.0 404 Not Found&quot;);\ndie();\n?&gt;<\/code><\/pre><\/p>\n<p>Note that this has to be called before the <body> statement.<\/p>\n<p>If it is a legitimate request, I make then use a prepared statement to execute it.<br \/>\n<pre><code class=\"preserve-code-formatting\">\n$qry.=&nbsp;&nbsp;&quot;HAVING COUNT(sorted_letters) &gt; :number_of_letters &quot;;\n\n$stmt = $dbWG-&gt;prepare($qry);\n$stmt-&gt;bindParam(&#039;:number_of_letters&#039;, $number_of_letters);\n$stmt-&gt;execute();<\/code><\/pre><\/p>\n","protected":false},"excerpt":{"rendered":"<p>As I discussed in an earlier post, my sites are frequently attacked by malicious actors trying to get into my database by using SQL injection techniques. I stopped most of them by doing input validation and if the input fails validation, returning a 404 not found. I didn\u2019t do this on all of my pages &hellip; <a href=\"https:\/\/www.wellgolly.com\/?p=2459\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">More Thoughts on SQL Injection Attacks<\/span><\/a><\/p>\n","protected":false},"author":6,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[27],"tags":[],"class_list":["post-2459","post","type-post","status-publish","format-standard","hentry","category-mysql"],"_links":{"self":[{"href":"https:\/\/www.wellgolly.com\/index.php?rest_route=\/wp\/v2\/posts\/2459","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.wellgolly.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.wellgolly.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.wellgolly.com\/index.php?rest_route=\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/www.wellgolly.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2459"}],"version-history":[{"count":0,"href":"https:\/\/www.wellgolly.com\/index.php?rest_route=\/wp\/v2\/posts\/2459\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.wellgolly.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2459"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.wellgolly.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2459"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.wellgolly.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2459"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}