源代码

 def start():
"""
This function calls a function that performs checks on both URL
stability and all GET, POST, Cookie and User-Agent parameters to
check if they are dynamic and SQL injection affected
"""
if not conf.start:
return False if conf.direct:
initTargetEnv()
setupTargetEnv()
action()
return True if conf.url and not conf.forms:
kb.targetUrls.add(( conf.url, conf.method, conf.data, conf.cookie )) if conf.configFile and not kb.targetUrls:
errMsg = "you did not edit the configuration file properly, set "
errMsg += "the target url, list of targets or google dork"
logger.error(errMsg)
return False if kb.targetUrls and len(kb.targetUrls) > 1:
infoMsg = "sqlmap got a total of %d targets" % len(kb.targetUrls)
logger.info(infoMsg) hostCount = 0
cookieStr = ""
setCookieAsInjectable = True for targetUrl, targetMethod, targetData, targetCookie in kb.targetUrls:
try:
conf.url = targetUrl
conf.method = targetMethod
conf.data = targetData
conf.cookie = targetCookie
initTargetEnv()
parseTargetUrl() testSqlInj = False
if PLACE.GET in conf.parameters:
for parameter in re.findall(r"([^=]+)=[^&]+&?", conf.parameters[PLACE.GET]):
paramKey = (conf.hostname, conf.path, PLACE.GET, parameter)
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 testSqlInj &= (conf.hostname, conf.path, None, None) not in kb.testedParams if not testSqlInj:
infoMsg = "skipping '%s'" % targetUrl
logger.info(infoMsg)
continue if conf.multipleTargets:
hostCount += 1
if conf.forms:
message = "[#%d] form:\n%s %s" % (hostCount, conf.method or HTTPMETHOD.GET, targetUrl)
else:
message = "url %d:\n%s %s%s" % (hostCount, conf.method or HTTPMETHOD.GET, targetUrl, " (PageRank: %s)" % get_pagerank(targetUrl) if conf.googleDork and conf.pageRank else "") if conf.cookie:
message += "\nCookie: %s" % conf.cookie if conf.data:
message += "\nPOST data: %s" % urlencode(conf.data) if conf.data else "" if conf.forms:
if conf.method == HTTPMETHOD.GET and targetUrl.find("?") == -1:
continue message += "\ndo you want to test this form? [Y/n/q] "
test = readInput(message, default="Y") if not test or test[0] in ("y", "Y"):
if conf.method == HTTPMETHOD.POST:
message = "Edit POST data [default: %s]%s: " % (urlencode(conf.data) if conf.data else "None", " (Warning: blank fields detected)" if conf.data and extractRegexResult(EMPTY_FORM_FIELDS_REGEX, conf.data) else "")
conf.data = readInput(message, default=conf.data)
if extractRegexResult(EMPTY_FORM_FIELDS_REGEX, conf.data):
message = "do you want to fill blank fields with random values? [Y/n] "
test = readInput(message, default="Y")
if not test or test[0] in ("y", "Y"):
while extractRegexResult(EMPTY_FORM_FIELDS_REGEX, conf.data):
item = extractRegexResult(EMPTY_FORM_FIELDS_REGEX, conf.data)
if item[-1] == '&':
conf.data = conf.data.replace(item, "%s%s&" % (item[:-1], randomStr()))
else:
conf.data = conf.data.replace(item, "%s%s" % (item, randomStr()))
conf.data = urldecode(conf.data) elif conf.method == HTTPMETHOD.GET:
if conf.url.find("?") > -1:
firstPart = conf.url[:conf.url.find("?")]
secondPart = conf.url[conf.url.find("?")+1:]
message = "Edit GET data [default: %s]: " % secondPart
test = readInput(message, default=secondPart)
conf.url = "%s?%s" % (firstPart, test) elif test[0] in ("n", "N"):
continue
elif test[0] in ("q", "Q"):
break elif conf.realTest:
logger.info(message)
else:
message += "\ndo you want to test this url? [Y/n/q]"
test = readInput(message, default="Y") if not test or test[0] in ("y", "Y"):
pass
elif test[0] in ("n", "N"):
continue
elif test[0] in ("q", "Q"):
break logMsg = "testing url %s" % targetUrl
logger.info(logMsg) setupTargetEnv()
if not checkConnection(suppressOutput = conf.forms) or not checkString() or not checkRegexp():
continue if conf.nullConnection:
checkNullConnection() if not conf.dropSetCookie and conf.cj:
for _, cookie in enumerate(conf.cj):
cookie = getUnicode(cookie)
index = cookie.index(" for ") cookieStr += "%s;" % cookie[8:index] if cookieStr:
cookieStr = cookieStr[:-1] if PLACE.COOKIE in conf.parameters:
message = "you provided an HTTP Cookie header value. "
message += "The target url provided its own Cookie within "
message += "the HTTP Set-Cookie header. Do you want to "
message += "continue using the HTTP Cookie values that "
message += "you provided? [Y/n] "
test = readInput(message, default="Y") if not test or test[0] in ("y", "Y"):
setCookieAsInjectable = False if setCookieAsInjectable:
conf.httpHeaders.append(("Cookie", cookieStr))
conf.parameters[PLACE.COOKIE] = cookieStr
__paramDict = paramToDict(PLACE.COOKIE, cookieStr) if __paramDict:
conf.paramDict[PLACE.COOKIE] = __paramDict
# TODO: consider the following line in __setRequestParams()
# __testableParameters = True if (len(kb.injections) == 0 or (len(kb.injections) == 1 and kb.injections[0].place is None)) \
and (kb.injection.place is None or kb.injection.parameter is None):
if not conf.string and not conf.regexp:
# NOTE: this is not needed anymore, leaving only to display
# a warning message to the user in case the page is not stable
checkStability() # Do a little prioritization reorder of a testable parameter list
parameters = conf.parameters.keys() # Order of testing list (last to first)
orderList = (PLACE.URI, PLACE.GET, PLACE.POST) for place in orderList:
if place in parameters:
parameters.remove(place)
parameters.insert(0, place) proceed = True for place in parameters:
# Test User-Agent and Referer headers only if
# --level >= 3
skip = (place == PLACE.UA and conf.level < 3)
skip |= (place == PLACE.REFERER and conf.level < 3) # Test Cookie header only if --level >= 2
skip |= (place == PLACE.COOKIE and conf.level < 2) skip &= not (place == PLACE.UA and intersect(USER_AGENT_ALIASES, conf.testParameter))
skip &= not (place == PLACE.REFERER and intersect(REFERER_ALIASES, conf.testParameter)) if skip:
continue if not conf.paramDict.has_key(place):
continue paramDict = conf.paramDict[place]
for parameter, value in paramDict.items():
if not proceed:
break testSqlInj = True paramKey = (conf.hostname, conf.path, place, parameter) if paramKey in kb.testedParams:
testSqlInj = False infoMsg = "skipping previously processed %s parameter '%s'" % (place, parameter)
logger.info(infoMsg) # Avoid dinamicity test if the user provided the
# parameter manually
elif parameter in conf.testParameter or conf.realTest:
pass elif not checkDynParam(place, parameter, value):
warnMsg = "%s parameter '%s' is not dynamic" % (place, parameter)
logger.warn(warnMsg) else:
logMsg = "%s parameter '%s' is dynamic" % (place, parameter)
logger.info(logMsg) kb.testedParams.add(paramKey) if testSqlInj:
check = heuristicCheckSqlInjection(place, parameter)
if not check and conf.realTest and\
not simpletonCheckSqlInjection(place, parameter, value):
continue logMsg = "testing sql injection on %s " % place
logMsg += "parameter '%s'" % parameter
logger.info(logMsg) injection = checkSqlInjection(place, parameter, value)
proceed = not kb.endDetection if injection is not None and injection.place is not None:
kb.injections.append(injection) # In case when user wants to end detection phase (Ctrl+C)
if not proceed:
break msg = "%s parameter '%s' " % (injection.place, injection.parameter)
msg += "is vulnerable. Do you want to keep testing the others? [y/N] "
test = readInput(msg, default="N") if test[0] in ("n", "N"):
proceed = False
paramKey = (conf.hostname, conf.path, None, None)
kb.testedParams.add(paramKey)
else:
warnMsg = "%s parameter '%s' is not " % (place, parameter)
warnMsg += "injectable"
logger.warn(warnMsg) if len(kb.injections) == 0 or (len(kb.injections) == 1 and kb.injections[0].place is None):
if not conf.realTest:
errMsg = "all parameters are not injectable, try to "
errMsg += "increase --level/--risk values to perform "
errMsg += "more tests." if isinstance(conf.tech, list) and len(conf.tech) > 0:
errMsg += " Rerun without providing the --technique switch." if not conf.textOnly and kb.originalPage:
percent = (100.0 * len(getFilteredPageContent(kb.originalPage)) / len(kb.originalPage))
errMsg += " Give it a go with the --text-only switch "
errMsg += "if the target page has a low percentage of "
errMsg += "textual content (~%.2f%% of " % percent
errMsg += "page content is text)" raise sqlmapNotVulnerableException, errMsg
else:
errMsg = "it seems that all parameters are not injectable"
raise sqlmapNotVulnerableException, errMsg
else:
# Flush the flag
kb.testMode = False __saveToSessionFile()
__showInjections()
__selectInjection() if kb.injection.place is not None and kb.injection.parameter is not None:
if kb.testQueryCount == 0 and conf.realTest:
condition = False
elif conf.multipleTargets:
message = "do you want to exploit this SQL injection? [Y/n] "
exploit = readInput(message, default="Y") condition = not exploit or exploit[0] in ("y", "Y")
else:
condition = True
if condition:
action() except KeyboardInterrupt:
if conf.multipleTargets:
warnMsg = "user aborted in multiple target mode"
logger.warn(warnMsg) message = "do you want to skip to the next target in list? [Y/n/q]"
test = readInput(message, default="Y") if not test or test[0] in ("y", "Y"):
pass
elif test[0] in ("n", "N"):
return False
elif test[0] in ("q", "Q"):
raise sqlmapUserQuitException
else:
raise except sqlmapUserQuitException:
raise except sqlmapSilentQuitException:
raise except exceptionsTuple, e:
e = getUnicode(e) if conf.multipleTargets:
e += ", skipping to the next %s" % ("form" if conf.forms else "url")
logger.error(e)
else:
logger.critical(e)
return False finally:
showHttpErrorCodes() if conf.loggedToOut and not conf.multipleTargets:
logger.info("Fetched data logged to text files under '%s'" % conf.outputPath) return True

