源代码1defstart():2"""3This function calls a function that performs checks on both URL4stability and all GET, POST, Cookie and User-Agent parameters to5check if they are dynamic and SQL injection affected6"""7ifnotconf.start:8returnFalse910ifconf.direct:11initTargetEnv()12setupTargetEnv()13action()14returnTrue1516ifconf.urlandnotconf.forms:17kb.targetUrls.add(( conf.url, conf.method, conf.data, conf.cookie ))1819ifconf.configFileandnotkb.targetUrls:20errMsg ="you did not edit the configuration filePRoperly, set"21errMsg +="the target url, list of targets or google dork"22logger.error(errMsg)23returnFalse2425ifkb.targetUrlsandlen(kb.targetUrls) > 1:26infoMsg ="sqlmap got a total of %d targets"%len(kb.targetUrls)27logger.info(infoMsg)2829hostCount =030cookieStr =""31setCookieAsInjectable =True3233fortargetUrl, targetMethod, targetData, targetCookieinkb.targetUrls:34try:35conf.url =targetUrl36conf.method =targetMethod37conf.data =targetData38conf.cookie =targetCookie39initTargetEnv()40parseTargetUrl()4142testSqlInj =False43ifPLACE.GETinconf.parameters:44forparameterinre.findall(r"([^=]+)=[^&]+&?", conf.parameters[PLACE.GET]):45paramKey =(conf.hostname, conf.path, PLACE.GET, parameter)46ifparamKeynotinkb.testedParams:47testSqlInj =True48
break49else:50paramKey =(conf.hostname, conf.path, None, None)51ifparamKeynotinkb.testedParams:52testSqlInj =True5354testSqlInj &= (conf.hostname, conf.path, None, None)notinkb.testedParams5556ifnottestSqlInj:57infoMsg ="skipping '%s'"%targetUrl58logger.info(infoMsg)59continue6061ifconf.multipleTargets:62hostCount += 163ifconf.forms:64message ="[#%d] form:\n%s %s"% (hostCount, conf.methodorHTTPMETHOD.GET, targetUrl)65else:66message ="url %d:\n%s %s%s"% (hostCount, conf.methodorHTTPMETHOD.GET, targetUrl,"(PageRank: %s)"% get_pagerank(targetUrl)ifconf.googleDorkandconf.pageRankelse"")6768ifconf.cookie:69message +="\nCookie: %s"%conf.cookie7071ifconf.data:72message +="\nPOST data: %s"% urlencode(conf.data)ifconf.dataelse""7374ifconf.forms:75ifconf.method == HTTPMETHOD.GETandtargetUrl.find("?") == -1:76continue7778message +="\ndo you want to test this form? [Y/n/q]"79test = readInput(message, default="Y")8081ifnottestortest[0]in("y","Y"):82ifconf.method ==HTTPMETHOD.POST:83message ="Edit POST data [default: %s]%s:"% (urlencode(conf.data)ifconf.dataelse"None","(Warning: blank fields detected)"ifconf.dataandextractRegexResult(EMPTY_FORM_FIELDS_REGEX, conf.data)else"")84conf.data = readInput(message, default=conf.data)85ifextractRegexResult(EMPTY_FORM_FIELDS_REGEX, conf.data):86message ="do you want to fill blank fields with random values? [Y/n]"87test = readInput(message, default="Y")88ifnottestortest[0]in("y","Y"):89whileextractRegexResult(EMPTY_FORM_FIELDS_REGEX, conf.data):90item =extractRegexResult(EMPTY_FORM_FIELDS_REGEX, conf.data)91ifitem[-1] =='&':92conf.data = conf.data.replace(item,"%s%s&"% (item[:-1], randomStr()))93else:94conf.data = conf.data.replace(item,"%s%s"%(item, randomStr()))95conf.data =urldecode(conf.data)9697elifconf.method ==HTTPMETHOD.GET:98ifconf.url.find("?") > -1:99firstPart = conf.url[:conf.url.find("?")]100secondPart = conf.url[conf.url.find("?")+1:]101message ="Edit GET data [default: %s]:"%secondPart102test = readInput(message, default=secondPart)103conf.url ="%s?%s"%(firstPart, test)104105eliftest[0]in("n","N"):106continue107eliftest[0]in("q","Q"):108
break109110elifconf.realTest:111logger.info(message)112else:113message +="\ndo you want to test this url? [Y/n/q]"114test = readInput(message, default="Y")115116ifnottestortest[0]in("y","Y"):117pass118eliftest[0]in("n","N"):119continue120eliftest[0]in("q","Q"):121
break122123logMsg ="testing url %s"%targetUrl124logger.info(logMsg)125126setupTargetEnv()127ifnotcheckConnection(suppressOutput = conf.forms)ornotcheckString()ornotcheckRegexp():128continue129130ifconf.nullConnection:131checkNullConnection()132133ifnotconf.dropSetCookieandconf.cj:134for_, cookieinenumerate(conf.cj):135cookie =getUnicode(cookie)136index = cookie.index("for")137138cookieStr +="%s;"% cookie[8:index]139140ifcookieStr:141cookieStr = cookieStr[:-1]142143ifPLACE.COOKIEinconf.parameters:144message ="you provided an HTTP Cookie header value."145message +="The target url provided its own Cookie within"146message +="the HTTP Set-Cookie header. Do you want to"147message +="continue using the HTTP Cookie values that"148message +="you provided? [Y/n]"149test = readInput(message, default="Y")150151ifnottestortest[0]in("y","Y"):152setCookieAsInjectable =False153154ifsetCookieAsInjectable:155conf.httpHeaders.append(("Cookie", cookieStr))156conf.parameters[PLACE.COOKIE] =cookieStr157__paramDict=paramToDict(PLACE.COOKIE, cookieStr)158159if__paramDict:160conf.paramDict[PLACE.COOKIE] =__paramDict161#TODO: consider the following line in __setRequestParams()162#__testableParameters = True163164if(len(kb.injections) == 0or(len(kb.injections) == 1andkb.injections[0].placeisNone)) \165and(kb.injection.placeisNoneorkb.injection.parameterisNone):166ifnotconf.stringandnotconf.regexp:167#NOTE: this is not needed anymore, leaving only to display168#a warning message to the user in case the page is not stable169checkStability()170171#Do a little prioritization reorder of a testable parameter list172parameters =conf.parameters.keys()173174#Order of testing list (last to first)175orderList =(PLACE.URI, PLACE.GET, PLACE.POST)176177forplaceinorderList:178ifplaceinparameters:179parameters.remove(place)180parameters.insert(0, place)181182proceed =True183184forplaceinparameters:185#Test User-Agent and Referer headers only if186#--level >= 3187skip = (place == PLACE.UAandconf.level < 3)188skip |= (place == PLACE.REFERERandconf.level < 3)189190#Test Cookie header only if --level >= 2191skip |= (place == PLACE.COOKIEandconf.level < 2)192193skip &=not(place == PLACE.UAandintersect(USER_AGENT_ALIASES, conf.testParameter))194skip &=not(place == PLACE.REFERERandintersect(REFERER_ALIASES, conf.testParameter))195196ifskip:197continue198199ifnotconf.paramDict.has_key(place):200continue201202paramDict =conf.paramDict[place]203forparameter, valueinparamDict.items():204ifnotproceed:205
break206207testSqlInj =True208209paramKey =(conf.hostname, conf.path, place, parameter)210211ifparamKeyinkb.testedParams:212testSqlInj =False213214infoMsg ="skipping previously processed %s parameter '%s'"%(place, parameter)215logger.info(infoMsg)216217#Avoid dinamicity test if the user provided the218#parameter manually219elifparameterinconf.testParameterorconf.realTest:220pass221222elifnotcheckDynParam(place, parameter, value):223warnMsg ="%s parameter '%s' is not dynamic"%(place, parameter)224logger.warn(warnMsg)225226else:227logMsg ="%s parameter '%s' is dynamic"%(place, parameter)228logger.info(logMsg)229230kb.testedParams.add(paramKey)231232iftestSqlInj:233check =heuristicCheckSqlInjection(place, parameter)234ifnotcheckandconf.realTestand\235notsimpletonCheckSqlInjection(place, parameter, value):236continue237238logMsg ="testing sql injection on %s"%place239logMsg +="parameter '%s'"%parameter240logger.info(logMsg)241242injection =checkSqlInjection(place, parameter, value)243proceed =notkb.endDetection244245ifinjectionisnotNoneandinjection.placeisnotNone:246kb.injections.append(injection)247248#In case when user wants to end detection phase (Ctrl+C)249ifnotproceed:250
break251252msg ="%s parameter '%s'"%(injection.place, injection.parameter)253msg +="is vulnerable. Do you want to keep testing the others? [y/N]"254test = readInput(msg, default="N")255256iftest[0]in("n","N"):257proceed =False258paramKey =(conf.hostname, conf.path, None, None)259kb.testedParams.add(paramKey)260else:261warnMsg ="%s parameter '%s' is not"%(place, parameter)262warnMsg +="injectable"263logger.warn(warnMsg)264265iflen(kb.injections) == 0or(len(kb.injections) == 1andkb.injections[0].placeisNone):266ifnotconf.realTest:267errMsg ="all parameters are not injectable, try to"268errMsg +="increase --level/--risk values to perform"269errMsg +="more tests."270271ifisinstance(conf.tech, list)andlen(conf.tech) >0:272errMsg +="Rerun without providing the --technique switch."273274ifnotconf.textOnlyandkb.originalPage:275percent = (100.0 * len(getFilteredPageContent(kb.originalPage)) /len(kb.originalPage))276errMsg +="Give it a go with the --text-only switch"277errMsg +="if the target page has a low percentage of"278errMsg +="textual content (~%.2f%% of"%percent279errMsg +="page content is text)"280281raisesqlmapNotVulnerableException, errMsg282else:283errMsg ="it seems that all parameters are not injectable"284raisesqlmapNotVulnerableException, errMsg285else:286#Flush the flag287kb.testMode =False288289__saveTosessionFile()290__showInjections()291__selectInjection()292293ifkb.injection.placeisnotNoneandkb.injection.parameterisnotNone:294ifkb.testQueryCount == 0andconf.realTest:295condition =False296elifconf.multipleTargets:297message ="do you want to exploit this SQL injection? [Y/n]"298exploit = readInput(message, default="Y")299300condition =notexploitorexploit[0]in("y","Y")301else:302condition =True303ifcondition:304action()305306exceptKeyboardInterrupt:307ifconf.multipleTargets:308warnMsg ="user aborted in multiple target mode"309logger.warn(warnMsg)310311message ="do you want to skip to the next target in list? [Y/n/q]"312test = readInput(message, default="Y")313314ifnottestortest[0]in("y","Y"):315pass316eliftest[0]in("n","N"):317returnFalse318eliftest[0]in("q","Q"):319raisesqlmapUserQuitException320else:321raise322323exceptsqlmapUserQuitException:324raise325326exceptsqlmapSilentQuitException:327raise328329exceptexceptionsTuple, e:330e =getUnicode(e)331332ifconf.multipleTargets:333e +=", skipping to the next %s"% ("form"ifconf.formselse"url")334logger.error(e)335else:336logger.critical(e)337returnFalse338339finally:340showHttpErrorCodes()341342ifconf.loggedToOutandnotconf.multipleTargets:343logger.info("Fetched data logged to text files under '%s'"%conf.outputPath)344345returnTrue
代码解释10-14行ifconf.direct:
initTargetEnv()
setupTargetEnv()
action()returnTrue
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行ifPLACE.GETinconf.parameters:forparameterinre.findall(r"([^=]+)=[^&]+&?", conf.parameters[PLACE.GET]):
paramKey=(conf.hostname, conf.path, PLACE.GET, parameter)ifparamKeynotinkb.testedParams:
testSqlInj=True
breakelse:
paramKey=(conf.hostname, conf.path, None, None)ifparamKeynotinkb.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