Python:SQLMap源码精读—start函数

源代码

  1 def start():
  2     """
  3     This function calls a function that performs checks on both URL
  4     stability and all GET, POST, Cookie and User-Agent parameters to
  5     check if they are dynamic and SQL injection affected
  6     """
  7     if not conf.start:
  8         return False
  9
 10     if conf.direct:
 11         initTargetEnv()
 12         setupTargetEnv()
 13         action()
 14         return True
 15
 16     if conf.url and not conf.forms:
 17         kb.targetUrls.add(( conf.url, conf.method, conf.data, conf.cookie ))
 18
 19     if conf.configFile and not kb.targetUrls:
 20         errMsg  = "you did not edit the configuration file properly, set "
 21         errMsg += "the target url, list of targets or google dork"
 22         logger.error(errMsg)
 23         return False
 24
 25     if kb.targetUrls and len(kb.targetUrls) > 1:
 26         infoMsg = "sqlmap got a total of %d targets" % len(kb.targetUrls)
 27         logger.info(infoMsg)
 28
 29     hostCount             = 0
 30     cookieStr             = ""
 31     setCookieAsInjectable = True
 32
 33     for targetUrl, targetMethod, targetData, targetCookie in kb.targetUrls:
 34         try:
 35             conf.url    = targetUrl
 36             conf.method = targetMethod
 37             conf.data   = targetData
 38             conf.cookie = targetCookie
 39             initTargetEnv()
 40             parseTargetUrl()
 41
 42             testSqlInj = False
 43             if PLACE.GET in conf.parameters:
 44                 for parameter in re.findall(r"([^=]+)=[^&]+&?", conf.parameters[PLACE.GET]):
 45                     paramKey = (conf.hostname, conf.path, PLACE.GET, parameter)
 46                     if paramKey not in kb.testedParams:
 47                         testSqlInj = True
 48                         break
 49             else:
 50                 paramKey = (conf.hostname, conf.path, None, None)
 51                 if paramKey not in kb.testedParams:
 52                     testSqlInj = True
 53
 54             testSqlInj &= (conf.hostname, conf.path, None, None) not in kb.testedParams
 55
 56             if not testSqlInj:
 57                 infoMsg = "skipping ‘%s‘" % targetUrl
 58                 logger.info(infoMsg)
 59                 continue
 60
 61             if conf.multipleTargets:
 62                 hostCount += 1
 63                 if conf.forms:
 64                     message = "[#%d] form:\n%s %s" % (hostCount, conf.method or HTTPMETHOD.GET, targetUrl)
 65                 else:
 66                     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 "")
 67
 68                 if conf.cookie:
 69                     message += "\nCookie: %s" % conf.cookie
 70
 71                 if conf.data:
 72                     message += "\nPOST data: %s" % urlencode(conf.data) if conf.data else ""
 73
 74                 if conf.forms:
 75                     if conf.method == HTTPMETHOD.GET and targetUrl.find("?") == -1:
 76                         continue
 77
 78                     message += "\ndo you want to test this form? [Y/n/q] "
 79                     test = readInput(message, default="Y")
 80
 81                     if not test or test[0] in ("y", "Y"):
 82                         if conf.method == HTTPMETHOD.POST:
 83                             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 "")
 84                             conf.data = readInput(message, default=conf.data)
 85                             if extractRegexResult(EMPTY_FORM_FIELDS_REGEX, conf.data):
 86                                 message = "do you want to fill blank fields with random values? [Y/n] "
 87                                 test = readInput(message, default="Y")
 88                                 if not test or test[0] in ("y", "Y"):
 89                                     while extractRegexResult(EMPTY_FORM_FIELDS_REGEX, conf.data):
 90                                         item = extractRegexResult(EMPTY_FORM_FIELDS_REGEX, conf.data)
 91                                         if item[-1] == ‘&‘:
 92                                             conf.data = conf.data.replace(item, "%s%s&" % (item[:-1], randomStr()))
 93                                         else:
 94                                             conf.data = conf.data.replace(item, "%s%s" % (item, randomStr()))
 95                             conf.data = urldecode(conf.data)
 96
 97                         elif conf.method == HTTPMETHOD.GET:
 98                             if conf.url.find("?") > -1:
 99                                 firstPart = conf.url[:conf.url.find("?")]
