Skip to content

Commit 86ac302

Browse files
committed
Improving SQLite table schema parsing (#2678)
1 parent ebaee3a commit 86ac302

File tree

4 files changed

+29
-8
lines changed

4 files changed

+29
-8
lines changed

data/xml/queries.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -357,8 +357,8 @@
357357
<blind query="SELECT tbl_name FROM sqlite_master WHERE type='table' LIMIT %d,1" count="SELECT COUNT(tbl_name) FROM sqlite_master WHERE type='table'"/>
358358
</tables>
359359
<columns>
360-
<inband query="SELECT MAX(sql) FROM sqlite_master WHERE tbl_name='%s'"/>
361-
<blind query="SELECT sql FROM sqlite_master WHERE tbl_name='%s' LIMIT 1" condition=""/>
360+
<inband query="SELECT MAX(sql) FROM sqlite_master WHERE type='table' AND tbl_name='%s'"/>
361+
<blind query="SELECT sql FROM sqlite_master WHERE type='table' AND tbl_name='%s' LIMIT 1" condition=""/>
362362
</columns>
363363
<dump_table>
364364
<inband query="SELECT %s FROM %s"/>

extra/vulnserver/vulnserver.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@
4444
CREATE TABLE users (
4545
id INTEGER,
4646
name TEXT,
47-
surname TEXT
47+
surname TEXT,
48+
PRIMARY KEY (id)
4849
);
4950
INSERT INTO users (id, name, surname) VALUES (1, 'luther', 'blisset');
5051
INSERT INTO users (id, name, surname) VALUES (2, 'fluffy', 'bunny');

lib/core/common.py

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3402,19 +3402,39 @@ def parseSqliteTableSchema(value):
34023402
>>> kb.data.cachedColumns = {}
34033403
>>> parseSqliteTableSchema("CREATE TABLE users(\\n\\t\\tid INTEGER,\\n\\t\\tname TEXT\\n);")
34043404
True
3405-
>>> repr(kb.data.cachedColumns).count(',') == 1
3405+
>>> tuple(kb.data.cachedColumns[conf.db][conf.tbl].items()) == (('id', 'INTEGER'), ('name', 'TEXT'))
3406+
True
3407+
>>> parseSqliteTableSchema("CREATE TABLE dummy(`foo bar` BIGINT, \\"foo\\" VARCHAR, 'bar' TEXT)");
3408+
True
3409+
>>> tuple(kb.data.cachedColumns[conf.db][conf.tbl].items()) == (('foo bar', 'BIGINT'), ('foo', 'VARCHAR'), ('bar', 'TEXT'))
3410+
True
3411+
>>> parseSqliteTableSchema("CREATE TABLE suppliers(\\n\\tsupplier_id INTEGER PRIMARY KEY DESC,\\n\\tname TEXT NOT NULL\\n);");
3412+
True
3413+
>>> tuple(kb.data.cachedColumns[conf.db][conf.tbl].items()) == (('supplier_id', 'INTEGER'), ('name', 'TEXT'))
3414+
True
3415+
>>> parseSqliteTableSchema("CREATE TABLE country_languages (\\n\\tcountry_id INTEGER NOT NULL,\\n\\tlanguage_id INTEGER NOT NULL,\\n\\tPRIMARY KEY (country_id, language_id),\\n\\tFOREIGN KEY (country_id) REFERENCES countries (country_id) ON DELETE CASCADE ON UPDATE NO ACTION,\\tFOREIGN KEY (language_id) REFERENCES languages (language_id) ON DELETE CASCADE ON UPDATE NO ACTION);");
3416+
True
3417+
>>> tuple(kb.data.cachedColumns[conf.db][conf.tbl].items()) == (('country_id', 'INTEGER'), ('language_id', 'INTEGER'))
34063418
True
34073419
"""
34083420

34093421
retVal = False
34103422

3423+
value = extractRegexResult(r"(?s)\((?P<result>.+)\)", value)
3424+
34113425
if value:
34123426
table = {}
3413-
columns = {}
3427+
columns = OrderedDict()
3428+
3429+
value = re.sub(r"\(.+?\)", "", value).strip()
34143430

3415-
for match in re.finditer(r"[(,]\s*[\"'`]?(\w+)[\"'`]?(?:\s+(INT|INTEGER|TINYINT|SMALLINT|MEDIUMINT|BIGINT|UNSIGNED BIG INT|INT2|INT8|INTEGER|CHARACTER|VARCHAR|VARYING CHARACTER|NCHAR|NATIVE CHARACTER|NVARCHAR|TEXT|CLOB|LONGTEXT|BLOB|NONE|REAL|DOUBLE|DOUBLE PRECISION|FLOAT|REAL|NUMERIC|DECIMAL|BOOLEAN|DATE|DATETIME|NUMERIC)\b)?", decodeStringEscape(value), re.I):
3431+
for match in re.finditer(r"(?:\A|,)\s*(([\"'`]).+?\2|\w+)(?:\s+(INT|INTEGER|TINYINT|SMALLINT|MEDIUMINT|BIGINT|UNSIGNED BIG INT|INT2|INT8|INTEGER|CHARACTER|VARCHAR|VARYING CHARACTER|NCHAR|NATIVE CHARACTER|NVARCHAR|TEXT|CLOB|LONGTEXT|BLOB|NONE|REAL|DOUBLE|DOUBLE PRECISION|FLOAT|REAL|NUMERIC|DECIMAL|BOOLEAN|DATE|DATETIME|NUMERIC)\b)?", decodeStringEscape(value), re.I):
3432+
column = match.group(1).strip(match.group(2) or "")
3433+
if re.search(r"(?i)\A(CONSTRAINT|PRIMARY|UNIQUE|CHECK|FOREIGN)\b", column.strip()):
3434+
continue
34163435
retVal = True
3417-
columns[match.group(1)] = match.group(2) or "TEXT"
3436+
3437+
columns[column] = match.group(3) or "TEXT"
34183438

34193439
table[safeSQLIdentificatorNaming(conf.tbl, True)] = columns
34203440
kb.data.cachedColumns[conf.db] = table

lib/core/settings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from thirdparty.six import unichr as _unichr
2121

2222
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
23-
VERSION = "1.6.12.1"
23+
VERSION = "1.6.12.2"
2424
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
2525
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
2626
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)

0 commit comments

Comments
 (0)