0x003 SQLMAP如何检测是否存在SQL注入

0x003 SQLMAP如何检测是否存在SQL注入

我们直接看到lib.controller.controller​中的strat()​方法

因为start()​代码较长,所以我们这里就调重要的代码进行分析

parseTargetUrl()

            testSqlInj = False

            if PLACE.GET in conf.parameters and not any((conf.data, conf.testParameter)):
                for parameter in re.findall(r"([^=]+)=([^%s]+%s?|\Z)" % (re.escape(conf.paramDel or "") or DEFAULT_GET_POST_DELIMITER, re.escape(conf.paramDel or "") or DEFAULT_GET_POST_DELIMITER), conf.parameters[PLACE.GET]):
                    paramKey = (conf.hostname, conf.path, PLACE.GET, parameter[0])

                    if paramKey not in kb.testedParams:
                        testSqlInj = True
                        break
            else:
                paramKey = (conf.hostname, conf.path, None, None)
                if paramKey not in kb.testedParams:
                    testSqlInj = True

            if testSqlInj and conf.hostname in kb.vulnHosts:
                if kb.skipVulnHost is None:
                    message = "SQL injection vulnerability has already been detected "
                    message += "against '%s'. Do you want to skip " % conf.hostname
                    message += "further tests involving it? [Y/n]"

                    kb.skipVulnHost = readInput(message, default='Y', boolean=True)

                testSqlInj = not kb.skipVulnHost

            if not testSqlInj:
                infoMsg = "skipping '%s'" % targetUrl
                logger.info(infoMsg)
                continue

首先调用了parseTargetUrl()​函数进行了解析

def parseTargetUrl():
    """
    Parse target URL and set some attributes into the configuration singleton

    >>> pushValue(conf.url)
    >>> conf.url = "https://www.test.com/?id=1"
    >>> parseTargetUrl()
    >>> conf.hostname
    'www.test.com'
    >>> conf.scheme
    'https'
    >>> conf.url = popValue()
    """

就是简单解析了一下url​ 区分是http​还是https​等等

testSqlInj​用来表示是否需要测试SQL注入漏洞,初始值为False

然后判断是否为GET​请求,且没有conf.data​和conf.testParameter​两个参数

如果上述条件满足就可以对每个GET​请求参数进行分析,判断是否这些参数是否在testedParameter​参数中,如果不在,则将testSqlInj​设置为True

如果需要测试的主机在已经知道存在漏洞的主机列表kb.vulnHosts​中,则进一步处理,提示用户是否需要跳过对这个主机的测试

这里正则的逻辑就是先匹配一段非=的任意长度的字符​然后用=​号分割键和值,再对值进行匹配

if testSqlInj:
                            try:
                                if place == PLACE.COOKIE:
                                    pushValue(kb.mergeCookies)
                                    kb.mergeCookies = False

                                check = heuristicCheckSqlInjection(place, parameter)

                                if check != HEURISTIC_TEST.POSITIVE:
                                    if conf.smart or (kb.ignoreCasted and check == HEURISTIC_TEST.CASTED):
                                        infoMsg = "skipping %sparameter '%s'" % ("%s " % paramType if paramType != parameter else "", parameter)
                                        logger.info(infoMsg)
                                        continue

                                infoMsg = "testing for SQL injection on %sparameter '%s'" % ("%s " % paramType if paramType != parameter else "", parameter)
                                logger.info(infoMsg)
                                # 真正开始sql注入的地方
                                injection = checkSqlInjection(place, parameter, value)
                                proceed = not kb.endDetection
                                injectable = False

                                if getattr(injection, "place", None) is not None:
                                    if NOTE.FALSE_POSITIVE_OR_UNEXPLOITABLE in injection.notes:
                                        kb.falsePositives.append(injection)
                                    else:
                                        injectable = True

                                        kb.injections.append(injection)

                                        if not kb.alerted:
                                            if conf.alert:
                                                infoMsg = "executing alerting shell command(s) ('%s')" % conf.alert
                                                logger.info(infoMsg)
                                                try:
                                                    process = subprocess.Popen(conf.alert, shell=True)
                                                    process.wait()
                                                except Exception as ex:
                                                    errMsg = "error occurred while executing '%s' ('%s')" % (conf.alert, getSafeExString(ex))
                                                    logger.error(errMsg)

                                            kb.alerted = True

                                        # In case when user wants to end detection phase (Ctrl+C)
                                        if not proceed:
                                            break

                                        msg = "%sparameter '%s' " % ("%s " % injection.place if injection.place != injection.parameter else "", injection.parameter)
                                        msg += "is vulnerable. Do you want to keep testing the others (if any)? [y/N] "

                                        if not readInput(msg, default='N', boolean=True):
                                            proceed = False
                                            paramKey = (conf.hostname, conf.path, None, None)
                                            kb.testedParams.add(paramKey)

                                if not injectable:
                                    warnMsg = "%sparameter '%s' does not seem to be injectable" % ("%s " % paramType if paramType != parameter else "", parameter)
                                    logger.warning(warnMsg)

                            finally:
                                if place == PLACE.COOKIE:
                                    kb.mergeCookies = popValue()