代码解释

10-14行

if conf.direct:
initTargetEnv()
setupTargetEnv()
action()
return True

conf.direct是通过命令行参数:"-d"指定的。

通过参数"-d"指定要连接的数据库
eg:-d "mysql:123123//root:@127.0.0.1:3306/security"

39-40行

initTargetEnv()
parseTargetUrl()

initTargetEnv()函数主要就是完成全局变量conf和kb的初始化工作

parseTargetUrl()函数主要完成针对目标网址的解析工作,如获取协议名、路径、端口、请求参数等信息

43-52行

if PLACE.GET in conf.parameters:
for parameter in re.findall(r"([^=]+)=[^&]+&?", conf.parameters[PLACE.GET]):
paramKey = (conf.hostname, conf.path, PLACE.GET, parameter)
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

测试过的url参数信息会保存到kb.testedParams中(第230行和第259行),所以在进行test之前,会先判断当前的url是否已经test过

如果没test过的话,则testSqlInj = True,否则testSqlInj = False。

当testSqlInj = False的时候,就不会执行 injection = checkSqlInjection(place, parameter, value)这句代码了。

126行

setupTargetEnv()

该函数主要包含3个子功能:

1.创建保存目标执行结果的目录和文件
2.将get或post发送的数据解析成字典形式,并保存到conf.paramDict中
3.读取session文件(如果存在的话),并提起文件中的数据,保存到kb变量中

