Close

sqlmap源码解析(一)

sqlmap源码解析(一)

打算写扫描器了 参考一下最经典的sqlmap来做
目录

主函数

在运行之前先运行了四个函数

dirtyPatches

修复了一个windows cmd下python的bug

checkEnvironment

检测了当前的运行环境

setPaths

将当前运行的环境设置为工作目录

banner

输出banner

cmdLineParser

然后通过这个来解析传入的参数
调用了一个optparse的库来解析参数

        parser.add_option_group(target)
        parser.add_option_group(request)
        parser.add_option_group(optimization)
        parser.add_option_group(injection)
        parser.add_option_group(detection)
        parser.add_option_group(techniques)
        parser.add_option_group(fingerprint)
        parser.add_option_group(enumeration)
        parser.add_option_group(brute)
        parser.add_option_group(udf)
        parser.add_option_group(filesystem)
        parser.add_option_group(takeover)
        parser.add_option_group(windows)
        parser.add_option_group(general)
        parser.add_option_group(miscellaneous)

总共分为这么多类
cmdLineOptions.update(cmdLineParser().__dict__)这样传入的

然后进入initOptions(cmdLineOptions)
cmdLineOptions就是一个字典参数包含着输入的一些东西输出看看
python sqlmap.py -u "www.bilibili.com?id=1" --dbs --random-agent --level 5
cmdLineOptions

{'fileDest': None, 'code': None, 'getUsers': None, 'getPasswordHashes': None, 'excludeSysDbs': None, 'ignoreTimeouts': None, 'skip': None, 'prefix': None, 'osShell': None, 'googlePage': None, 'randomAgent': True, 'testSkip': None, 'authType': None, 'safeUrl': None, 'requestFile': None, 'predictOutput': None, 'wizard': None, 'stopFail': None, 'forms': None, 'uChar': None, 'secondReq': None, 'taskid': None, 'pivotColumn': None, 'preprocess': None, 'dropSetCookie': None, 'dbmsCred': None, 'getAll': None, 'risk': None, 'sqlFile': None, 'rParam': None, 'getCurrentUser': None, 'notString': None, 'getRoles': None, 'getPrivileges': None, 'testParameter': None, 'tbl': None, 'showVersion': None, 'trafficFile': None, 'forceDbms': None, 'osBof': None, 'osSmb': None, 'level': 5, 'dnsDomain': None, 'outputDir': None, 'skipWaf': None, 'timeout': None, 'firstChar': None, 'torPort': None, 'advancedHelp': None, 'charset': None, 'getComments': None, 'binaryFields': None, 'checkTor': None, 'commonTables': None, 'direct': None, 'tmpPath': None, 'titles': None, 'getSchema': None, 'timeSec': None, 'paramDel': None, 'safeReqFile': None, 'regKey': None, 'limitStart': None, 'regRead': None, 'crawlExclude': None, 'flushSession': None, 'loadCookies': None, 'csvDel': None, 'offline': None, 'method': None, 'tmpDir': None, 'fileWrite': None, 'disablePrecon': None, 'murphyRate': None, 'invalidLogical': None, 'getCurrentDb': None, 'hexConvert': None, 'proxyFile': None, 'mobile': None, 'answers': None, 'host': None, 'dependencies': None, 'cookie': None, 'proxy': None, 'updateAll': None, 'regexp': None, 'repair': None, 'optimize': None, 'limitStop': None, 'search': None, 'shLib': None, 'uFrom': None, 'noCast': None, 'testFilter': None, 'ignoreCode': None, 'eta': None, 'csrfToken': None, 'threads': None, 'logFile': None, 'os': None, 'col': None, 'user': None, 'proxyCred': None, 'verbose': None, 'crawlDepth': None, 'encoding': None, 'privEsc': None, 'forceDns': None, 'paramExclude': None, 'base64Parameter': None, 'header': None, 'api': None, 'hashFile': None, 'invalidBignum': None, 'regType': None, 'getDbs': True, 'freshQueries': None, 'uCols': None, 'smokeTest': None, 'regData': None, 'udfInject': None, 'invalidString': None, 'tor': None, 'forceSSL': None, 'beep': None, 'disableColoring': None, 'configFile': None, 'delay': None, 'scope': None, 'authFile': None, 'isDba': None, 'torType': None, 'regVal': None, 'dummy': None, 'checkInternet': None, 'mnemonics': None, 'listTampers': None, 'skipUrlEncode': None, 'referer': None, 'liveTest': None, 'retries': None, 'extensiveFp': None, 'dumpTable': None, 'getColumns': None, 'batch': None, 'purge': None, 'headers': None, 'authCred': None, 'osCmd': None, 'suffix': None, 'smart': None, 'regDel': None, 'chunked': None, 'sitemapUrl': None, 'identifyWaf': None, 'msfPath': None, 'dumpAll': None, 'fileRead': None, 'getHostname': None, 'sessionFile': None, 'safePost': None, 'noEscape': None, 'getTables': None, 'safeFreq': None, 'agent': None, 'sqlmapShell': None, 'webRoot': None, 'exclude': None, 'lastChar': None, 'string': None, 'dbms': None, 'forceThreads': None, 'dumpWhere': None, 'tamper': None, 'ignoreRedirects': None, 'hpp': None, 'runCase': None, 'osPwn': None, 'evalCode': None, 'cleanup': None, 'csrfUrl': None, 'secondUrl': None, 'getBanner': None, 'profile': None, 'disableStats': None, 'bulkFile': None, 'db': None, 'dumpFormat': None, 'alert': None, 'harFile': None, 'nullConnection': None, 'forcePivoting': None, 'skipStatic': None, 'parseErrors': None, 'getCount': None, 'data': None, 'regAdd': None, 'ignoreProxy': None, 'database': None, 'url': u'www.bilibili.com?id=1', 'googleDork': None, 'saveConfig': None, 'sqlQuery': None, 'sqlShell': None, 'vulnTest': None, 'tech': None, 'textOnly': None, 'cookieDel': None, 'commonColumns': None, 'keepAlive': None}