100                                 secondPart = conf.url[conf.url.find("?")+1:]
101                                 message = "Edit GET data [default: %s]: " % secondPart
102                                 test = readInput(message, default=secondPart)
103                                 conf.url = "%s?%s" % (firstPart, test)
104
105                     elif test[0] in ("n", "N"):
106                         continue
107                     elif test[0] in ("q", "Q"):
108                         break
109
110                 elif conf.realTest:
111                     logger.info(message)
112                 else:
113                     message += "\ndo you want to test this url? [Y/n/q]"
114                     test = readInput(message, default="Y")
115
116                     if not test or test[0] in ("y", "Y"):
117                         pass
118                     elif test[0] in ("n", "N"):
119                         continue
120                     elif test[0] in ("q", "Q"):
121                         break
122
123                     logMsg = "testing url %s" % targetUrl
124                     logger.info(logMsg)
125
126             setupTargetEnv()
127             if not checkConnection(suppressOutput = conf.forms) or not checkString() or not checkRegexp():
128                 continue
129
130             if conf.nullConnection:
131                 checkNullConnection()
132
133             if not conf.dropSetCookie and conf.cj:
134                 for _, cookie in enumerate(conf.cj):
135                     cookie = getUnicode(cookie)
136                     index  = cookie.index(" for ")
137
138                     cookieStr += "%s;" % cookie[8:index]
139
140                 if cookieStr:
141                     cookieStr = cookieStr[:-1]
142
143                     if PLACE.COOKIE in conf.parameters:
144                         message  = "you provided an HTTP Cookie header value. "
145                         message += "The target url provided its own Cookie within "
146                         message += "the HTTP Set-Cookie header. Do you want to "
147                         message += "continue using the HTTP Cookie values that "
148                         message += "you provided? [Y/n] "
149                         test = readInput(message, default="Y")
150
151                         if not test or test[0] in ("y", "Y"):
152                             setCookieAsInjectable = False
153
154                     if setCookieAsInjectable:
155                         conf.httpHeaders.append(("Cookie", cookieStr))
156                         conf.parameters[PLACE.COOKIE] = cookieStr
157                         __paramDict = paramToDict(PLACE.COOKIE, cookieStr)
158
159                         if __paramDict:
160                             conf.paramDict[PLACE.COOKIE] = __paramDict
161                             # TODO: consider the following line in __setRequestParams()
162                             # __testableParameters = True
163
164             if (len(kb.injections) == 0 or (len(kb.injections) == 1 and kb.injections[0].place is None)) 165                 and (kb.injection.place is None or kb.injection.parameter is None):
166                 if not conf.string and not conf.regexp:
167                     # NOTE: this is not needed anymore, leaving only to display
168                     # a warning message to the user in case the page is not stable
169                     checkStability()
170
171                 # Do a little prioritization reorder of a testable parameter list
172                 parameters = conf.parameters.keys()
173
174                 # Order of testing list (last to first)
175                 orderList = (PLACE.URI, PLACE.GET, PLACE.POST)
176
177                 for place in orderList:
178                     if place in parameters:
179                         parameters.remove(place)
180                         parameters.insert(0, place)
181
182                 proceed = True
183
184                 for place in parameters:
185                     # Test User-Agent and Referer headers only if
186                     # --level >= 3
187                     skip = (place == PLACE.UA and conf.level < 3)
188                     skip |= (place == PLACE.REFERER and conf.level < 3)
189
190                     # Test Cookie header only if --level >= 2
191                     skip |= (place == PLACE.COOKIE and conf.level < 2)
192
193                     skip &= not (place == PLACE.UA and intersect(USER_AGENT_ALIASES, conf.testParameter))
194                     skip &= not (place == PLACE.REFERER and intersect(REFERER_ALIASES, conf.testParameter))
195
196                     if skip:
197                         continue
198
199                     if not conf.paramDict.has_key(place):
200                         continue
201
202                     paramDict = conf.paramDict[place]
203                     for parameter, value in paramDict.items():
204                         if not proceed:
205                             break
206
207                         testSqlInj = True
208
209                         paramKey = (conf.hostname, conf.path, place, parameter)
210
211                         if paramKey in kb.testedParams:
212                             testSqlInj = False
213
214                             infoMsg = "skipping previously processed %s parameter ‘%s‘" % (place, parameter)
215                             logger.info(infoMsg)
216
217                         # Avoid dinamicity test if the user provided the
218                         # parameter manually
219                         elif parameter in conf.testParameter or conf.realTest:
220                             pass
221
222                         elif not checkDynParam(place, parameter, value):
223                             warnMsg = "%s parameter ‘%s‘ is not dynamic" % (place, parameter)
224                             logger.warn(warnMsg)
225
226                         else:
227                             logMsg = "%s parameter ‘%s‘ is dynamic" % (place, parameter)
228                             logger.info(logMsg)
229
230                         kb.testedParams.add(paramKey)
231
232                         if testSqlInj:
233                             check = heuristicCheckSqlInjection(place, parameter)
234                             if not check and conf.realTest and235                               not simpletonCheckSqlInjection(place, parameter, value):
236                                 continue
237
238                             logMsg = "testing sql injection on %s " % place
239                             logMsg += "parameter ‘%s‘" % parameter
240                             logger.info(logMsg)
241
242                             injection = checkSqlInjection(place, parameter, value)
243                             proceed = not kb.endDetection
244
245                             if injection is not None and injection.place is not None:
246                                 kb.injections.append(injection)
247
248                                 # In case when user wants to end detection phase (Ctrl+C)
249                                 if not proceed:
250                                     break
251
252                                 msg = "%s parameter ‘%s‘ " % (injection.place, injection.parameter)
253                                 msg += "is vulnerable. Do you want to keep testing the others? [y/N] "
254                                 test = readInput(msg, default="N")
255
256                                 if test[0] in ("n", "N"):
257                                     proceed = False
258                                     paramKey = (conf.hostname, conf.path, None, None)
259                                     kb.testedParams.add(paramKey)
260                             else:
261                                 warnMsg = "%s parameter ‘%s‘ is not " % (place, parameter)
262                                 warnMsg += "injectable"
263                                 logger.warn(warnMsg)
264
265             if len(kb.injections) == 0 or (len(kb.injections) == 1 and kb.injections[0].place is None):
266                 if not conf.realTest:
267                     errMsg = "all parameters are not injectable, try to "
268                     errMsg += "increase --level/--risk values to perform "
269                     errMsg += "more tests."
270
271                     if isinstance(conf.tech, list) and len(conf.tech) > 0:
272                         errMsg += " Rerun without providing the --technique switch."
273
274                     if not conf.textOnly and kb.originalPage:
275                         percent = (100.0 * len(getFilteredPageContent(kb.originalPage)) / len(kb.originalPage))
276                         errMsg += " Give it a go with the --text-only switch "
277                         errMsg += "if the target page has a low percentage of "
278                         errMsg += "textual content (~%.2f%% of " % percent
279                         errMsg += "page content is text)"
280
281                     raise sqlmapNotVulnerableException, errMsg
282                 else:
283                     errMsg = "it seems that all parameters are not injectable"
284                     raise sqlmapNotVulnerableException, errMsg
285             else:
286                 # Flush the flag
287                 kb.testMode = False
288
289                 __saveToSessionFile()
290                 __showInjections()
291                 __selectInjection()
292
293             if kb.injection.place is not None and kb.injection.parameter is not None:
294                 if kb.testQueryCount == 0 and conf.realTest:
295                     condition = False
296                 elif conf.multipleTargets:
297                     message = "do you want to exploit this SQL injection? [Y/n] "
298                     exploit = readInput(message, default="Y")
299
300                     condition = not exploit or exploit[0] in ("y", "Y")
301                 else:
302                     condition = True
303                 if condition:
304                     action()
305
306         except KeyboardInterrupt:
307             if conf.multipleTargets:
308                 warnMsg = "user aborted in multiple target mode"
309                 logger.warn(warnMsg)
310
311                 message = "do you want to skip to the next target in list? [Y/n/q]"
312                 test = readInput(message, default="Y")
313
314                 if not test or test[0] in ("y", "Y"):
315                     pass
316                 elif test[0] in ("n", "N"):
317                     return False
318                 elif test[0] in ("q", "Q"):
319                     raise sqlmapUserQuitException
320             else:
321                 raise
322
323         except sqlmapUserQuitException:
324             raise
325
326         except sqlmapSilentQuitException:
327             raise
328
329         except exceptionsTuple, e:
330             e = getUnicode(e)
331
332             if conf.multipleTargets:
333                 e += ", skipping to the next %s" % ("form" if conf.forms else "url")
334                 logger.error(e)
335             else:
336                 logger.critical(e)
337                 return False
338
339         finally:
340             showHttpErrorCodes()
341
342     if conf.loggedToOut and not conf.multipleTargets:
343         logger.info("Fetched data logged to text files under ‘%s‘" % conf.outputPath)
344
345     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://www.cnblogs.com/hongfei/p/sqlmap-start.html