133-162行

如果在命令中有提供cookie的话,就会将攻城师指定的cookie加入到http请求头中,以便使用cookie访问。

164-263行

提取url中的参数信息,并将其传递给checkSqlInjection函数,checkSqlInjection函数的功能主要是检测给定的url参数,看其是否可注入,如果可注入的话,就将payload等相关信息返回(即checkSqlInjection函数的返回值),再将其append到kb.injections中。

304行

action()是很总要的一个函数,该函数主要根据攻城师的命令行参数选型,从而利用存在注入漏洞的url,以进一步获取攻城师要获取的数据。

比如:当前的数据库用户、枚举数据库的所有数据表等等

版权

作       者:曾是土木人

新浪微博:http://weibo.com/cstmr

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

Python:SQLMap源码精读—start函数的更多相关文章

  1. Python:Sqlmap源码精读之解析xml

    XML <?xml version="1.0" encoding="UTF-8"?> <root> <!-- MySQL --&g ...

  2. Python:SQLMap源码精读—基于时间的盲注(time-based blind)

    建议阅读 Time-Based Blind SQL Injection Attacks 基于时间的盲注(time-based blind) 测试应用是否存在SQL注入漏洞时,经常发现某一潜在的漏洞难以 ...

  3. Python:SQLMap源码精读—基于错误的盲注(error-based blind)

    目标网址 http://127.0.0.1/shentou/sqli-labs-master/Less-5/?id=1 Payload的生成 <test> <title>MyS ...

  4. SQLmap源码分析之框架初始化(一)

    SQLmap是现在搞web人手一个的注入神器,不仅包含了主流数据库的SQL注入检测,而且包含提权以及后渗透模块.基于python2.x开发而成,使用方便.所以研究web安全少不了分析源码,学习代码的同 ...

  5. SQLMAP源码分析(一)

    说起来,学习Python很大一部分原因是由于对WEB安全的兴趣以及对SQLMAP这款工具的好奇,曾经设想学完Python基础就读一读SQLMAP源码,然而懒病一犯,随之就大江东去.近来,又重新燃起了读 ...

  6. sqlmap源码分析(一)

    Sqlmap源码分析(一) 此次分析的sqlmap目标版本为1.6.1.2#dev 只对sqlmap的核心检测代码进行详细分析其他的一带而过 sqlmap.py文件结构 为了不让篇幅过长下面只写出了s ...

  7. 《python解释器源码剖析》第0章--python的架构与编译python

    本系列是以陈儒先生的<python源码剖析>为学习素材,所记录的学习内容.不同的是陈儒先生的<python源码剖析>所剖析的是python2.5,本系列对应的是python3. ...

  8. 性能测试分享: Jmeter的源码分析main函数参数

    性能测试分享: Jmeter的源码分析main函数参数   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大 ...

  9. 读zepto源码之工具函数

    读zepto源码之工具函数 Zepto 提供了丰富的工具函数,下面来一一解读. 源码版本 本文阅读的源码为 zepto1.2.0 $.extend $.extend 方法可以用来扩展目标对象的属性.目 ...