这段代码就是真正进行sql注入​的地方

首先启发性检测sql注入​,通过heuristicCheckSqlInjection()​这个函数

如果启发性测试成功了的话,check​就会等于HEURISTIC_TEST.POSITIVE​这个参数,不成功的话就跳过

我们来看看heuristicCheckSqlInjection()​函数也就是启发性sql注入​的代码

def heuristicCheckSqlInjection(place, parameter):
    if conf.skipHeuristics:
        return None
    # 获取参数
    origValue = conf.paramDict[place][parameter]
    paramType = conf.method if conf.method not in (None, HTTPMETHOD.GET, HTTPMETHOD.POST) else place

    prefix = ""
    suffix = ""
    randStr = ""
    # 由conf的值决定prefix和suffix
    if conf.prefix or conf.suffix:
        if conf.prefix:
            prefix = conf.prefix

        if conf.suffix:
            suffix = conf.suffix
    # rendStr 生成的启发式payload 单引号或者双引号的个数不等于1
    while randStr.count('\'') != 1 or randStr.count('\"') != 1:
        """
        返回具有给定字符数的随机字符串值
        长度10 HEURISTIC_CHECK_ALPHABET
        可以在lib/core/settings.py中找到HEURISTIC_CHECK_ALPHABET的配置
        HEURISTIC_CHECK_ALPHABET = ('"', '\'', ')', '(', ',', '.')
        随机生成长度为10的 且生成的内容的基础是HEURISTIC_CHECK_ALPHABET
        """
        randStr = randomStr(length=10, alphabet=HEURISTIC_CHECK_ALPHABET)
    # 启发模式设置为True
    kb.heuristicMode = True
    # 将生成的随机字符串拼接进入payload,如果我们conf的属性中prefix和suffix为空的话,这里直接就是randStr了
    payload = "%s%s%s" % (prefix, randStr, suffix)
    # 将请求类型 place 请求参数 parameter 和生成的payload也就是randStr传入agent.payload中
    # 也就是?id=1 插入payload分隔符 1 后面再加上随机字符串,然后再加上payload分隔符
    payload = agent.payload(place, parameter, newValue=payload)
    page, _, _ = Request.queryPage(payload, place, content=True, raise404=False)

    kb.heuristicPage = page

    kb.heuristicMode = False

    # 通过返回的页面获取可能的路径,也是正则匹配
    parseFilePaths(page)
    # 通过页面回显查询是否有可识别的数据库报错,如果匹配到了返回True反之则为False
    result = wasLastResponseDBMSError()

    infoMsg = "heuristic (basic) test shows that %sparameter '%s' might " % ("%s " % paramType if paramType != parameter else "", parameter)

    def _(page):
        # 启发式的请求的返回有异常字符串
        # FORMAT_EXCEPTION_STRINGS同样在setting.py中
        # FORMAT_EXCEPTION_STRINGS = ("Type mismatch", "Error converting", "Please enter a", "Conversion failed", "String or binary data would be truncated", "Failed to convert", "unable to interpret text value", "Input string was not in a correct format", "System.FormatException", "java.lang.NumberFormatException", "ValueError: invalid literal", "TypeMismatchException", "CF_SQL_INTEGER", "CF_SQL_NUMERIC", " for CFSQLTYPE ", "cfqueryparam cfsqltype", "InvalidParamTypeException", "Invalid parameter type", "Attribute validation error for tag", "is not of type numeric", "<cfif Not IsNumeric(", "invalid input syntax for integer", "invalid input syntax for type", "invalid number", "character to number conversion error", "unable to interpret text value", "String was not recognized as a valid", "Convert.ToInt", "cannot be converted to a ", "InvalidDataException", "Arguments are of the wrong type")
        return any(_ in (page or "") for _ in FORMAT_EXCEPTION_STRINGS)

    casting = _(page) and not _(kb.originalPage) # 如果页面回显有异常字符串有True,反之为False
    # 这里是启发式判断是否有 数据库报错获取数据库类型 代码执行的错误
    if not casting and not result and kb.dynamicParameter and origValue.isdigit() and not kb.heavilyDynamic:
        # 上面请求的回显没有报错的话就执行下面的代码
        randInt = int(randomInt())
        payload = "%s%s%s" % (prefix, "%d-%d" % (int(origValue) + randInt, randInt), suffix)
        payload = agent.payload(place, parameter, newValue=payload, where=PAYLOAD.WHERE.REPLACE)
        result = Request.queryPage(payload, place, raise404=False) # 比较页面内容

        if not result:
            # 如果还是不行就随机生成字符串再尝试一遍
            randStr = randomStr()
            payload = "%s%s%s" % (prefix, "%s.%d%s" % (origValue, random.randint(1, 9), randStr), suffix)
            payload = agent.payload(place, parameter, newValue=payload, where=PAYLOAD.WHERE.REPLACE)
            casting = Request.queryPage(payload, place, raise404=False)
    # 根据上面的返回来查看是否匹配了一些异常 也就是setting中定义的值和页面的内容来判断是否存在出入
    kb.heuristicTest = HEURISTIC_TEST.CASTED if casting else HEURISTIC_TEST.NEGATIVE if not result else HEURISTIC_TEST.POSITIVE

    if kb.heavilyDynamic:
        debugMsg = "heuristic check stopped because of heavy dynamicity"
        logger.debug(debugMsg)
        return kb.heuristicTest
    # 报错信息
    if casting:
        errMsg = "possible %s casting detected (e.g. '" % ("integer" if origValue.isdigit() else "type")

        platform = conf.url.split('.')[-1].lower()
        if platform == WEB_PLATFORM.ASP:
            errMsg += "%s=CInt(request.querystring(\"%s\"))" % (parameter, parameter)
        elif platform == WEB_PLATFORM.ASPX:
            errMsg += "int.TryParse(Request.QueryString[\"%s\"], out %s)" % (parameter, parameter)
        elif platform == WEB_PLATFORM.JSP:
            errMsg += "%s=Integer.parseInt(request.getParameter(\"%s\"))" % (parameter, parameter)
        else:
            errMsg += "$%s=intval($_REQUEST[\"%s\"])" % (parameter, parameter)

        errMsg += "') at the back-end web application"
        logger.error(errMsg)

        if kb.ignoreCasted is None:
            message = "do you want to skip those kind of cases (and save scanning time)? %s " % ("[Y/n]" if conf.multipleTargets else "[y/N]")
            kb.ignoreCasted = readInput(message, default='Y' if conf.multipleTargets else 'N', boolean=True)

    elif result:
        infoMsg += "be injectable"
        if Backend.getErrorParsedDBMSes():
            infoMsg += " (possible DBMS: '%s')" % Format.getErrorParsedDBMSes()
        logger.info(infoMsg)

    else:
        infoMsg += "not be injectable"
        logger.warning(infoMsg)

    kb.heuristicMode = True
    # 禁用HTML编码
    kb.disableHtmlDecoding = True
    # 随机生成两个payload,长度为6
    randStr1, randStr2 = randomStr(NON_SQLI_CHECK_PREFIX_SUFFIX_LENGTH), randomStr(NON_SQLI_CHECK_PREFIX_SUFFIX_LENGTH)
    value = "%s%s%s" % (randStr1, DUMMY_NON_SQLI_CHECK_APPENDIX, randStr2)
    payload = "%s%s%s" % (prefix, "'%s" % value, suffix)
    payload = agent.payload(place, parameter, newValue=payload)
    page, _, _ = Request.queryPage(payload, place, content=True, raise404=False)
    # 传入探测是否存在sql注入
    paramType = conf.method if conf.method not in (None, HTTPMETHOD.GET, HTTPMETHOD.POST) else place

    # Reference: https://bugs.python.org/issue18183
    if value.upper() in (page or "").upper():
        infoMsg = "heuristic (XSS) test shows that %sparameter '%s' might be vulnerable to cross-site scripting (XSS) attacks" % ("%s " % paramType if paramType != parameter else "", parameter)
        logger.info(infoMsg)

        if conf.beep:
            beep()

    for match in re.finditer(FI_ERROR_REGEX, page or ""):
        if randStr1.lower() in match.group(0).lower():
            infoMsg = "heuristic (FI) test shows that %sparameter '%s' might be vulnerable to file inclusion (FI) attacks" % ("%s " % paramType if paramType != parameter else "", parameter)
            logger.info(infoMsg)

            if conf.beep:
                beep()

            break

    kb.disableHtmlDecoding = False
    kb.heuristicMode = False

    return kb.heuristicTest


