• Python:Sqlmap源码精读之解析xml


    XML

    <?xml version="1.0" encoding="UTF-8"?>
    <root>
        <!-- MySQL -->
        <dbms value="MySQL">
            <cast query="CAST(%s AS CHAR)"/>
            <length query="LENGTH(%s)"/>
            <isnull query="IFNULL(%s,' ')"/>
            <delimiter query=","/>
            <limit query="LIMIT %d,%d"/>
            <limitregexp query="s+LIMITs+([d]+)s*\,s*([d]+)"/>
            <limitgroupstart query="1"/>
            <limitgroupstop query="2"/>
            <limitstring query=" LIMIT "/>
            <order query="ORDER BY %s ASC"/>
            <count query="COUNT(%s)"/>
            <comment query="-- " query2="/*" query3="#"/>
            <!--
                 NOTE: MySQL 5.0.12 introduced SLEEP() function
                       References:
                       * http://dev.mysql.com/doc/refman/5.0/en/news-5-0-12.html
                       * http://dev.mysql.com/doc/refman/5.1/en/miscellaneous-functions.html#function_sleep
            -->
            <timedelay query="SELECT SLEEP(%d)" query2="SELECT BENCHMARK(5000000,MD5('%d'))"/>
            <substring query="MID((%s),%d,%d)"/>
            <case query="SELECT (CASE WHEN (%s) THEN 1 ELSE 0 END)"/>
            <inference query="ORD(MID((%s),%d,1)) > %d"/>
            <banner query="VERSION()"/>
            <current_user query="CURRENT_USER()"/>
            <current_db query="DATABASE()"/>
            <is_dba query="(SELECT super_priv FROM mysql.user WHERE user='%s' LIMIT 0,1)='Y'"/>
            <check_udf query="(SELECT name FROM mysql.func WHERE name='%s' LIMIT 0,1)='%s'"/>
            <users>
                <inband query="SELECT grantee FROM information_schema.USER_PRIVILEGES" query2="SELECT user FROM mysql.user"/>
                <blind query="SELECT DISTINCT(grantee) FROM information_schema.USER_PRIVILEGES LIMIT %d,1" query2="SELECT DISTINCT(user) FROM mysql.user LIMIT %d,1" count="SELECT COUNT(DISTINCT(grantee)) FROM information_schema.USER_PRIVILEGES" count2="SELECT COUNT(DISTINCT(user)) FROM mysql.user"/>
            </users>
            <passwords>
                <inband query="SELECT user,password FROM mysql.user" condition="user"/>
                <blind query="SELECT DISTINCT(password) FROM mysql.user WHERE user='%s' LIMIT %d,1" count="SELECT COUNT(DISTINCT(password)) FROM mysql.user WHERE user='%s'"/>
            </passwords>
            <privileges>
                <inband query="SELECT grantee,privilege_type FROM information_schema.USER_PRIVILEGES" condition="grantee" query2="SELECT user,select_priv,insert_priv,update_priv,delete_priv,create_priv,drop_priv,reload_priv,shutdown_priv,process_priv,file_priv,grant_priv,references_priv,index_priv,alter_priv,show_db_priv,super_priv,create_tmp_table_priv,lock_tables_priv,execute_priv,repl_slave_priv,repl_client_priv,create_view_priv,show_view_priv,create_routine_priv,alter_routine_priv,create_user_priv FROM mysql.user" condition2="user"/>
                <blind query="SELECT DISTINCT(privilege_type) FROM information_schema.USER_PRIVILEGES WHERE grantee%s%s LIMIT %d,1" query2="SELECT select_priv,insert_priv,update_priv,delete_priv,create_priv,drop_priv,reload_priv,shutdown_priv,process_priv,file_priv,grant_priv,references_priv,index_priv,alter_priv,show_db_priv,super_priv,create_tmp_table_priv,lock_tables_priv,execute_priv,repl_slave_priv,repl_client_priv,create_view_priv,show_view_priv,create_routine_priv,alter_routine_priv,create_user_priv FROM mysql.user WHERE user='%s' LIMIT %d,1" count="SELECT COUNT(DISTINCT(privilege_type)) FROM information_schema.USER_PRIVILEGES WHERE grantee%s%s" count2="SELECT COUNT(*) FROM mysql.user WHERE user='%s'"/>
            </privileges>
            <roles/>
            <dbs>
                <inband query="SELECT schema_name FROM information_schema.SCHEMATA" query2="SELECT db FROM mysql.db"/>
                <blind query="SELECT DISTINCT(schema_name) FROM information_schema.SCHEMATA LIMIT %d,1" query2="SELECT DISTINCT(db) FROM mysql.db LIMIT %d,1" count="SELECT COUNT(DISTINCT(schema_name)) FROM information_schema.SCHEMATA" count2="SELECT COUNT(DISTINCT(db)) FROM mysql.db"/>
            </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' LIMIT %d,1" count="SELECT COUNT(table_name) FROM information_schema.TABLES WHERE table_schema='%s'"/>
            </tables>
            <columns>
                <inband query="SELECT column_name,column_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 column_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"/>
                <blind query="SELECT %s FROM %s.%s LIMIT %d,1" count="SELECT COUNT(*) FROM %s.%s"/>
            </dump_table>
            <search_db>
                <inband query="SELECT schema_name FROM information_schema.SCHEMATA WHERE " query2="SELECT db FROM mysql.db WHERE " condition="schema_name" condition2="db"/>
                <blind query="SELECT DISTINCT(schema_name) FROM information_schema.SCHEMATA WHERE " query2="SELECT DISTINCT(db) FROM mysql.db WHERE " count="SELECT COUNT(DISTINCT(schema_name)) FROM information_schema.SCHEMATA WHERE " count2="SELECT COUNT(DISTINCT(db)) FROM mysql.db WHERE " condition="schema_name" condition2="db"/>
            </search_db>
            <search_table>
                <inband query="SELECT table_schema,table_name FROM information_schema.TABLES WHERE " condition="table_name" condition2="table_schema"/>
                <blind query="SELECT DISTINCT(table_schema) FROM information_schema.TABLES WHERE " query2="SELECT DISTINCT(table_name) FROM information_schema.TABLES WHERE table_schema='%s'" count="SELECT COUNT(DISTINCT(table_schema)) FROM information_schema.TABLES WHERE " 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 " condition="column_name" condition2="table_schema"/>
                <blind query="SELECT DISTINCT(table_schema) FROM information_schema.COLUMNS WHERE " query2="SELECT DISTINCT(table_name) FROM information_schema.COLUMNS WHERE table_schema='%s'" count="SELECT COUNT(DISTINCT(table_schema)) FROM information_schema.COLUMNS WHERE " count2="SELECT COUNT(DISTINCT(table_name)) FROM information_schema.COLUMNS WHERE table_schema='%s'" condition="column_name" condition2="table_schema"/>
            </search_column>
        </dbms>
    
        <!-- PostgreSQL -->
        <dbms value="PostgreSQL">
            <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+OFFSETs+([d]+)s+LIMITs+([d]+)"/>
            <limitgroupstart query="1"/>
            <limitgroupstop query="2"/>
            <limitstring query=" OFFSET "/>
            <order query="ORDER BY %s ASC"/>
            <count query="COUNT(%s)"/>
            <comment query="--" query2="/*"/>
            <!--
                 NOTE: PostgreSQL 8.2 introduced PG_SLEEP() function
                       References:
                       * http://www.postgresql.org/docs/8.3/interactive/release-8-2.html
                       * http://www.postgresql.org/docs/8.3/interactive/functions-datetime.html#FUNCTIONS-DATETIME-DELAY
            -->
            <timedelay query="SELECT PG_SLEEP(%d)" query2="SELECT 'sqlmap' WHERE exists(SELECT * FROM generate_series(1,300000%d))" query3="CREATE OR REPLACE FUNCTION sleep(int) RETURNS int AS '/lib/libc.so.6','sleep' language 'C' STRICT; SELECT sleep(%d)"/>
            <substring query="SUBSTR((%s)::text,%d,%d)"/>
            <case query="SELECT (CASE WHEN (%s) THEN '1' ELSE '0' END)"/>
            <inference query="ASCII(SUBSTR((%s)::text,%d,1)) > %d"/>
            <banner query="SELECT VERSION()"/>
            <current_user query="SELECT CURRENT_USER"/>
            <current_db query="SELECT CURRENT_DATABASE()"/>
            <is_dba query="(SELECT usesuper=true FROM pg_user WHERE usename=CURRENT_USER OFFSET 0 LIMIT 1)"/>
            <check_udf query="(SELECT proname='%s' FROM pg_proc WHERE proname='%s' OFFSET 0 LIMIT 1)"/>
            <users>
                <inband query="SELECT usename FROM pg_user"/>
                <blind query="SELECT DISTINCT(usename) FROM pg_user OFFSET %d LIMIT 1" count="SELECT COUNT(DISTINCT(usename)) FROM pg_user"/>
            </users>
            <passwords>
                <inband query="SELECT usename,passwd FROM pg_shadow" condition="usename"/>
                <blind query="SELECT DISTINCT(passwd) FROM pg_shadow WHERE usename='%s' OFFSET %d LIMIT 1" count="SELECT COUNT(DISTINCT(passwd)) FROM pg_shadow WHERE usename='%s'"/>
            </passwords>
            <privileges>
                <inband query="SELECT usename,(CASE WHEN usecreatedb THEN 1 ELSE 0 END),(CASE WHEN usesuper THEN 1 ELSE 0 END),(CASE WHEN usecatupd THEN 1 ELSE 0 END) FROM pg_user" condition="usename"/>
                <blind query="SELECT (CASE WHEN usecreatedb THEN 1 ELSE 0 END),(CASE WHEN usesuper THEN 1 ELSE 0 END),(CASE WHEN usecatupd THEN 1 ELSE 0 END) FROM pg_user WHERE usename='%s' OFFSET %d LIMIT 1" count="SELECT COUNT(DISTINCT(usename)) FROM pg_user WHERE usename='%s'"/>
            </privileges>
            <roles/>
            <dbs>
                <inband query="SELECT datname FROM pg_database"/>
                <blind query="SELECT DISTINCT(datname) FROM pg_database OFFSET %d LIMIT 1" count="SELECT COUNT(DISTINCT(datname)) FROM pg_database"/>
            </dbs>
            <tables>
                <inband query="SELECT schemaname,tablename FROM pg_tables" condition="schemaname"/>
                <blind query="SELECT tablename FROM pg_tables WHERE schemaname='%s' OFFSET %d LIMIT 1" count="SELECT COUNT(tablename) FROM pg_tables WHERE schemaname='%s'"/>
            </tables>
            <columns>
                <inband query="SELECT attname,typname FROM pg_namespace,pg_type,pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND a.relname='%s' AND nspname='%s'" condition="attname"/>
                <blind query="SELECT attname FROM pg_namespace,pg_type,pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND a.relname='%s' AND nspname='%s'" query2="SELECT typname FROM pg_namespace,pg_type,pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relname='%s' AND a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND attname='%s' AND nspname='%s'" count="SELECT COUNT(attname) FROM pg_namespace,pg_type,pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND a.relname='%s' AND nspname='%s'" condition="attname"/>
            </columns>
            <dump_table>
                <inband query="SELECT %s FROM %s.%s"/>
                <blind query="SELECT %s FROM %s.%s OFFSET %d LIMIT 1" count="SELECT COUNT(*) FROM %s.%s"/>
            </dump_table>
            <search_db>
                <inband query="SELECT datname FROM pg_database WHERE " query2="" condition="datname" condition2=""/>
                <blind query="SELECT DISTINCT(datname) FROM pg_database WHERE " query2="" count="SELECT COUNT(DISTINCT(datname)) FROM pg_database WHERE " count2="" condition="datname" condition2=""/>
            </search_db>
            <search_table>
                <inband query="SELECT schemaname,tablename FROM pg_tables WHERE " condition="tablename" condition2="schemaname"/>
                <blind query="SELECT DISTINCT(schemaname) FROM pg_tables WHERE " query2="SELECT tablename FROM pg_tables WHERE schemaname='%s'" count="SELECT COUNT(DISTINCT(schemaname)) FROM pg_tables WHERE " count2="SELECT COUNT(tablename) FROM pg_tables WHERE schemaname='%s'" condition="tablename" condition2="schemaname"/>
            </search_table>
            <search_column>
                <inband query="SELECT nspname,relname FROM pg_namespace,pg_type,pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND " condition="attname" condition2="nspname"/>
                <blind query="SELECT DISTINCT(nspname) FROM pg_namespace,pg_type,pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND " query2="SELECT DISTINCT(relname) FROM pg_namespace,pg_type,pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND nspname='%s'" count="SELECT COUNT(DISTINCT(nspname)) FROM pg_namespace,pg_type,pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND " count2="SELECT COUNT(DISTINCT(relname)) FROM pg_namespace,pg_type,pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND nspname='%s'" condition="attname" condition2="nspname"/>
            </search_column>
        </dbms>
    
        <!-- Microsoft SQL Server -->
        <dbms value="Microsoft SQL Server">
            <cast query="CAST(%s AS NVARCHAR(4000))"/>
            <length query="LTRIM(STR(LEN(%s)))"/>
            <isnull query="ISNULL(%s,' ')"/>
            <delimiter query="+"/>
            <limit query="SELECT TOP %d "/>
            <limitregexp query="TOPs+([d]+)s+.+?s+FROMs+.+?s+WHEREs+.+?s+NOTs+INs+(SELECTs+TOPs+([d]+)s+"/>
            <limitgroupstart query="2"/>
            <limitgroupstop query="1"/>
            <limitstring/>
            <order query="ORDER BY %s ASC"/>
            <count query="COUNT(%s)"/>
            <comment query="--" query2="/*"/>
            <timedelay query="WAITFOR DELAY '0:0:%d'"/>
            <substring query="SUBSTRING((%s),%d,%d)"/>
            <case query="SELECT (CASE WHEN (%s) THEN '1' ELSE '0' END)"/>
            <inference query="ASCII(SUBSTRING((%s),%d,1)) > %d"/>
            <banner query="SELECT @@VERSION"/>
            <current_user query="SELECT SYSTEM_USER"/>
            <current_db query="SELECT DB_NAME()"/>
            <is_dba query="IS_SRVROLEMEMBER('sysadmin')=1" query2="IS_SRVROLEMEMBER('sysadmin','%s')=1"/>
            <users>
                <inband query="SELECT name FROM master..syslogins" query2="SELECT name FROM sys.sql_logins"/>
                <!-- NOTE: in NOT IN kind of queries ORDER BY is a must -->
                <blind query="SELECT TOP 1 name FROM master..syslogins WHERE name NOT IN (SELECT TOP %d name FROM master..syslogins ORDER BY name) ORDER BY name" query2="SELECT TOP 1 name FROM sys.sql_logins WHERE name NOT IN (SELECT TOP %d name FROM sys.sql_logins ORDER BY name) ORDER BY name" count="SELECT LTRIM(STR(COUNT(name))) FROM master..syslogins" count2="SELECT LTRIM(STR(COUNT(name))) FROM sys.sql_logins"/>
            </users>
            <passwords>
                <inband query="SELECT name,master.dbo.fn_varbintohexstr(password) FROM master..sysxlogins" query2="SELECT name,master.dbo.fn_varbintohexstr(password_hash) FROM sys.sql_logins" condition="name"/>
                <blind query="SELECT TOP 1 master.dbo.fn_varbintohexstr(password) FROM master..sysxlogins WHERE name='%s' AND password NOT IN (SELECT TOP %d password FROM master..sysxlogins WHERE name='%s' ORDER BY password) ORDER BY password" query2="SELECT TOP 1 master.dbo.fn_varbintohexstr(password_hash) FROM sys.sql_logins WHERE name='%s' AND password_hash NOT IN (SELECT TOP %d password_hash FROM sys.sql_logins WHERE name='%s' ORDER BY password_hash) ORDER BY password_hash" count="SELECT LTRIM(STR(COUNT(password))) FROM master..sysxlogins WHERE name='%s'" count2="SELECT LTRIM(STR(COUNT(password_hash))) FROM sys.sql_logins WHERE name='%s'"/>
            </passwords>
            <!-- NOTE: in Microsoft SQL Server there is no query to enumerate DBMS users privileges -->
            <privileges/>
            <roles/>
            <dbs>
                <inband query="SELECT name FROM master..sysdatabases"/>
                <blind query="SELECT TOP 1 name FROM master..sysdatabases WHERE name NOT IN (SELECT TOP %d name FROM master..sysdatabases ORDER BY name) ORDER BY name" count="SELECT LTRIM(STR(COUNT(name))) FROM master..sysdatabases"/>
            </dbs>
            <tables>
                <inband query="SELECT sysusers.name+'.'+sysobjects.name FROM %s..sysobjects INNER JOIN sysusers ON sysobjects.uid = sysusers.uid WHERE xtype IN ('u', 'v')"/>
                <blind query="SELECT TOP 1 sysusers.name+'.'+sysobjects.name FROM %s..sysobjects INNER JOIN sysusers ON sysobjects.uid = sysusers.uid WHERE xtype IN ('u', 'v') AND sysusers.name+'.'+sysobjects.name NOT IN (SELECT TOP %d sysusers.name+'.'+sysobjects.name FROM %s..sysobjects INNER JOIN sysusers ON sysobjects.uid = sysusers.uid WHERE xtype IN ('u', 'v') ORDER BY sysusers.name+'.'+sysobjects.name) ORDER BY sysusers.name+'.'+sysobjects.name" count="SELECT LTRIM(STR(COUNT(name))) FROM %s..sysobjects WHERE xtype IN ('u','v')"/>
            </tables>
            <columns>
                <inband query="SELECT %s..syscolumns.name,TYPE_NAME(%s..syscolumns.xtype) FROM %s..syscolumns,%s..sysobjects WHERE %s..syscolumns.id=%s..sysobjects.id AND %s..sysobjects.name='%s'" condition="[DB]..syscolumns.name"/>
                <blind query="SELECT %s..syscolumns.name FROM %s..syscolumns,%s..sysobjects WHERE %s..syscolumns.id=%s..sysobjects.id AND %s..sysobjects.name='%s'" query2="SELECT TYPE_NAME(%s..syscolumns.xtype) FROM %s..syscolumns,%s..sysobjects WHERE %s..syscolumns.name='%s' AND %s..syscolumns.id=%s..sysobjects.id AND %s..sysobjects.name='%s'" count="SELECT LTRIM(STR(COUNT(name))) FROM %s..syscolumns WHERE id=(SELECT id FROM %s..sysobjects WHERE name='%s')" condition="[DB]..syscolumns.name"/>
            </columns>
            <dump_table>
                <inband query="SELECT %s FROM %s.%s"/>
                <blind query="SELECT MIN(%s) FROM %s WHERE CONVERT(NVARCHAR(4000),%s)>'%s'" query2="SELECT MAX(%s) FROM %s WHERE CONVERT(NVARCHAR(4000),%s) LIKE '%s'" count="SELECT LTRIM(STR(COUNT(*))) FROM %s" count2="SELECT LTRIM(STR(COUNT(DISTINCT(%s)))) FROM %s"/>
            </dump_table>
            <search_db>
                <inband query="SELECT name FROM master..sysdatabases WHERE " condition="name"/>
                <blind query="SELECT name FROM master..sysdatabases WHERE " count="SELECT LTRIM(STR(COUNT(name))) FROM master..sysdatabases WHERE " condition="name"/>
            </search_db>
            <search_table>
                <inband query="SELECT name FROM %s..sysobjects WHERE xtype IN ('u','v') AND " condition="name" condition2="name"/>
                <blind query="" query2="SELECT name FROM %s..sysobjects WHERE xtype IN ('u','v') " count="" count2="SELECT LTRIM(STR(COUNT(name))) FROM %s..sysobjects WHERE xtype IN ('u','v')" condition="name" condition2="name"/>
            </search_table>
            <search_column>
                <inband query="SELECT %s..sysobjects.name FROM %s..syscolumns,%s..sysobjects WHERE %s..syscolumns.id=%s..sysobjects.id AND %s..sysobjects.xtype in ('u', 'v')" condition="[DB]..syscolumns.name"/>
                <blind query="" query2="SELECT %s..sysobjects.name FROM %s..syscolumns,%s..sysobjects WHERE %s..syscolumns.id=%s..sysobjects.id  AND %s..sysobjects.xtype in ('u', 'v')" count="" count2="SELECT COUNT(%s..sysobjects.name) FROM %s..syscolumns,%s..sysobjects WHERE %s..syscolumns.id=%s..sysobjects.id" condition="[DB]..syscolumns.name"/>
            </search_column>
        </dbms>
    
        <!-- Oracle -->
        <dbms value="Oracle">
            <cast query="CAST(%s AS VARCHAR(4000))"/>
            <length query="LENGTH(%s)"/>
            <isnull query="NVL(%s,' ')"/>
            <delimiter query="||"/>
            <limit query="ROWNUM AS LIMIT %s) WHERE LIMIT"/>
            <limitregexp query="ROWNUMs+ASs+.+?s+FROMs+.+?)s+WHEREs+.+?s*=s*[d]+|ROWNUMs*=s*[d]+"/>
            <limitgroupstart/>
            <limitgroupstop/>
            <limitstring/>
            <order query="ORDER BY %s ASC"/>
            <count query="COUNT(%s)"/>
            <comment query="--"/>
            <timedelay query="BEGIN DBMS_LOCK.SLEEP(%d); END" query2="EXEC DBMS_LOCK.SLEEP(%d.00)" query3="EXEC USER_LOCK.SLEEP(%d.00)"/>
            <substring query="SUBSTR((%s),%d,%d)"/>
            <case query="SELECT (CASE WHEN (%s) THEN 1 ELSE 0 END)"/>
            <inference query="ASCII(SUBSTR((%s),%d,1)) > %d"/>
            <banner query="SELECT banner FROM v$version WHERE ROWNUM=1"/>
            <current_user query="SELECT USER FROM DUAL"/>
            <!--
            NOTE: current physical DB but not usable for enumeration
            <current_db query="SELECT SYS.DATABASE_NAME FROM DUAL"/>
            -->
            <current_db query="SELECT USER FROM DUAL"/>
            <!--
                 NOTE: in Oracle to check if the session user is DBA you can use:
                 SELECT USERENV('ISDBA') FROM DUAL
            -->
            <is_dba query="(SELECT GRANTED_ROLE FROM DBA_ROLE_PRIVS WHERE GRANTEE=USER AND GRANTED_ROLE='DBA')='DBA'"/>
            <users>
                <inband query="SELECT USERNAME FROM SYS.ALL_USERS"/>
                <blind query="SELECT DISTINCT(USERNAME) FROM (SELECT DISTINCT(USERNAME),ROWNUM AS LIMIT FROM SYS.ALL_USERS) WHERE LIMIT=%d" count="SELECT COUNT(DISTINCT(USERNAME)) FROM SYS.ALL_USERS"/>
            </users>
            <passwords>
                <inband query="SELECT NAME,PASSWORD FROM SYS.USER$" condition="NAME"/>
                <blind query="SELECT DISTINCT(PASSWORD) FROM (SELECT DISTINCT(PASSWORD),ROWNUM AS LIMIT FROM SYS.USER$ WHERE NAME='%s') WHERE LIMIT=%d" count="SELECT COUNT(DISTINCT(PASSWORD)) FROM SYS.USER$ WHERE NAME='%s'"/>
            </passwords>
            <!--
                 NOTE: in Oracle to enumerate the privileges for the session user you can use:
                 SELECT * FROM SESSION_PRIVS
            -->
            <privileges>
                <inband query="SELECT GRANTEE,PRIVILEGE FROM DBA_SYS_PRIVS" query2="SELECT USERNAME,PRIVILEGE FROM USER_SYS_PRIVS" condition="GRANTEE" condition2="USERNAME"/>
                <blind query="SELECT DISTINCT(PRIVILEGE) FROM (SELECT DISTINCT(PRIVILEGE),ROWNUM AS LIMIT FROM DBA_SYS_PRIVS WHERE GRANTEE='%s') WHERE LIMIT=%d" query2="SELECT DISTINCT(PRIVILEGE) FROM (SELECT DISTINCT(PRIVILEGE),ROWNUM AS LIMIT FROM USER_SYS_PRIVS WHERE USERNAME='%s') WHERE LIMIT=%d" count="SELECT COUNT(DISTINCT(PRIVILEGE)) FROM DBA_SYS_PRIVS WHERE GRANTEE='%s'" count2="SELECT COUNT(DISTINCT(PRIVILEGE)) FROM USER_SYS_PRIVS WHERE USERNAME='%s'"/>
            </privileges>
            <!--
                 NOTE: in Oracle to enumerate the roles for the session user you can use:
                 SELECT * FROM SESSION_ROLES
            -->
            <roles>
                <inband query="SELECT GRANTEE,GRANTED_ROLE FROM DBA_ROLE_PRIVS" query2="SELECT USERNAME,GRANTED_ROLE FROM USER_ROLE_PRIVS" condition="GRANTEE" condition2="USERNAME"/>
                <blind query="SELECT DISTINCT(GRANTED_ROLE) FROM (SELECT DISTINCT(GRANTED_ROLE),ROWNUM AS LIMIT FROM DBA_ROLE_PRIVS WHERE GRANTEE='%s') WHERE LIMIT=%d" query2="SELECT DISTINCT(GRANTED_ROLE) FROM (SELECT DISTINCT(GRANTED_ROLE),ROWNUM AS LIMIT FROM USER_ROLE_PRIVS WHERE USERNAME='%s') WHERE LIMIT=%d" count="SELECT COUNT(DISTINCT(GRANTED_ROLE)) FROM DBA_ROLE_PRIVS WHERE GRANTEE='%s'" count2="SELECT COUNT(DISTINCT(GRANTED_ROLE)) FROM USER_ROLE_PRIVS WHERE USERNAME='%s'"/>
            </roles>
            <!-- NOTE: in Oracle schema names are the counterpart to database names on other DBMSes -->
            <dbs>
                <inband query="SELECT OWNER FROM (SELECT DISTINCT(OWNER) FROM SYS.ALL_TABLES)"/>
                <blind query="SELECT OWNER FROM (SELECT OWNER,ROWNUM AS LIMIT FROM (SELECT DISTINCT(OWNER) FROM SYS.ALL_TABLES)) WHERE LIMIT=%d" count="SELECT COUNT(DISTINCT(OWNER)) FROM SYS.ALL_TABLES"/>
            </dbs>
            <tables>
                <inband query="SELECT OWNER,TABLE_NAME FROM SYS.ALL_TABLES" condition="OWNER"/>
                <blind query="SELECT TABLE_NAME FROM (SELECT TABLE_NAME,ROWNUM AS LIMIT FROM SYS.ALL_TABLES WHERE OWNER='%s') WHERE LIMIT=%d" count="SELECT COUNT(TABLE_NAME) FROM SYS.ALL_TABLES WHERE OWNER='%s'"/>
            </tables>
            <columns>
                <inband query="SELECT COLUMN_NAME,DATA_TYPE FROM SYS.ALL_TAB_COLUMNS WHERE TABLE_NAME='%s'" condition="COLUMN_NAME"/>
                <blind query="SELECT COLUMN_NAME FROM SYS.ALL_TAB_COLUMNS WHERE TABLE_NAME='%s'" query2="SELECT DATA_TYPE FROM SYS.ALL_TAB_COLUMNS WHERE TABLE_NAME='%s' AND COLUMN_NAME='%s'" count="SELECT COUNT(COLUMN_NAME) FROM SYS.ALL_TAB_COLUMNS WHERE TABLE_NAME='%s'" condition="COLUMN_NAME"/>
            </columns>
            <dump_table>
                <inband query="SELECT %s FROM %s"/>
                <blind query="SELECT %s FROM (SELECT %s,ROWNUM AS LIMIT FROM %s) WHERE LIMIT=%d" count="SELECT COUNT(*) FROM %s"/>
            </dump_table>
            <search_db/>
            <search_table>
                <inband query="SELECT OWNER,TABLE_NAME FROM SYS.ALL_TABLES WHERE " condition="TABLE_NAME" condition2="OWNER"/>
                <blind query="SELECT DISTINCT(OWNER) FROM SYS.ALL_TABLES WHERE " query2="SELECT TABLE_NAME FROM SYS.ALL_TABLES WHERE OWNER='%s'" count="SELECT COUNT(DISTINCT(OWNER)) FROM SYS.ALL_TABLES WHERE " count2="SELECT COUNT(TABLE_NAME) FROM SYS.ALL_TABLES WHERE OWNER='%s'" condition="TABLE_NAME" condition2="OWNER"/>
            </search_table>
            <search_column>
                <inband query="SELECT TABLE_NAME FROM SYS.ALL_TAB_COLUMNS WHERE " condition="COLUMN_NAME"/>
                <blind query="" query2="SELECT DISTINCT(TABLE_NAME) FROM SYS.ALL_TAB_COLUMNS" count="" count2="SELECT COUNT(DISTINCT(TABLE_NAME)) FROM SYS.ALL_TAB_COLUMNS" condition="COLUMN_NAME"/>
            </search_column>
        </dbms>
    
        <!-- SQLite -->
        <dbms value="SQLite">
            <cast query="CAST(%s AS VARCHAR(8000))" dbms_version="&gt;=3.0"/>
            <length query="LENGTH(%s)"/>
            <isnull query="IFNULL(%s,' ')"/>
            <delimiter query="||"/>
            <limit query="LIMIT %d,%d"/>
            <limitregexp query="s+LIMITs+([d]+)s*\,s*([d]+)"/>
            <limitgroupstart query="1"/>
            <limitgroupstop query="2"/>
            <limitstring query=" LIMIT "/>
            <order query="ORDER BY %s ASC"/>
            <count query="COUNT(%s)"/>
            <comment query="--" query2="/*"/>
            <timedelay query="SELECT LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB(1000000%d))))" dbms_version="&gt;=3.0"/>
            <substring query="SUBSTR((%s),%d,%d)"/>
            <case query="SELECT (CASE WHEN (%s) THEN 1 ELSE 0 END)"/>
            <inference query="SUBSTR((%s),%d,1) > '%c'"/>
            <banner query="SELECT SQLITE_VERSION()"/>
            <current_user/>
            <current_db/>
            <is_dba/>
            <check_udf/>
            <users/>
            <passwords/>
            <privileges/>
            <roles/>
            <dbs/>
            <tables>
                <inband query="SELECT tbl_name FROM sqlite_master WHERE type='table'"/>
                <blind query="SELECT tbl_name FROM sqlite_master WHERE type='table' LIMIT %d,1" count="SELECT COUNT(tbl_name) FROM sqlite_master WHERE type='table'"/>
            </tables>
            <columns>
                <inband query="SELECT MIN(sql) FROM sqlite_master WHERE tbl_name='%s'"/>
                <blind query="SELECT sql FROM sqlite_master WHERE tbl_name='%s' LIMIT 1" condition=""/>
            </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/>
            <search_table/>
            <search_column/>
        </dbms>
    
        <!-- Microsoft Access -->
        <dbms value="Microsoft Access">
            <cast query="CVAR(%s)"/>
            <length query="LEN(%s)"/>
            <isnull query="IIF(LEN(%s)=0,' ',%s)"/>
            <delimiter query=","/>
            <limit query="TOP %d"/>
            <limitregexp query="s+TOPs+([d]+)"/>
            <limitgroupstart query="1"/>
            <limitgroupstop query="1"/>
            <limitstring query=" TOP "/>
            <order query="ORDER BY %s ASC"/>
            <count query="COUNT(%s)"/>
            <comment query="%00"/>
            <timedelay/>
            <substring query="MID((%s),%d,%d)"/>
            <case query="IIF(%s,1,0)"/>
            <banner/>
            <!--CURRENTUSER() is not available outside the MS Access query tool itself-->
            <current_user/>
            <current_db/>
            <inference query="ASC(MID((%s),%d,1)) > %d"/>
            <is_dba/>
            <dbs/>
            <!--MSysObjects have no read permission by default-->
            <tables>
                <blind query="SELECT MIN(Name) FROM MSysObjects WHERE Type=1 AND Name>'%s'" count="SELECT COUNT(Name) FROM MSysObjects WHERE Type=1"/>
            </tables>
            <dump_table>
                <inband query="SELECT %s FROM %s"/>
                <blind query="SELECT MIN(%s) FROM %s WHERE CVAR(%s)>'%s'" query2="SELECT TOP 1 %s FROM %s WHERE CVAR(%s) LIKE '%s'" count="SELECT COUNT(*) FROM %s" count2="SELECT COUNT(*) FROM (SELECT DISTINCT %s FROM %s)"/>
            </dump_table>
            <users/>
            <privileges/>
            <roles/>
            <search_db/>
            <search_table/>
            <search_column/>
       </dbms>
    
       <!-- Firebird -->
       <dbms value="Firebird">
            <cast query="CAST(%s AS VARCHAR(10000))"/>
            <length query="CHAR_LENGTH(%s)"/>
            <!-- TODO: add proper value -->
            <delimiter query=""/>
            <limit query="ROWS %d TO %d"/>
            <limitregexp query="s+ROWSs+([d]+)(s+TOs+([d]+))?"/>
            <limitgroupstart query="1"/>
            <limitgroupstop query="2"/>
            <limitstring query=" ROWS "/>
            <isnull query="%s"/>
            <order query="ORDER BY %s ASC"/>
            <comment query="--"/>
            <count query="COUNT(%s)"/>
            <timedelay query="SELECT COUNT(*) FROM RDB$DATABASE AS T1,RDB$FIELDS AS T2,RDB$FUNCTIONS AS T3,RDB$TYPES AS T4,RDB$FORMATS AS T5,RDB$COLLATIONS AS T6"/>
            <substring query="SUBSTRING((%s) FROM %d FOR %d)"/>
            <case query="SELECT IIF(%s,1,0)"/>
            <banner query="SELECT RDB$GET_CONTEXT('SYSTEM','ENGINE_VERSION') FROM RDB$DATABASE" dbms_version="&gt;=2.1"/>
            <current_user query="SELECT CURRENT_USER FROM RDB$DATABASE"/>
            <current_db query="SELECT RDB$GET_CONTEXT('SYSTEM','DB_NAME') FROM RDB$DATABASE"/>
            <users>
                <inband query="SELECT DISTINCT RDB$USER FROM RDB$USER_PRIVILEGES"/>
                <blind query="SELECT FIRST 1 SKIP %d DISTINCT(RDB$USER) FROM RDB$USER_PRIVILEGES" count="SELECT COUNT(DISTINCT(RDB$USER)) FROM RDB$USER_PRIVILEGES"/>
            </users>
            <inference query="ASCII_VAL(SUBSTRING((%s) FROM %d FOR 1)) > %d" dbms_version="&gt;=2.1" query2="SUBSTRING((%s) FROM %d FOR 1) > '%c'"/>
            <is_dba query="CURRENT_USER='SYSDBA'"/>
            <tables>
                <inband query="SELECT RDB$RELATION_NAME FROM RDB$RELATIONS WHERE RDB$VIEW_BLR IS NULL AND (RDB$SYSTEM_FLAG IS NULL OR RDB$SYSTEM_FLAG = 0)"/>
                <blind query="SELECT FIRST 1 SKIP %d RDB$RELATION_NAME FROM RDB$RELATIONS WHERE RDB$VIEW_BLR IS NULL AND (RDB$SYSTEM_FLAG IS NULL OR RDB$SYSTEM_FLAG = 0)" count="SELECT COUNT(RDB$RELATION_NAME) FROM RDB$RELATIONS WHERE RDB$VIEW_BLR IS NULL AND (RDB$SYSTEM_FLAG IS NULL OR RDB$SYSTEM_FLAG = 0)"/>
            </tables>
            <privileges>
                <inband query="SELECT RDB$USER,RDB$PRIVILEGE FROM RDB$USER_PRIVILEGES" condition="RDB$USER"/>
                <blind query="SELECT FIRST 1 SKIP %d DISTINCT(RDB$PRIVILEGE) FROM RDB$USER_PRIVILEGES WHERE RDB$USER='%s'" count="SELECT COUNT(DISTINCT(RDB$PRIVILEGE)) FROM RDB$USER_PRIVILEGES WHERE RDB$USER='%s'"/>
            </privileges>
            <roles/>
            <dbs/>
            <columns>
                <!--<inband query="SELECT r.RDB$FIELD_NAME,CASE f.RDB$FIELD_TYPE WHEN 261 THEN 'BLOB' WHEN 14 THEN 'CHAR' WHEN 40 THEN 'CSTRING' WHEN 11 THEN 'D_FLOAT' WHEN 27 THEN 'DOUBLE' WHEN 10 THEN 'FLOAT' WHEN 16 THEN 'INT64' WHEN 8 THEN 'INTEGER' WHEN 9 THEN 'QUAD' WHEN 7 THEN 'SMALLINT' WHEN 12 THEN 'DATE' WHEN 13 THEN 'TIME' WHEN 35 THEN 'TIMESTAMP' WHEN 37 THEN 'VARCHAR' ELSE 'UNKNOWN' END AS field_type FROM RDB$RELATION_FIELDS r LEFT JOIN RDB$FIELDS f ON r.RDB$FIELD_SOURCE = f.RDB$FIELD_NAME WHERE r.RDB$RELATION_NAME='%s'"/>-->
                <inband query="SELECT r.RDB$FIELD_NAME,f.RDB$FIELD_TYPE FROM RDB$RELATION_FIELDS r LEFT JOIN RDB$FIELDS f ON r.RDB$FIELD_SOURCE = f.RDB$FIELD_NAME WHERE r.RDB$RELATION_NAME='%s'"/>
                <blind query="SELECT r.RDB$FIELD_NAME FROM RDB$RELATION_FIELDS r LEFT JOIN RDB$FIELDS f ON r.RDB$FIELD_SOURCE = f.RDB$FIELD_NAME WHERE r.RDB$RELATION_NAME='%s'" query2="SELECT f.RDB$FIELD_TYPE FROM RDB$RELATION_FIELDS r LEFT JOIN RDB$FIELDS f ON r.RDB$FIELD_SOURCE = f.RDB$FIELD_NAME WHERE r.RDB$RELATION_NAME='%s' AND r.RDB$FIELD_NAME='%s'" count="SELECT COUNT(r.RDB$FIELD_NAME) FROM RDB$RELATION_FIELDS r LEFT JOIN RDB$FIELDS f ON r.RDB$FIELD_SOURCE = f.RDB$FIELD_NAME WHERE r.RDB$RELATION_NAME='%s'"/>
            </columns>
            <dump_table>
                <inband query="SELECT %s FROM %s"/>
                <blind query="SELECT FIRST 1 SKIP %d %s FROM %s" count="SELECT COUNT(*) FROM %s"/>
            </dump_table>
            <search_db/>
            <search_table/>
            <search_column/>
       </dbms>
    
       <!-- http://dev.mysql.com/tech-resources/articles/maxdb-php-ready-for-web.html -->
       <!-- http://dev.mysql.com/doc/refman/5.0/es/maxdb-reserved-words.html -->
       <!-- http://maxdb.sap.com/doc/7_6/default.htm -->
       <!-- http://www.sapdb.org/7.4/htmhelp/35/f8823cb7e5d42be10000000a114027/content.htm -->
       <!-- http://www.ximido.de/research/PenTestingMaxDB.pdf -->
    
       <!-- SAP MaxDB -->
       <dbms value="SAP MaxDB">
            <length query="LENGTH(%s)"/>
            <timedelay/>
            <banner query="SELECT ID FROM SYSINFO.VERSION"/>
            <isnull query="VALUE(%s,' ')" query2="IFNULL(%s,' ')"/>
            <comment query="--" query2="#"/>
            <count query="COUNT(%s)"/>
            <!-- No real cast on SAP MaxDB -->
            <cast query="REPLACE(CHR(%s),' ','_')"/>
            <current_user query="SELECT USER() FROM DUAL"/>
            <current_db query="SELECT DATABASE() FROM DUAL"/>
            <order query="ORDER BY %s ASC"/>
            <case query="SELECT (CASE WHEN (%s) THEN 1 ELSE 0 END)"/>
            <inference query="SUBSTR((%s),%d,1) > '%c'"/>
            <delimiter query=","/>
            <substring query="SUBSTR((%s),%d,%d)"/>
            <users>
                <inband query="SELECT username FROM domain.users"/>
                <blind query="SELECT MIN(username) FROM domain.users WHERE username > '%s'" count="SELECT CHR(COUNT(*)) FROM domain.users"/>
            </users>
            <columns>
                <inband query="SELECT columnname,datatype,len FROM domain.columns WHERE tablename='%s' AND schemaname=%s"/>
                <blind/>
            </columns>
            <tables>
                <inband query="SELECT tablename FROM domain.tables WHERE schemaname=%s AND type='TABLE'"/>
                <blind/>
            </tables>
            <dbs>
                <inband query="SELECT DISTINCT(schemaname) FROM domain.tables"/>
                <blind/>
            </dbs>
            <roles>
                <inband query="SELECT owner,role FROM domain.roles" condition="owner"/>
                <blind/>
            </roles>
            <dump_table>
                <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 value_table"/>
            </dump_table>
       </dbms>
    
        <!-- Sybase -->
        <dbms value="Sybase">
            <cast query="CONVERT(NVARCHAR(4000),%s)"/>
            <length query="LTRIM(STR(LEN(%s)))"/>
            <isnull query="ISNULL(%s,' ')"/>
            <delimiter query="+"/>
            <limit query="SELECT TOP %d "/>
            <limitregexp query="TOPs+([d]+)s+.+?s+FROMs+.+?s+WHEREs+.+?s+NOTs+INs+(SELECTs+TOPs+([d]+)s+"/>
            <limitgroupstart query="2"/>
            <limitgroupstop query="1"/>
            <limitstring/>
            <order query="ORDER BY %s ASC"/>
            <count query="COUNT(%s)"/>
            <comment query="--" query2="/*"/>
            <timedelay query="WAITFOR DELAY '0:0:%d'"/>
            <substring query="SUBSTRING((%s),%d,%d)"/>
            <case query="SELECT (CASE WHEN (%s) THEN '1' ELSE '0' END)"/>
            <inference query="ASCII(SUBSTRING((%s),%d,1)) > %d"/>
            <banner query="SELECT @@VERSION"/>
            <current_user query="SELECT SUSER_NAME()"/>
            <current_db query="SELECT DB_NAME()"/>
            <is_dba query="PATINDEX('%sa_role%',SHOW_ROLE())>0" query2="EXISTS(SELECT * FROM master..syslogins,master..sysloginroles WHERE srid=0 and name='%s')"/>
            <users>
                <inband query="SELECT name FROM master..syslogins"/>
                <blind/>
            </users>
            <passwords>
                <inband query="SELECT name,password FROM master..syslogins" condition="name"/>
                <blind/>
            </passwords>
            <privileges/>
            <roles>
                <inband query="SELECT name,srid FROM master..syslogins,master..sysloginroles" condition="name"/>
                <blind/>
            </roles>
            <dbs>
                <inband query="SELECT name FROM master..sysdatabases"/>
                <blind/>
            </dbs>
            <tables>
                <inband query="SELECT name FROM %s..sysobjects WHERE type IN ('U')"/>
                <blind/>
            </tables>
            <columns>
                <inband query="SELECT %s..syscolumns.name,%s..syscolumns.usertype FROM %s..syscolumns,%s..sysobjects WHERE %s..syscolumns.id=%s..sysobjects.id AND %s..sysobjects.name='%s'" condition="[DB]..syscolumns.name"/>
                <blind/>
            </columns>
            <dump_table>
                <inband query="SELECT %s FROM %s..%s"/>
                <blind query="SELECT MIN(%s) FROM %s WHERE CONVERT(NVARCHAR(4000),%s)>'%s'" query2="SELECT MAX(%s) FROM %s WHERE CONVERT(NVARCHAR(4000),%s) LIKE '%s'" count="SELECT COUNT(*) FROM %s" count2="SELECT COUNT(*) FROM (SELECT DISTINCT %s FROM %s) AS value_table"/>
            </dump_table>
            <search_db>
                <inband query="SELECT name FROM master..sysdatabases WHERE " condition="name"/>
                <blind/>
            </search_db>
            <search_table>
                <inband query="SELECT name FROM %s..sysobjects WHERE type IN ('U') AND " condition="name" condition2="name"/>
                <blind/>
            </search_table>
            <search_column>
                <inband query="SELECT %s..sysobjects.name FROM %s..syscolumns,%s..sysobjects WHERE %s..syscolumns.id=%s..sysobjects.id" condition="[DB]..syscolumns.name"/>
                <blind/>
            </search_column>
        </dbms>
    </root>
    XML

    需求

    基本上每个元素结点中都有query属性,比如:

    元素结点:<order query="ORDER BY %s ASC"/>

    query属性值:ORDER BY %s ASC

    现在需要提取出结点名称和与之对应的query属性值

    执行结果如下图所示:

    分析

    <root>是根节点,文档中的所有其他节点都被包含在<root>中。

    根节点<root>共有9个<dbms>节点

    每个<dbms>节点表示一种数据库,value的值是数据库名称

    现在我们直接以MySQL的dbms节点作为分析对象。

    <dbms value="MySQL">节点包含了30多个子节点,sqlmap会根据用户在终端中给出的参数进而读取相应的子节点的query值。

    比如:

    当用户在终端中输入以下命令:python sqlmap.py -u 'http://127.0.0.1/?id=1' --current-user

    说明用户想获取网站:http://127.0.0.1上所运行的数据库的当前用户名。

    注:<dbms value="MySQL">节点下文用MySQL节点表示,<current_user query="CURRENT_USER()"/>节点用current_user节点表示,以此类推

    我们发现在queries.xml文件中,MySQL节点的子节点中有一个节点:current_user节点

    节点名称是:current_user

    query值:CURRENT_USER()

    sqlmap中会通过以下代码来获取的:

    if conf.getCurrentUser:
      conf.dumper.currentUser(conf.dbmsHandler.getCurrentUser())

    getCurrentUser()函数的代码如下:

    def getCurrentUser(self):
        infoMsg = "fetching current user"
        logger.info(infoMsg)
        query = queries[Backend.getIdentifiedDbms()].current_user.query
        if not kb.data.currentUser:
            kb.data.currentUser = unArrayizeValue(inject.getValue(query))
        return kb.data.currentUser

    当运行后,通过pycharm调试可以发现,query的值就是等于current_user节点的query属性的值:CURRENT_USER()

    这次主要就是对代码

    query = queries[Backend.getIdentifiedDbms()].current_user.query

    的实现方法进行分析。

    其中,有个地方需要特别注意,在节点dbms的部分子节点还含有子节点。

    比如:users节点就包含inband和blind2个子节点。解决办法就是使用递归(sqlmap就是这么做的)

    想通过代码:queries["MySQL"].current_db.query 来获取制定的query的值的话,需要将每个节点的信息封装到一个类中(XMLNode)

    比如:MySQL节点下包含有很多的子节点,所以,XMLNode类中应该有一个容器能够用来保存所有的子节点的信息。

    XMLNode类的代码如下:

    class XMLNode:
        def __init__(self,parent,node):
            self._node          = node
            self._nodeName      = node.nodeName
            self._childrenByName= {}
    
            parentDict  = parent._childrenByName
            nodeName    = node.nodeName
    
            if not parentDict.has_key(nodeName):
                parentDict[nodeName]        = self
            else:
                if isinstance(parentDict[nodeName],XMLNode):
                    parentDict[nodeName]    = [parentDict[nodeName]]
                parentDict[nodeName].append(self)
    
            self._value = None
            if isinstance(node, xml.dom.minidom.Text):
                self._type = "text"
                self._value = ""
            elif isinstance(node, xml.dom.minidom.Element):
                self._type = "node"
            elif isinstance(node, xml.dom.minidom.Comment):
                self._type = "comment"
                self._value = node.nodeValue
    
            for child in node.childNodes:
                XMLNode(self,child)
    
        def __getattr__(self, attr):
            if self._type in ['text', 'comment']:
                return None
            if self._node.hasAttribute(attr):
                return self._node.getAttribute(attr)
            elif self._childrenByName.has_key(attr):
                return self._childrenByName[attr]

    其中,变量_childrenByName保存着某个节点的子节点信息

    if not parentDict.has_key(nodeName):
            parentDict[nodeName]        = self

    注:parentDict表示当前节点的父节点_childrenByName值

    比如:当前正递归到MySQL节点的current_user节点,此时,nodeName=current_user,self表示current_user节点的信息,由于此时

    parentDict.has_key(nodeName)的执行结果为False,所以就将current_user节点的信息(self)赋值给parentDict[nodeName]

    另外,如果当前节点的父节点已经包含有nodeName属性值的时候

    比如:root节点下有9个dbms节点,当递归遍历dbms节点的时候,由于每个dbms节点的nodeName都是等于dbms,所以此时,应该将后续的dbms节点append进去。

    当有多一个相同名字的子节点的时候,sqlmap中是使用list来存储的,代码如下所示:

    if isinstance(parentDict[nodeName],XMLNode):
        parentDict[nodeName]    = [parentDict[nodeName]]
    parentDict[nodeName].append(self)

    递归遍历可以通过以下代码来实现:

    for child in node.childNodes:
        XMLNode(self,child)

    至此,queries["MySQL"].current_db.query的实现基本上差不多了,只是我们想通过.current_db.query来访问的话,我们还需要另外添加一个__getattr__函数

    def __getattr__(self, attr):
        if self._type in ['text', 'comment']:
            return None
        if self._node.hasAttribute(attr):
            return self._node.getAttribute(attr)
        elif self._childrenByName.has_key(attr):
            return self._childrenByName[attr]

    代码很简单,当要访问的节点类型为文本节点时(comment和text的时候),由于文本节点并没有hasAttribute()方法,所以简单的返回None(详细的可以参考sqlmap源码,我这是精简版的,^_^)

    比如:元素节点dbms含有value属性值,dbms节点的子节点基本都有query属性值

    当执行queries["MySQL"].current_db.query的时候,由于queries["MySQL"].current_db的类型为XMLNode,所以通过点号(.)来获取query属性值的时候,就会调用__getattr__函数,进而通过self._node.getAttribute(attr)来返回节点的query值。

    另外,当执行代码:queries["MySQL"].current_db的时候,由于每个元素节点中,并没有current_db属性,所以就会跳转到

    elif self._childrenByName.has_key(attr):
         return self._childrenByName[attr]

    之前,我们已经通过递归遍历,将各个节点的信息以nodeName为下标,self(当前节点的XMLNode对象)为值保存起来了
    具体就是以下代码:

    if not parentDict.has_key(nodeName):
        parentDict[nodeName]        = self
    else:
        if isinstance(parentDict[nodeName],XMLNode):
            parentDict[nodeName]    = [parentDict[nodeName]]
        parentDict[nodeName].append(self)

    完整代码

    index.py

    from xmlobject.xmltest import XMLFile
    from xmlobject.xmltest import XMLNode
    
    queries = {}
    def main():
        xml = XMLFile(path = "queries.xml")
        """Type 1"""
        for node in xml.root.dbms:
            queries[node.value] = node
        print queries["MySQL"].current_db.query
        """Type 2"""
        for node in xml.root.dbms:
            print "*"*20+str(node.value)+"*"*20
            for _ in node._childrenByName:
                if isinstance(node._childrenByName[_],XMLNode):
                    nodeName = node._childrenByName[_]._nodeName
                    query = node._childrenByName[_].query
                    print "[%s]     %s"%(nodeName,query)
    
    if __name__ =="__main__":
        main()
    index.py

    xmltest.py

    import xml.dom.minidom
    
    class XMLFile:
        def __init__(self,**kwargs):
            path     = kwargs.get("path",None)
            self._childrenByName = {}
    
            dom = xml.dom.minidom.parse(path)
            root = dom.documentElement
            for node in dom.childNodes:
                childnode = XMLNode(self,node)
                if root == node:
                    self.root = childnode
    
    class XMLNode:
        def __init__(self,parent,node):
            self._node          = node
            self._nodeName      = node.nodeName
            self._childrenByName= {}
    
            parentDict  = parent._childrenByName
            nodeName    = node.nodeName
    
            if not parentDict.has_key(nodeName):
                parentDict[nodeName]        = self
            else:
                if isinstance(parentDict[nodeName],XMLNode):
                    parentDict[nodeName]    = [parentDict[nodeName]]
                parentDict[nodeName].append(self)
    
            self._value = None
            if isinstance(node, xml.dom.minidom.Text):
                self._type = "text"
                self._value = ""
            elif isinstance(node, xml.dom.minidom.Element):
                self._type = "node"
            elif isinstance(node, xml.dom.minidom.Comment):
                self._type = "comment"
                self._value = node.nodeValue
    
            for child in node.childNodes:
                XMLNode(self,child)
    
        def __getattr__(self, attr):
            if self._type in ['text', 'comment']:
                return None
            if self._node.hasAttribute(attr):
                return self._node.getAttribute(attr)
            elif self._childrenByName.has_key(attr):
                return self._childrenByName[attr]
    xmltest.py

    在分析代码的过程中,发现pycharm的调试功能很强大,帮了我不少忙,也推荐大家使用下

    Pycharm下断调试:http://blog.csdn.net/chenggong2dm/article/details/9368641

    注:Pycharm支持下条件断点的

    作       者:曾是土木人

    转载请注明出处:http://www.cnblogs.com/hongfei/p/sqlmap-xml.html

  • 相关阅读:
    讨论Android开发中的MVC设计思想
    关于AppFromwork集成XMPP开发的使用详解
    Android 强大的开发支持库组件AppFromwork框架详解
    Z语音概述from百度
    《软件形式规格说明语言-Z》 缪淮扣 学习笔记 10-12
    形式化规格技术和验证技术小结
    编译TS发生 Property or signature expected
    electron 启动错误
    java学习第三章4.运算
    java学习第三章3.基本类型的转换和直接量
  • 原文地址:https://www.cnblogs.com/hongfei/p/sqlmap-xml.html
Copyright © 2020-2023  润新知