随机推荐

  1. mysql学习笔记--数据完整性

    一.数据完整性包括: 1. 域完整性 2. 实体完整性 3. 引用完整性 二.保证实体完整性 1. 主键约束 2. 唯一约束 3. 自动增长列 三.保证域完整性 1. 数据类型约束 2. 非空约束 3 ...

  2. python list中append()方法和extend()方法区别

    共同点 只能作用于list类型(不能作用于tuple等其他类型) 单参数限制(不支持多参数) 不同点 list.append(object) 向列表中添加一个对象object. 使用append的时候 ...

  3. 169. Majority Element (Array)

    Given an array of size n, find the majority element. The majority element is the element that appear ...

  4. Oracle修改表结构字段名和字段长度

    添加字段的语法:alter table tablename add (column datatype [default value][null/not null],….); 修改字段的语法:alter ...

  5. react项目请求数据的fetch的使用

    准备三个文件(封装请求函数),然后测试一下,能不能调用数据 第一个文件  request.js import 'whatwg-fetch'; /** * Parses the JSON returne ...

  6. swift 设置阴影和圆角

    1.正常view设置阴影 func setShadow(view:UIView,sColor:UIColor,offset:CGSize, opacity:Float,radius:CGFloat) ...

  7. LinkedList 源码实现

    闲暇之余,准备将Java 一些常用的数据结构进行重新的剖析,并记录博客比如LinkedList ,HashMap ,HashTable ,以及并发包所引入的集合,在博客中会陆续更新 start 哈哈, ...

  8. 写jsp文件时需要注意的一些小细节

    ①jsp文件的最开始的部分: <%@ page language="java" contentType="text/html; charset=UTF-8" ...

  9. Python开发——数据类型【集合】

    集合的定义 由一个或多个确定的元素所构成的整体 可变集合 s=set('hello') print(s) # {'e', 'l', 'o', 'h'} s=set(['alex','alex','Lu ...

  10. AutoCAD开发1---获取块属性

    Private Sub CommandButton1_Click() Dim pEntity As AcadObject Dim pBlock As AcadBlockReference Dim pP ...