接下来的检测sql注入的主要函数我们后续再详细分析
如果文章中内容有误,希望大佬们帮忙指正!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/594436.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【源码】 频裂变加群推广强制分享引流源码

视频裂变加群推广强制分享引流源码&#xff0c;用户达到观看次数后需要分享给好友或者群,好友必须点击推广链接后才会增加观看次数。 引导用户转发QV分享,达到快速裂变引流的效果&#xff01; 视频裂变推广程序&#xff0c;强制分享链接&#xff0c;引导用户转发&#xff0c;…

prometheus搭建

1.prometheus下载 下载地址:Download | Prometheus 请下载LTS稳定版本 本次prometheus搭建使用prometheus-2.37.1.linux-amd64.tar.gz版本 2.上传prometheus-2.37.1.linux-amd64.tar.gz至服务器/opt目录 CentOS7.9 使用命令rz -byE上传 3.解压缩prometheus-2.37.1.linux…

VscodeC/C++环境配置

引言 vscode是一款非常好用的编辑器&#xff0c;集成了大量的插件&#xff0c;具有很高的自由度&#xff0c;因此广受大家的喜爱。但是他本身是不带编译器的&#xff0c;因此如果要使用vscode来编译C/C程序的话&#xff0c;我们需要额外安装编译器并且为vscode配上环境。 编译…

