MS Access SQL Injection
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
String concatenation is possible with & (%26)
and + (%2b)
characters.
There are no comments in MS access, but apparently it's possible to remove the last of a query with a NULL char:
If this is not working you could always fix the syntax of the query:
They aren't supported.
The LIMIT
operator isn't implemented. However, it's possible to limit SELECT query results to the first N table rows using the TOP
operator. TOP
accepts as argument an integer, representing the number of rows to be returned.
Just like TOP you can use LAST
which will get the rows from the end.
In a SQLi you usually will want to somehow execute a new query to extract information from other tables. MS Access always requires that in subqueries or extra queries a FROM
is indicated.
So, if you want to execute a UNION SELECT
or UNION ALL SELECT
or a SELECT
between parenthesis in a condition, you always need to indicate a FROM
with a valid table name.
Therefore, you need to know a valid table name.
This will allow you to exfiltrate values of the current table without needing to know the name of the table.
MS Access allows weird syntax such as '1'=2='3'='asd'=false
. As usually the SQL injection will be inside a WHERE
clause we can abuse that.
Imagine you have a SQLi in a MS Access database and you know (or guessed) that one column name is username, and thats the field you want to exfiltrate. You could check the different responses of the web app when the chaining equals technique is used and potentially exfiltrate content with a boolean injection using the Mid
function to get substrings.
If you know the name of the table and column to dump you can use a combination between Mid
, LAST
and TOP
to leak all the info via boolean SQLi:
Feel free to check this in the online playground.
Using the chaining equals technique you can also bruteforce table names with something like:
You can also use a more traditional way:
Feel free to check this in the online playground.
Sqlmap common table names: https://github.com/sqlmapproject/sqlmap/blob/master/data/txt/common-tables.txt
There is another list in http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html
You can brute-force current columns names with the chaining equals trick with:
Or with a group by:
Or you can brute-force column names of a different table with:
We have already discussed the chaining equals technique to dump data from the current and other tables. But there are other ways:
In a nutshell, the query uses an “if-then” statement in order to trigger a “200 OK” in case of success or a “500 Internal Error” otherwise. Taking advantage of the TOP 10 operator, it is possible to select the first ten results. The subsequent usage of LAST allows to consider the 10th tuple only. On such value, using the MID operator, it is possible to perform a simple character comparison. Properly changing the index of MID and TOP, we can dump the content of the “username” field for all rows.
Mid('admin',1,1)
get substring from position 1 length 1 (initial position is 1)
LEN('1234')
get length of string
ASC('A')
get ascii value of char
CHR(65)
get string from ascii value
IIF(1=1,'a','b')
if then
COUNT(*)
Count number of items
From here you can see a query to get tables names:
However, note that is very typical to find SQL Injections where you don't have access to read the table MSysObjects
.
The knowledge of the web root absolute path may facilitate further attacks. If application errors are not completely concealed, the directory path can be uncovered trying to select data from an inexistent database.
http://localhost/script.asp?id=1'+'+UNION+SELECT+1+FROM+FakeDB.FakeTable%00
MS Access responds with an error message containing the web directory full pathname.
The following attack vector can be used to inferrer the existence of a file on the remote filesystem. If the specified file exists, MS Access triggers an error message informing that the database format is invalid:
http://localhost/script.asp?id=1'+UNION+SELECT+name+FROM+msysobjects+IN+'\boot.ini'%00
Another way to enumerate files consists into specifying a database.table item. If the specified file exists, MS Access displays a database format error message.
http://localhost/script.asp?id=1'+UNION+SELECT+1+FROM+C:\boot.ini.TableName%00
Database file name (.mdb) can be inferred with the following query:
http://localhost/script.asp?id=1'+UNION+SELECT+1+FROM+name[i].realTable%00
Where name[i] is a .mdb filename and realTable is an existent table within the database. Although MS Access will always trigger an error message, it is possible to distinguish between an invalid filename and a valid .mdb filename.
Access PassView is a free utility that can be used to recover the main database password of Microsoft Access 95/97/2000/XP or Jet Database Engine 3.0/4.0.
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)