{"id":1799,"date":"2013-10-17T16:51:35","date_gmt":"2013-10-17T16:51:35","guid":{"rendered":"http:\/\/www.sitekickr.com\/blog\/?p=1799"},"modified":"2013-10-17T23:09:50","modified_gmt":"2013-10-17T23:09:50","slug":"sql-inserts-safe","status":"publish","type":"post","link":"https:\/\/www.sitekickr.com\/blog\/sql-inserts-safe\/","title":{"rendered":"Fun with SQL Injection"},"content":{"rendered":"<p>In case you&#39;re not familiar with SQL injection, you&#39;ll find a crash course below. Then, we&#39;ll have some fun coming up with examples to demonstrate the various ways that your data could be open to an SQL injection attack.<\/p>\n<p>&nbsp;<\/p>\n<h3>The SQL Injection Attack<\/h3>\n<p>SQL injection is essentially the act of providing input to a website or application which contains SQL commands, with the intent of altering or obtain data from a database in a way not intended by the application.<\/p>\n<p>As an example, let&#39;s have a piece of code that uses a query string parameter to pull data from a database.<\/p>\n<p><kbd>http:\/\/www.mysite.com\/getWage.php?employee_code=A8CNDU37<\/kbd><\/p>\n<pre class=\"prettyprint\"><code>SELECT name, wage\r\nFROM employee\r\nWHERE employee_code = &#39;A8CNDU37&#39;;<\/code><\/pre>\n<p>The employee_code is random enough that we&#39;re not to worried about people guessing it, and hence are comfortable pulling a value from the query string.<\/p>\n<p>But, let&#39;s say we used this query string:<\/p>\n<p><kbd>http:\/\/www.mysite.com\/getWage.php?employee_code=A8CNDU37&#39; OR &#39;dummy&#39; = &#39;dummy<\/kbd><\/p>\n<pre class=\"prettyprint\"><code>SELECT name, wage\r\nFROM employee\r\nWHERE employee_code = &#39;A8CNDU37&#39; OR &#39;dummy&#39; = &#39;dummy&#39;;<\/code><\/pre>\n<div>This query string has injected a logical OR into the SQL query where makes the where condition always true. In this case, the attacker is easily able to obtain the name and wage of the first employee in the database.<\/div>\n<div>&nbsp;<\/div>\n<div>Now that you&#39;re comfortable with the term and how hackers make use of it, let&#39;s get to the examples.<\/div>\n<div>&nbsp;<\/div>\n<div>&nbsp;<\/div>\n<div>&nbsp;<\/div>\n<h3>Spoofer&rsquo;s Delight<\/h3>\n<p><img loading=\"lazy\" align=\"right\" alt=\"user agent spoofing\" border=\"2\" class=\"alignright size-full wp-image-1839\" height=\"256\" src=\"http:\/\/www.sitekickr.com\/blog\/wp-content\/uploads\/2013\/10\/browser-spoofing.png\" style=\"padding:5px;margin-left: 5px;\" width=\"256\" srcset=\"https:\/\/www.sitekickr.com\/blog\/wp-content\/uploads\/2013\/10\/browser-spoofing.png 256w, https:\/\/www.sitekickr.com\/blog\/wp-content\/uploads\/2013\/10\/browser-spoofing-150x150.png 150w\" sizes=\"(max-width: 256px) 100vw, 256px\" \/>A good place to start is with server variables. I&rsquo;m talking about <kbd>PHP&#39;s $_SERVER[&#39;x&#39;], ColdFusions&#39;s CGI.X, Python&#39;s REQUEST.get(&#39;x&#39;) <\/kbd>or any variable passed down from the web server for use in your script.<\/p>\n<p>We tend to place a bit more trust in the validity of the data sent from our web server and, in turn, might feel more comfortable inserting this data directly into our database.<\/p>\n<p>Don&#39;t get too cozy with server variables, as many of them depend on the information passed by the web browser. One such variable, the <kbd>HTTP_USER_AGENT<\/kbd>.<\/p>\n<p>You might be tempted to run a query like this, using PHP as an example:<\/p>\n<pre class=\"prettyprint\"><code>$sql = sprintf(&quot;INSERT INTO contact_form (user_id, email, browser)\r\n                VALUES (%d, &#39;%s&#39;, &#39;%s&#39;)&quot;,\r\n                $_SESSION[&#39;user_id&#39;],\r\n                mysql-&gt;real_escape_string($_POST[&#39;email&#39;],\r\n                $_SERVER[&#39;HTTP_USER_AGENT&#39;])<\/code><\/pre>\n<p>&nbsp;<\/p>\n<p>But what happens if a funny guy decides to alter the user agent string sent by his browser (using any of a myriad tools available to do so)?<\/p>\n<p><kbd>HTTP_USER_AGENT = Mozilla &#39;); DELETE FROM contact_form WHERE &#39;1&#39; NOT IN (&#39;<br \/>\n\t<\/kbd><br \/>\n\tYou can delete all your data yourself, or you can wait until a human or bot to spoof it&rsquo;s user agent string and do it for you!<\/p>\n<p>&nbsp;<\/p>\n<h3>Man on the Inside<\/h3>\n<p><img loading=\"lazy\" align=\"left\" alt=\"sql-injection-delayed\" border=\"2\" class=\"alignleft size-full wp-image-1841\" height=\"256\" src=\"http:\/\/www.sitekickr.com\/blog\/wp-content\/uploads\/2013\/10\/sql-injection-delayed.png\" style=\"padding:5px;margin-right: 5px;\" width=\"256\" srcset=\"https:\/\/www.sitekickr.com\/blog\/wp-content\/uploads\/2013\/10\/sql-injection-delayed.png 256w, https:\/\/www.sitekickr.com\/blog\/wp-content\/uploads\/2013\/10\/sql-injection-delayed-150x150.png 150w\" sizes=\"(max-width: 256px) 100vw, 256px\" \/>You may also think that data coming <strong>out <\/strong>of your database is safe, and there&#39;s little need to check it for SQL injection. But, in a typical web scenario, who is putting data <strong>into <\/strong>your database? Users!<\/p>\n<p>If an even funnier guy decides to create a username on your website:<\/p>\n<p><kbd>jerryseinfeld2&#39; OR <br \/>\n\tusername IS NOT NULL&nbsp;OR &#39;x&#39; = &#39;<\/kbd><\/p>\n<p>Inside this user&#39;s account is a nice interface where it lists previous quotes and estimates provided for the account.<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"prettyprint\"><code>SELECT quote_id, material_list, total_estimate\r\nFROM quotes\r\nWHERE username = &#39;jerryseinfeld2&#39; OR username IS NOT NULL OR &#39;x&#39; = &#39;&#39;<\/code><\/pre>\n<p>It may be a pain in the neck for this guy to log in to your site next time, but he doesn&rsquo;t care. He just found out not only what materials his competitor is requesting quotes on, but also that his competitor is getting a lower rate!<\/p>\n<div>&nbsp;<\/div>\n<h3>The Free Pass<\/h3>\n<p><img loading=\"lazy\" align=\"right\" alt=\"SQL injection union all\" border=\"2\" class=\"alignright size-full wp-image-1847\" height=\"256\" src=\"http:\/\/www.sitekickr.com\/blog\/wp-content\/uploads\/2013\/10\/sql-injection-union-all.png\" style=\"padding:5px;margin-left: 5px;\" width=\"256\" srcset=\"https:\/\/www.sitekickr.com\/blog\/wp-content\/uploads\/2013\/10\/sql-injection-union-all.png 256w, https:\/\/www.sitekickr.com\/blog\/wp-content\/uploads\/2013\/10\/sql-injection-union-all-150x150.png 150w\" sizes=\"(max-width: 256px) 100vw, 256px\" \/>The SQL Union statement struts around disguised as an innocent way to combine the results of two select statements. But take off that mask and you have what amounts to a free pass for any hacker to retrieve data from any table in your database!<\/p>\n<p>Here&#39;s how a real miserable hacker might attempt to pull protected data from a table completely unrelated to the task at hand.<\/p>\n<p>Let&#39;s build off of the example above, where the hacker supplies a <em>username <\/em>which contains SQL statements:<\/p>\n<p><kbd>x193ajx832jx&#39; UNION ALL SELECT social_security_number, &#39;&#39;, &#39;&#39; FROM users WHERE username = &#39;competitor<\/kbd><\/p>\n<p>Again, using the same example as above, only this time we&#39;re going to attack the users table. We want to grab the social security number of any <em>username <\/em>we choose.<\/p>\n<p>Because we provide a totally random value for <em>username <\/em>in the first select statement, we&#39;re guaranteed <strong>not <\/strong>to get a record from it. This means that we&#39;ll get the first record from the <strong>second <\/strong>select statement, which is targeted at a specific <em>username<\/em>.<\/p>\n<pre class=\"prettyprint\"><code><span style=\"font-family: monospace;\">SELECT quote_id, material_list, total_estimate<\/span>\r\n<span style=\"font-family: monospace;\">FROM quotes<\/span>\r\n<span style=\"font-family: monospace;\">WHERE username = &#39;<\/span>x193ajx832jx&#39; \r\n\r\nUNION ALL \r\n\r\nSELECT social_security_number, &#39;&#39;, &#39;&#39; FROM users WHERE username = &#39;competitor<span style=\"font-family: monospace;\">&#39;<\/span><\/code><\/pre>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<h3>How to Prevent SQL Injection<\/h3>\n<h4>Your Language Has You Covered<\/h4>\n<p>Thieves have been around as long as their has been something to steel, and SQL injection has been around as long as SQL. This means that just about any language has methods for protecting your queries against SQL injection.<\/p>\n<ul>\n<li>PHP has prepared statements and the real_escape_string function.<\/li>\n<li>ColdFusion has the &lt;cfqueryparam&gt; tag.<\/li>\n<li>Python has formatting built directly into the execute function.<\/li>\n<\/ul>\n<p>A more complete list of languages along with their SQL injection protection mechanisms can be found here: <a href=\"http:\/\/bobby-tables.com\/asp.html\">http:\/\/bobby-tables.com\/asp.html<\/a><\/p>\n<p>&nbsp;<\/p>\n<h4>Your Database Can Help<\/h4>\n<p>In many situations, it can be helpful to have three different database user accounts with different privilege levels. One account can only SELECT, the other account can only INSERT, UPDATE, the third can INSERT, UPDATE or DELETE.<\/p>\n<p>Then, when using a server-side script to query your database, use the account with the most minimal set of privileges that will get the job done.<\/p>\n<p>For instance, if you are displaying a list of products, query with the SELECT-only user.<\/p>\n<p>If you are adding a product review, execute the statement with the INSERT,UPDATE-only user.<\/p>\n<p>&nbsp;<\/p>\n<h4>Some Languages Take it up a Notch<\/h4>\n<p>Check your language for features that offer more specific protection. ColdFusion, for instance, disables the ability to run multiple SQL queries in one statement. This feature can be disabled\/enabled at will, but it is there to protect you if you need it.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>There are dozens of different ways to be a victim of an SQL injection attack. This article offers a more example-driven approach to learning about SQL Injection and how to avoid it.<\/p>\n","protected":false},"author":1,"featured_media":1837,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"amp_status":""},"categories":[13],"tags":[88,119],"_links":{"self":[{"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/posts\/1799"}],"collection":[{"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/comments?post=1799"}],"version-history":[{"count":25,"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/posts\/1799\/revisions"}],"predecessor-version":[{"id":1856,"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/posts\/1799\/revisions\/1856"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/media\/1837"}],"wp:attachment":[{"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/media?parent=1799"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/categories?post=1799"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/tags?post=1799"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}