Docker 入门与实践:从零开始构建容器化应用环境

Docker 一、docker常用命令docker ps 格式化输出Linux设置命令别名 二、数据卷相关命令挂载到默认目录&#xff08;/var/lib/docker&#xff09;挂载到本地目录 三、自定义镜像Dockerfile构建镜像的命令 四、网络自定义网络 五、DockerCompose相关命令 一、docker常用命令 dock…

Python | Leetcode Python题解之第71题简化路径

题目&#xff1a; 题解&#xff1a; class Solution:def simplifyPath(self, path: str) -> str:names path.split("/")stack list()for name in names:if name "..":if stack:stack.pop()elif name and name ! ".":stack.append(name)re…

ThreeJS:光线投射与3D场景交互

光线投射Raycaster 光线投射详细介绍可参考&#xff1a;https://en.wikipedia.org/wiki/Ray_casting&#xff0c; ThreeJS中&#xff0c;提供了Raycaster类&#xff0c;用于进行鼠标拾取&#xff0c;即&#xff1a;当三维场景中鼠标移动时&#xff0c;利用光线投射&#xff0c;…

点亮一个LED

新建项目 #include <REGX52.H>void main() {P2 0xFE;while(1){} }调整字体大小 在编译之前要勾选一个东西,不然scp读取不了 去stc-isp中烧录进51单片机 两个地方要勾选,一个是单片机型号,一个是串口号,我的单片机型号不是江科大视频里面那个型号,所以不能按视频里面来选…

【数据结构(邓俊辉)学习笔记】列表04——排序器

文章目录 0. 统一入口1. 选择排序1.1 构思1.2 实例1.3 实现1.4 复杂度 2. 插入排序2.1 构思2.2 实例2.3 实现2.4 复杂度分析2.5 性能分析 3. 归并排序3.1 二路归并算法3.1.1 二路归并算法原理3.1.2 二路归并算法实现3.1.3 归并时间 3.2 分治策略3.2.1 实现3.2.2 排序时间 4. 总…

学习笔记:【QC】Android Q - IMS 模块

一、IMS init 流程图 二、IMS turnon 流程图 三、分析说明 1、nv702870 不创建ims apn pdp 2、nv702811 nv702811的时候才创建ims pdp&#xff1a; ims pdp 由ims库发起&#xff0c;高通没有开放这部分代码&#xff1a; 10-10 11:45:53.027 943 943 E Diag_Lib: [IMS_D…