传入initOptions

def initOptions(inputOptions=AttribDict(), overrideOptions=False):
    _setConfAttributes()
    _setKnowledgeBaseAttributes()
    _mergeOptions(inputOptions, overrideOptions)

_setConfAttributes

是用来给conf做初始化的
之后所有的参数都是存在conf里面的

_setKnowledgeBaseAttributes

给kb做初始化
KnowledgeBase

_mergeOptions

用作者给的注释来解释
Merge command line options with configuration file and default options.
合并参数到conf里面

进入初始化函数init()

Set attributes into both configuration and knowledge base singletons
based upon command line and configuration file options.

-w545
特别长
慢慢看

_useWizardInterface

Presents simple wizard interface for beginner users
隐藏模块
给新入门用的-w207
将conf.wizard为True就好了
-w664
在参数里面找到了所以只需要
sqlmap –wizard就可以开启了

_setRequestFromFile

-w523
可以看到他是解析-r参数获得的数据
parseRequestFile来解析请求包

parseRequestFile

Parses WebScarab and Burp logs and adds results to the target URL list
通过readCachedFileContent函数来查询缓存
-w651
_parseBurpLog
这个是解析从burpsuite中获得的txt文件
_parseWebScarabLog
这个是捷信从webscarab中获得的文件

_parseBurpLog

平常burp用的多久看这个方法了

这一段解析了所有的请求头

\A是开头必须为string \S就可以为任何字符串后面带着:就可以
提取出所有的header

match = re.search(r"\A(%s) (.+) HTTP/[\d.]+\Z" % "|".join(getPublicTypeMembers(HTTPMETHOD, True)), line) if not method else None
if len(line.strip()) == 0 and method and method != HTTPMETHOD.GET and data is None:
    data = ""
    params = True
elif match:
    method = match.group(1)
    url = match.group(2)
if any(_ in line for _ in ('?', '=', kb.customInjectionMark)):
    params = True
    getPostReq = True

通过正则来匹配出method和url

if not(conf.scope and not re.search(conf.scope, url, re.I)):
    yield (url, conf.method or method, data, cookie, tuple(headers))

返回的结果
将所有的结果放入
kb.secondReq

后记

之前也写了一点扫描器的部分参考了
https://github.com/Xyntax/POC-T
https://github.com/w-digital-scanner/
https://github.com/knownsec/pocsuite3

看了很多发现都是基于POC-T
然后POC-T又是基于sqlmap就看sqlmap了=。=

Leave a Reply

Your email address will not be published. Required fields are marked *