Python:SQLMap源码精读—start函数,布布扣,bubuko.com

时间: 2024-08-07 00:05:19

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

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

基于时间的盲注(time-based blind) 测试应用是否存在SQL注入漏洞时,经常发现某一潜在的漏洞难以确认.这可能源于多种原因,但主要是因为Web应用未显示任何错误,因而无法检索任何数据. 对于这种情况,要想识别漏洞,向数据库注入时间延迟并检查服务器响应是否也已经延迟会很有帮助.时间延迟是一种很强大的技术,Web服务器虽然可以隐藏错误或数据,但必须等待数据库返回结果,因此可用它来确认是否存在SQL注入.该技术尤其适合盲注. 源码解释 代码位置:在checkSqlInjection函数中

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

目标网址 http://127.0.0.1/shentou/sqli-labs-master/Less-5/?id=1 Payload的生成 1 <test> 2 <title>MySQL >= 5.0 AND error-based - WHERE or HAVING clause</title> 3 <stype>2</stype> 4 <level>1</level> 5 <risk>0</r

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=&quo

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

SQLmap是现在搞web人手一个的注入神器,不仅包含了主流数据库的SQL注入检测,而且包含提权以及后渗透模块.基于python2.x开发而成,使用方便.所以研究web安全少不了分析源码,学习代码的同时,也可以学习先进的漏洞检测技术.多的不多说,咱们来分析一下源码. 使用的工具如下: IDE: sublime text SQLmap源码:https://github.com/sqlmapproject/sqlmap 当前分析版本: 1.1.2.5 0x00 从入口文件开始 我们在拿到源代码以后,