只用语音能训练出AI大模型吗?就像训练会说话但不识字的人一样

AI语音对话技术通常是基于语音识别和自然语言处理&#xff08;NLP&#xff09;的。在这个过程中&#xff0c;语音首先被识别成文字&#xff0c;然后NLP技术对这些文字进行处理&#xff0c;生成回应。然而&#xff0c;我们是否可以直接训练一个“文盲”大模型&#xff0c;即只用…

45. UE5 RPG 增加角色受击反馈

在前面的文章中&#xff0c;我们实现了对敌人的属性的初始化&#xff0c;现在敌人也拥有的自己的属性值&#xff0c;技能击中敌人后&#xff0c;也能够实现血量的减少。 现在还需要的就是在技能击中敌人后&#xff0c;需要敌人进行一些击中反馈&#xff0c;比如敌人被技能击中后…

深度学习中的注意力机制二(Pytorch 16)

一 Bahdanau 注意力 通过设计一个 基于两个循环神经网络的编码器‐解码器架构&#xff0c;用于序列到序列学习。具体来说&#xff0c;循环神经网络编码器将长度可变的序列转换为固定形状的上下文变量&#xff0c;然后循环神经网络 解码器根据生成的词元和上下文变量按词元生成…

meshlab: pymeshlab计算两个模型的布尔交集(mesh boolean intersection)

一、关于环境 请参考&#xff1a;pymeshlab遍历文件夹中模型、缩放并导出指定格式-CSDN博客 二、关于代码 本文所给出代码仅为参考&#xff0c;禁止转载和引用&#xff0c;仅供个人学习。 本案例以两个圆环为例。 左侧为两个圆环&#xff0c;右上是重叠&#xff0c;右下是圆…

引流源码短剧搜索前端源码+内附搜索API

引流源码短剧搜索前端源码内附搜索API&#xff0c;全网短剧搜索前端源码分享&#xff0c;文末附API及使用详解 内含7000短剧资源(不支持在线播放&#xff09;&#xff0c;毕竟搞在线播放挺烧钱的[阴险] 源码直接上传虚拟主机或服务器即可使用&#xff0c;无需其他配置&#x…

jvm 马士兵 01 JVM简介,class文件结构

01.JVM是什么 JVM是一个跨平台的标准 JVM只识别class文件&#xff0c;符合JVM规范的class文件都可以被识别 u1 是一个字节 u2是两个字节

使用网络用户命令行工具的/passwordreq:yes

提示:"新建域时&#xff0c;本地administrator帐户将成为域administrator账户。无法新建域&#xff0c;因为本地administrator账户密码不符合要求。 目前&#xff0c;本地administrator账户不需要密码。我们建议您使用网络用户命令行工具的/passwordreq:yes选项获得该账户…

AI图书推荐:ChatGPT在真实商业世界中的应用

《ChatGPT在真实商业世界中的应用》 (Unleashing The Power of ChatGPT: A Real World Business Applications)首先概述了ChatGPT及其在对话式人工智能领域的影响。接着&#xff0c;你将深入了解ChatGPT的技术方面&#xff0c;理解机器学习算法和自然语言处理如何在后台工作。然…

鸿蒙ArkTs开发,仿抖音个人中心header 下拉放大

如果是iOS 或者android 上实现&#xff0c;可以用Scollview 的contentOffset 来实现&#xff0c;然而在鸿蒙ets中该如何实现&#xff1f;废话不多说开始撸代码 第一步、实现一个header // 创建header&#xff0c;准备一张背景图片BuilderHeaderBuilder(){Column() {Row() {Ima…

社交媒体数据恢复:爱聊

爱聊数据恢复方法 在爱聊的使用过程中&#xff0c;如果遇到数据丢失的情况&#xff0c;可以尝试以下几种方法来恢复数据。 1. 硬盘坏道检测与修复 如果问题是由于硬盘坏道导致的&#xff0c;可以按照以下步骤进行操作&#xff1a; 找到需要修复的坏道磁盘&#xff1a;首先&…

js模块化:修改导入模块的内容,会有影响吗?

起因 element-ui的popper组件相关的层级&#xff0c;是使用popup-manager来统一管理的。 之前试图在自己的组件里导入并使用element-ui的popup-manager&#xff0c;但是层级老是和element-ui组件的层级冲突&#xff0c;看了下源码&#xff0c;竟意外发现&#xff0c;使用popu…