SQL injection site in real-world attacks and CTF tasks
SQL injection in the classification of MITRE ATT & CK — technique Exploit Public-Facing Application (T1190, Initial Access). The attacker finds the entry point in the web application and through it gets to the database - the collection tactic, the Databases technique (T1213.006). In advanced scenarios, injection leads to reading files from the server (Data from Local System, T1005) or securing through SQL Stored Procedures (T1505.001, Persistence). According to the OWASP classification – A03:2021 Injection : user input enters the SQL request without validation and sanitization. More details – in our review, creating ctf tasks.
Why would the attacker do all this? Monetization. Leakage of user data (email, passwords, payment), capture the server through reading system files, execution of OS commands. Exploit.In leak (2016, publication date in HIBP: 2016-10-13) — 593 427 119 email addresses with passwords, according to Have I Been Pwned. According to Verizon DBIR 2025, the proportion of web attacks among all confirmed violations is 26%.
In the CTF, the chain is shorter, but the logic is the same: find the entry point, determine the database, select the technique, pull the flag. Each step depends on the result of the previous one – so SQL injections in the CTF require a methodology, not a random copypaste of payloads.
Solutions Tree: Which SQL Injection Technique to CTF Choose
Three-step algorithm that I use on each web task:
Step 1 is the reaction to the special symbol. Insert a single quote ' in the parameter. Three options. SQL syntax error (text like You have an error in your SQL syntax) – probable error-based. The content of the page has changed, but without error, boolean-based blind-based SQLi is likely. No visible reaction, we try ' AND SLEEP(5)-- for MySQL or '; SELECT pg_sleep(5)-- for PostgreSQL: 5 second response delay will confirm time-closely based SQL injection.
Step 2 – definition of DBMS. According to the data SQL Injection Cheat Sheet from Invicti, the difference in the syntax of the database is the main reason why universal payloads do not work. Quick checks: %23 works as a comment (URL-encoded symbol #) – MySQL/MariaDB. ' UNION SELECT sqlite_version()-- return the result – SQLite. ' AND @@version>0-- passes without error - probably MySQL or MSSQL (check is unreliable: in MySQL 5.7+/8.0 with default strict mode comparison of the string with the number can throw away the type error - the result should be checked empirically; for MySQL is preferable %23 or version()). Concatenation through || works – PostgreSQL or SQLite.
Step 3 – choice of technique. Errors are visible in the answer — error-based SQL injection (the fastest). The data from the request is displayed on the page — UNION-based SQL injection. No errors, no data – blind (boolean or time). The correct classification in this step saves 30-40 minutes on the task.
Summary table of key DBMS differences for web CTF tasks SQL injection:
Parameter MySQL PostgreSQL SQLite MSSQL
Commentary of the line -- or # -- -- --
Line Concatenation CONCAT() double vertical line double vertical line +
Current version @@version version() sqlite_version() @@version
Metadata Tables information_schema information_schema sqlite_master information_schema
Delay SLEEP(N) pg_sleep(N) No native WAITFOR DELAY
Reading files LOAD_FILE() pg_read_file() No OPENROWSET
Error-based SQL injection: instant path to the flag
Error-based SQL injection works when the application gives the database error texts in HTTP response. On CTF, this is the fastest type – from detection to flag, you can reach for 3-5 requests.
Techniques for MySQL: extractvalue and updatexml
Two working functions – extractvalue() and updatexml(). Both expect the correct XPath expression and throw out the mistake if they get trash. Payload ' AND extractvalue(1, concat(0x7e, (SELECT version())))-- forces MySQL to return the error of the view XPATH syntax error: '~5.7.33' (the specific value depends on the server version; the technique works in MySQL 5.x and 8.x) — version of the database directly in the error text. The symbol 0x7e (tilda) is needed so that the string is guaranteed not to be valid XPath.
SQL injection chain manually: sub-request first SELECT table_name FROM information_schema.tables LIMIT 1 – get the name of the first table in the error. Then SELECT column_name FROM information_schema.columns WHERE table_name='flag' LIMIT 1 - column names. Finally, SELECT flag FROM flag - take the flag.
And here is the catch on which beginners are regularly burning. extractvalue() and updatexml() return no more than ~32 characters (characteristic of MySQL 5.x/8.0; the exact value depends on the version - check empirically), including service symbols like 0x7e, so useful data is placed even less. The flag is longer than 30 characters? Cut through SUBSTRING(): construction with substring((SELECT flag FROM flag), 33, 32) inside extractvalue Pulls out the second portion. A typical situation on the CTF is that the flag is trimmed in the middle, looks out of reach, and a person begins to look for another vulnerability. And it was necessary simply to finish.
Alternative – technique through FLOOR(RAND(0)*2) and GROUP BY, described in the pentest-tools.com manual. Error Duplicate entry '10.1.36-MariaDB#0' contains data. Subtlety: RAND(0) with fixed seed gives a deterministic sequence — without seed=0 The technique is unstable and can work at a time.
SQL injection in the classification of MITRE ATT & CK — technique Exploit Public-Facing Application (T1190, Initial Access). The attacker finds the entry point in the web application and through it gets to the database - the collection tactic, the Databases technique (T1213.006). In advanced scenarios, injection leads to reading files from the server (Data from Local System, T1005) or securing through SQL Stored Procedures (T1505.001, Persistence). According to the OWASP classification – A03:2021 Injection : user input enters the SQL request without validation and sanitization. More details – in our review, creating ctf tasks.
Why would the attacker do all this? Monetization. Leakage of user data (email, passwords, payment), capture the server through reading system files, execution of OS commands. Exploit.In leak (2016, publication date in HIBP: 2016-10-13) — 593 427 119 email addresses with passwords, according to Have I Been Pwned. According to Verizon DBIR 2025, the proportion of web attacks among all confirmed violations is 26%.
In the CTF, the chain is shorter, but the logic is the same: find the entry point, determine the database, select the technique, pull the flag. Each step depends on the result of the previous one – so SQL injections in the CTF require a methodology, not a random copypaste of payloads.
Solutions Tree: Which SQL Injection Technique to CTF Choose
Three-step algorithm that I use on each web task:
Step 1 is the reaction to the special symbol. Insert a single quote ' in the parameter. Three options. SQL syntax error (text like You have an error in your SQL syntax) – probable error-based. The content of the page has changed, but without error, boolean-based blind-based SQLi is likely. No visible reaction, we try ' AND SLEEP(5)-- for MySQL or '; SELECT pg_sleep(5)-- for PostgreSQL: 5 second response delay will confirm time-closely based SQL injection.
Step 2 – definition of DBMS. According to the data SQL Injection Cheat Sheet from Invicti, the difference in the syntax of the database is the main reason why universal payloads do not work. Quick checks: %23 works as a comment (URL-encoded symbol #) – MySQL/MariaDB. ' UNION SELECT sqlite_version()-- return the result – SQLite. ' AND @@version>0-- passes without error - probably MySQL or MSSQL (check is unreliable: in MySQL 5.7+/8.0 with default strict mode comparison of the string with the number can throw away the type error - the result should be checked empirically; for MySQL is preferable %23 or version()). Concatenation through || works – PostgreSQL or SQLite.
Step 3 – choice of technique. Errors are visible in the answer — error-based SQL injection (the fastest). The data from the request is displayed on the page — UNION-based SQL injection. No errors, no data – blind (boolean or time). The correct classification in this step saves 30-40 minutes on the task.
Summary table of key DBMS differences for web CTF tasks SQL injection:
Parameter MySQL PostgreSQL SQLite MSSQL
Commentary of the line -- or # -- -- --
Line Concatenation CONCAT() double vertical line double vertical line +
Current version @@version version() sqlite_version() @@version
Metadata Tables information_schema information_schema sqlite_master information_schema
Delay SLEEP(N) pg_sleep(N) No native WAITFOR DELAY
Reading files LOAD_FILE() pg_read_file() No OPENROWSET
Error-based SQL injection: instant path to the flag
Error-based SQL injection works when the application gives the database error texts in HTTP response. On CTF, this is the fastest type – from detection to flag, you can reach for 3-5 requests.
Techniques for MySQL: extractvalue and updatexml
Two working functions – extractvalue() and updatexml(). Both expect the correct XPath expression and throw out the mistake if they get trash. Payload ' AND extractvalue(1, concat(0x7e, (SELECT version())))-- forces MySQL to return the error of the view XPATH syntax error: '~5.7.33' (the specific value depends on the server version; the technique works in MySQL 5.x and 8.x) — version of the database directly in the error text. The symbol 0x7e (tilda) is needed so that the string is guaranteed not to be valid XPath.
SQL injection chain manually: sub-request first SELECT table_name FROM information_schema.tables LIMIT 1 – get the name of the first table in the error. Then SELECT column_name FROM information_schema.columns WHERE table_name='flag' LIMIT 1 - column names. Finally, SELECT flag FROM flag - take the flag.
And here is the catch on which beginners are regularly burning. extractvalue() and updatexml() return no more than ~32 characters (characteristic of MySQL 5.x/8.0; the exact value depends on the version - check empirically), including service symbols like 0x7e, so useful data is placed even less. The flag is longer than 30 characters? Cut through SUBSTRING(): construction with substring((SELECT flag FROM flag), 33, 32) inside extractvalue Pulls out the second portion. A typical situation on the CTF is that the flag is trimmed in the middle, looks out of reach, and a person begins to look for another vulnerability. And it was necessary simply to finish.
Alternative – technique through FLOOR(RAND(0)*2) and GROUP BY, described in the pentest-tools.com manual. Error Duplicate entry '10.1.36-MariaDB#0' contains data. Subtlety: RAND(0) with fixed seed gives a deterministic sequence — without seed=0 The technique is unstable and can work at a time.