sql 注入神器sqlmap 源码分析之调试sqlmap

相信大家平时 用sqlmap 命令,比如 python sqlmap.py -u"https://team.oschina.net/action/team/create" --data="name=onlyGuest&ident=onlyGuest&sident=onlyGuest&temp=1431349990862" --dbs --dbms=mysql --cookie="JmHE4Nja6ZqH8Vw0cSxY%2FW4LT

《python解释器源码剖析》第17章--python的内存管理与垃圾回收

17.0 序 内存管理,对于python这样的动态语言是至关重要的一部分,它在很大程度上决定了python的执行效率,因为在python的运行中会创建和销毁大量的对象,这些都设计内存的管理.同理python还提供了了内存的垃圾回收(GC,garbage collection),将开发者从繁琐的手动维护内存的工作中解放出来.这一章我们就来分析python的GC是如何实现的. 17.1 内存管理架构 在python中内存管理机制是分层次的,我们可以看成有四层,0 1 2 3.在最底层,也就是第0层是

ThinkPHP源码阅读2-----C函数配置文件详解

ThinkPHP的配置非常灵活,可自定义加载.大概看了一下,一共有这几个地方会加载配置文件,方便以后的读取 /** * 获取和设置配置参数 支持批量定义 * * @param string|array $name * 配置变量 * @param mixed $value * 配置值 * @return mixed */ function C($name = null, $value = null) { static $_config = array (); // 无参数时获取所有 if (emp

一个python游戏源码

#finalPyPong.py import pygame,sys class MyBallClass(pygame.sprite.Sprite): def __init__(self,image_file,speed,location=[0,0]): pygame.sprite.Sprite.__init__(self) self.image = pygame.image.load(image_file) self.rect = self.image.get_rect() self.rect.

jQuery源码分析-each函数

本文部分截取自且行且思 jQuery.each方法用于遍历一个数组或对象,并对当前遍历的元素进行处理,在jQuery使用的频率非常大,下面就这个函数做了详细讲解: 复制代码代码 /*! * jQuery源码分析-each函数 * jQuery版本:1.4.2 * * ---------------------------------------------------------- * 函数介绍 * * each函数通过jQuery.extend函数附加到jQuery对象中: * jQuery.