-
Notifications
You must be signed in to change notification settings - Fork 424
Insight
Injecting a target implies several steps like getting the character insertion, checking the database engine, and getting the schemas via dump optimization with syntax tricks and sometimes applying peculiar algorithm.
Input to internal query can take various forms and its identification is required even prior to the database vendor search :
- simple quotes :
... where id='{input}'
- integer :
... where id={input}
- parenthesis and quotes :
... where id=('{input}')
- etc... eg. multiple parenthesis and integer :
... where (id=({input}))
Consequently the injection prefix must properly match the internal query before proceeding to read any schema. A Boolean check is set to reliably detect the correct form.
In previous examples the respective {input}
prefix are :
' {inject} -- with an end comment to disable the remainder '
1 {inject} -- optional end comment as there's no remainder to disable
') {inject} -- with an end comment to disable the remainder ')
1)) {inject} -- with and end comment to disable the remainder ))
Each database engine uses its own SQL syntax making the injection process unreliable if vendor has not been identified first. In that purpose several techniques will look to identify the engine :
- Fingerprint by error message : query with any incorrect input to get specific error message from target's engine
- Fingerprint by incorrect
ORDER BY
: query with wrong column name to get specific engine error message - Fingerprint by engine specific function : call a method that works only on a given engine
Note
Create an issue to share other techniques you know.
The pattern of queries can take various forms which may or may not work, the goal is to find at least one strategy working in that specific order : Time
, Blind
, Multibit
, Error
, Stack
and Union
.
Improvements applied during the process are key for lowering the loading time and to decrease the number of queries :
- Query with
GROUP BY
to count rows : a single query gets database names with tables count, a single query gets table names with rows count - Apply
DISTINCT
on columns : prevents getting useless duplicated data - Failsafe
N0+1
syntax : sum interpreted by engine asN1
avoids matching when URL withN0+1
shows in the response - Indices calibrator : identify the best
Union
index when multiple indices are working (eg.... select 1,2✅,3,4,5✅
) - Bitwise queries in parallel : chars binary form is queried instead of ASCII form to avoid slower sequential "binary search"