{"id":372,"date":"2025-06-13T00:00:00","date_gmt":"2025-06-12T23:00:00","guid":{"rendered":"https:\/\/kosokoking.com\/?p=372"},"modified":"2025-06-12T11:54:23","modified_gmt":"2025-06-12T10:54:23","slug":"sql-injection-attacks-complete-security-guide","status":"publish","type":"post","link":"https:\/\/kosokoking.com\/index.php\/technology\/sql-injection-attacks-complete-security-guide\/","title":{"rendered":"SQL Injection Attacks: Complete Security Guide"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">SQL injection remains one of the most persistent and dangerous vulnerabilities in web applications. Despite decades of awareness, it continues to compromise data, disrupt services, and expose organisations to significant risk. If you\u2019re building or defending web applications, understanding <a href=\"https:\/\/portswigger.net\/web-security\/sql-injection\" target=\"_blank\" rel=\"noopener\" title=\"\">SQL injection<\/a>, especially how it works, how attackers exploit it, and how to defend against it, is not optional. This guide explains SQL injection in a simple way, showing how it\u2019s done, giving real-life examples, and suggesting ways to protect yourself.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>The Role of SQL in Modern Web Applications<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">At its core, SQL (Structured Query Language) is how most web applications interact with their databases. Whether you\u2019re using <a href=\"https:\/\/www.mysql.com\/\" target=\"_blank\" rel=\"noopener\" title=\"\">MySQL<\/a>, <a href=\"https:\/\/www.postgresql.org\/\" target=\"_blank\" rel=\"noopener\" title=\"\">PostgreSQL<\/a>, or SQL Server, your application likely builds queries dynamically, often incorporating user input.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Consider a typical PHP snippet:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$conn = <strong>new<\/strong> mysqli(\u201dlocalhost\u201d, \u201croot\u201d, \u201cpassword\u201d, \u201cusers\u201d);<br><br>$searchInput = $_POST&#91;\u2019findUser\u2019];<br><br>$query = \u201cSELECT * FROM logins WHERE username LIKE \u2018%$searchInput\u2019\";<br><br>$result = $conn->query($query);<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This code takes user input, drops it directly into an SQL query, and executes it. If you don\u2019t sanitise or parametrise that input, you\u2019re inviting attackers to manipulate the query and potentially control your database.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>What is SQL Injection?<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">SQL injection (SQLi) is a vulnerability that allows an attacker to interfere with the queries your application makes to its database. By injecting malicious SQL code into input fields, attackers can:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Bypass authentication<\/li>\n\n\n\n<li>Extract sensitive data<\/li>\n\n\n\n<li>Modify or delete data<\/li>\n\n\n\n<li>Execute administrative operations<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Essentially, if your application processes user input as code instead of data, it\u2019s insecure.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Types of SQL Injection<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Understanding the types of SQL injection is crucial for both attackers and defenders:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><td><strong>Type<\/strong><\/td><td><strong>Description<\/strong><\/td><\/tr><\/thead><tbody><tr><td>In-band<\/td><td>Attacker gets results directly in the application\u2019s response (Union-based, Error-based)<\/td><\/tr><tr><td>Blind<\/td><td>No direct output: attacker infers data by observing application behaviour (Boolean, Time-based)<\/td><\/tr><tr><td>Out-of-band<\/td><td>Data is sent to another channel (e.g., DNS requests)<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>The Classic Attack<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Let\u2019s walk through a real-world authentication bypass using SQL injection.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Scenario:<\/strong>&nbsp;An admin login page executes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>SELECT<\/strong> * <strong>FROM<\/strong> logins <strong>WHERE<\/strong> username=\u2019admin\u2019 AND password=\u2019p@ssw0rd\u2019;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If you enter&nbsp;admin\u2019 OR \u20181\u2019=\u20191&nbsp;as the username, the query becomes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>SELECT<\/strong> * <strong>FROM<\/strong> logins <strong>WHERE<\/strong> username=\u2019admin\u2019 OR \u20181\u2019=\u20191\u2019 AND password=\u2019p@ssw0rd\u2019;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Because&nbsp;\u20181\u2019=\u20191\u2019&nbsp;is always true, the query returns all users, and you\u2019re logged in as the first user in the database\u2014often the admin.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Key takeaway:<\/strong>&nbsp;The&nbsp;OR&nbsp;operator allows attackers to bypass authentication checks by forcing the WHERE clause to evaluate as true.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Discovering SQL Injection Vulnerabilities<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Before exploiting, you need to confirm that an input is vulnerable. Here\u2019s how:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Inject special characters<\/strong>: Try a single quote (\u2019). If you get an SQL error, the input is likely unsanitised.<\/li>\n\n\n\n<li><strong>Try known payloads<\/strong>: Use payloads like\u00a0admin\u2019&#8211;\u00a0or\u00a0admin\u2019 OR \u20181\u2019=\u20191\u00a0to see if authentication can be bypassed.<\/li>\n\n\n\n<li><strong>Observe application behaviour<\/strong>: Errors, unexpected outputs, or changes in page content are strong indicators of SQL injection.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Pro tip:<\/strong>&nbsp;Always URL-encode payloads when injecting via GET requests. For example,&nbsp;%27&nbsp;for&nbsp;&#8216;.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Using Comments to Subvert SQL Logic<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">SQL comments are a powerful tool for attackers. In MySQL, you can use&nbsp;&#8212;&nbsp;or&nbsp;#&nbsp;to comment out the rest of a query.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Example:<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Injecting&nbsp;admin\u2019&#8211;&nbsp;as the username transforms the query:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>SELECT<\/strong> * <strong>FROM<\/strong> logins <strong>WHERE<\/strong> username=\u2019admin\u2019<em>-- \u2018 AND password=\u2019irrelevant\u2019;<\/em><\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The database ignores everything after&nbsp;&#8211;, so only the username check remains. If&nbsp;admin&nbsp;exists, you\u2019re in.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Caveat:<\/strong>&nbsp;In MySQL,&nbsp;&#8212;&nbsp;must be followed by a space to be recognised as a comment.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Parentheses, Precedence, and Advanced Bypass<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Some applications use parentheses to enforce operator precedence:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>SELECT<\/strong> * <strong>FROM<\/strong> logins <strong>WHERE<\/strong> (username=\u2019admin\u2019 AND id &gt; 1) AND password=\u2019hash\u2019;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If the admin\u2019s&nbsp;id&nbsp;is 1, this query blocks admin logins. But with SQL injection, you can close the parenthesis and comment out the rest:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Inject\u00a0admin\u2019)&#8211;\u00a0as the username.<\/li>\n\n\n\n<li>The query becomes:\u00a0SELECT * FROM logins WHERE (username=\u2019admin\u2019)<\/li>\n\n\n\n<li>The rest is ignored, and you log in as admin3.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Union-Based SQL Injection<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The&nbsp;UNION&nbsp;operator allows attackers to combine results from different tables.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>How it works:<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Suppose you have two tables:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>ports (code, city)<\/li>\n\n\n\n<li>ships (Ship, city)<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">A query like:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>SELECT<\/strong> * <strong>FROM<\/strong> ports <strong>UNION<\/strong> <strong>SELECT<\/strong> * <strong>FROM<\/strong> ships;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Combines results from both tables, as long as the number and types of columns match.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Key rules:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The number of columns in both SELECT statements must match.<\/li>\n\n\n\n<li>Data types in each column position must be compatible.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>If not, you\u2019ll get errors like:<\/strong><\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">ERROR 1222 (21000): The used SELECT statements have a different number of columns<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Handling Column Mismatches<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Often, the original query and your injected query have different numbers of columns. You can fill extra columns with junk data or&nbsp;NULL.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Example:<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If the original query selects two columns, but you only want one (e.g., username), inject:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>UNION<\/strong> <strong>SELECT<\/strong> username, 2 <strong>FROM<\/strong> passwords<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Or, for four columns:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>UNION<\/strong> <strong>SELECT<\/strong> username, 2, 3, 4 <strong>FROM<\/strong> passwords<em>--<\/em><\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Using numbers or&nbsp;NULL&nbsp;helps you match the required column count and track which columns are displayed.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Detecting the Number of Columns<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Before crafting your payload, you need to know how many columns the original query returns. Two main methods:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>ORDER BY technique<\/strong>: Inject\u00a0ORDER BY 1,\u00a0ORDER BY 2, etc., until you get an error. The highest successful number is your column count.<\/li>\n\n\n\n<li><strong>UNION SELECT technique<\/strong>: Try\u00a0UNION SELECT 1,\u00a0UNION SELECT 1,2, etc., until the query succeeds.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Example:<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If&nbsp;ORDER BY 4&nbsp;works but&nbsp;ORDER BY 5&nbsp;fails, the table has four columns.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Finding Output Columns<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Not all columns are displayed to the user. To find which ones are, inject distinct values and see which appear in the output.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Example:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>UNION<\/strong> <strong>SELECT<\/strong> 1,@@version,3,4<em>-- -<\/em><\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If you see the database version in the output, you know which column is reflected. Place your payloads accordingly.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Real-World Defences<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Now that you understand how SQL injection works, let\u2019s talk defence. The best approaches are:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Parametrised queries (prepared statements):<\/strong>\u00a0Never concatenate user input into SQL queries.<\/li>\n\n\n\n<li><strong>Input validation and sanitisation:<\/strong>\u00a0Reject or sanitise unexpected input.<\/li>\n\n\n\n<li><strong>Least privilege:<\/strong>\u00a0The database user should have only the permissions it needs.<\/li>\n\n\n\n<li><strong>Error handling:<\/strong>\u00a0Don\u2019t leak database errors to users.<\/li>\n\n\n\n<li><strong>Regular security testing:<\/strong>\u00a0Use automated scanners and manual testing to find vulnerabilities.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Never rely solely on blacklists or escaping input.<\/strong>&nbsp;Attackers are creative, and new bypasses are discovered regularly.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>SQL Injection is a Mindset Problem<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The problem of SQL injection is less about technology and more about approach. If you treat user input as trustworthy, you\u2019re already behind. The solution is to assume all input is hostile, use parametrised queries by default and stay current with changing attack techniques.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For more insightful and engaging write-ups, visit <a href=\"https:\/\/kosokoking.com\/\" target=\"_blank\" rel=\"noopener\" title=\"\">kosokoking.com<\/a> and stay ahead in the world of cybersecurity!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Learn SQL injection techniques including authentication bypass, union-based attacks, and database enumeration. Complete guide with examples for developers.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7,6],"tags":[612,394,194,614,162,143,192,613,615,555],"class_list":["post-372","post","type-post","status-publish","format-standard","hentry","category-security","category-technology","tag-authentication-bypass","tag-cybersecurity-guide","tag-database-security","tag-mysql-security","tag-penetration-testing","tag-secure-coding","tag-sql-injection","tag-union-injection","tag-vulnerability-testing","tag-web-application-security"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/kosokoking.com\/index.php\/wp-json\/wp\/v2\/posts\/372","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kosokoking.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kosokoking.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kosokoking.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/kosokoking.com\/index.php\/wp-json\/wp\/v2\/comments?post=372"}],"version-history":[{"count":1,"href":"https:\/\/kosokoking.com\/index.php\/wp-json\/wp\/v2\/posts\/372\/revisions"}],"predecessor-version":[{"id":373,"href":"https:\/\/kosokoking.com\/index.php\/wp-json\/wp\/v2\/posts\/372\/revisions\/373"}],"wp:attachment":[{"href":"https:\/\/kosokoking.com\/index.php\/wp-json\/wp\/v2\/media?parent=372"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/kosokoking.com\/index.php\/wp-json\/wp\/v2\/categories?post=372"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kosokoking.com\/index.php\/wp-json\/wp\/v2\/tags?post=372"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}