@ -913,6 +913,7 @@ def checkFalsePositives(injection):
retVal = True
# 如果注入数据中所有元素都在PAYLOAD.TECHNIQUE.BOOLEAN、PAYLOAD.TECHNIQUE.TIME、PAYLOAD.TECHNIQUE.STACKED中, 或者注入数据长度为1且PAYLOAD.TECHNIQUE.UNION在注入数据中且"Generic"在注入数据[PAYLOAD.TECHNIQUE.UNION].title中
if all ( _ in ( PAYLOAD . TECHNIQUE . BOOLEAN , PAYLOAD . TECHNIQUE . TIME , PAYLOAD . TECHNIQUE . STACKED ) for _ in injection . data ) or ( len ( injection . data ) == 1 and PAYLOAD . TECHNIQUE . UNION in injection . data and " Generic " in injection . data [ PAYLOAD . TECHNIQUE . UNION ] . title ) :
pushValue ( kb . injection )
@ -920,11 +921,13 @@ def checkFalsePositives(injection):
infoMsg + = " parameter ' %s ' is a false positive " % injection . parameter
logger . info ( infoMsg )
# 定义一个函数,返回一个随机整数
def _ ( ) :
return int ( randomInt ( 2 ) ) + 1
kb . injection = injection
# 遍历配置级别
for level in xrange ( conf . level ) :
while True :
randInt1 , randInt2 , randInt3 = ( _ ( ) for j in xrange ( 3 ) )
@ -932,38 +935,48 @@ def checkFalsePositives(injection):
randInt1 = min ( randInt1 , randInt2 , randInt3 )
randInt3 = max ( randInt1 , randInt2 , randInt3 )
# 如果配置字符串存在且配置字符串在任意一个Unicode(_)中
if conf . string and any ( conf . string in getUnicode ( _ ) for _ in ( randInt1 , randInt2 , randInt3 ) ) :
continue
# 如果配置非字符串存在且配置非字符串在任意一个Unicode(_)中
if conf . notString and any ( conf . notString in getUnicode ( _ ) for _ in ( randInt1 , randInt2 , randInt3 ) ) :
continue
# 如果randInt3 > randInt2 > randInt1, 则跳出循环
if randInt3 > randInt2 > randInt1 :
break
# 如果不满足布尔表达式, 则retVal为False, 跳出循环
if not checkBooleanExpression ( " %d %s %d " % ( randInt1 , INFERENCE_EQUALS_CHAR , randInt1 ) ) :
retVal = False
break
# 如果PAYLOAD.TECHNIQUE.BOOLEAN不在注入数据中, 则检查布尔表达式
if PAYLOAD . TECHNIQUE . BOOLEAN not in injection . data :
checkBooleanExpression ( " %d %s %d " % ( randInt1 , INFERENCE_EQUALS_CHAR , randInt2 ) ) # just in case if DBMS hasn't properly recovered from previous delayed request
# 如果满足布尔表达式, 则retVal为False, 跳出循环
if checkBooleanExpression ( " %d %s %d " % ( randInt1 , INFERENCE_EQUALS_CHAR , randInt3 ) ) : # this must not be evaluated to True
retVal = False
break
# 如果满足布尔表达式, 则retVal为False, 跳出循环
elif checkBooleanExpression ( " %d %s %d " % ( randInt3 , INFERENCE_EQUALS_CHAR , randInt2 ) ) : # this must not be evaluated to True
retVal = False
break
# 如果不满足布尔表达式, 则retVal为False, 跳出循环
elif not checkBooleanExpression ( " %d %s %d " % ( randInt2 , INFERENCE_EQUALS_CHAR , randInt2 ) ) : # this must be evaluated to True
retVal = False
break
# 如果满足布尔表达式, 则retVal为False, 跳出循环
elif checkBooleanExpression ( " %d %d " % ( randInt3 , randInt2 ) ) : # this must not be evaluated to True (invalid statement)
retVal = False
break
# 如果retVal为False, 则记录警告信息
if not retVal :
warnMsg = " false positive or unexploitable injection point detected "
logger . warning ( warnMsg )
@ -978,22 +991,28 @@ def checkSuhosinPatch(injection):
Checks for existence of Suhosin - patch ( and alike ) protection mechanism ( s )
"""
# 如果注入点在GET或URI中
if injection . place in ( PLACE . GET , PLACE . URI ) :
debugMsg = " checking for parameter length "
debugMsg + = " constraining mechanisms "
logger . debug ( debugMsg )
# 将当前的注入点保存到栈中
pushValue ( kb . injection )
# 设置当前的注入点
kb . injection = injection
# 生成一个随机数
randInt = randomInt ( )
# 检查参数长度是否被限制
if not checkBooleanExpression ( " %d = %s %d " % ( randInt , ' ' * SUHOSIN_MAX_VALUE_LENGTH , randInt ) ) :
warnMsg = " parameter length constraining "
warnMsg + = " mechanism detected (e.g. Suhosin patch). "
warnMsg + = " Potential problems in enumeration phase can be expected "
logger . warning ( warnMsg )
# 恢复之前的注入点
kb . injection = popValue ( )
@stackedmethod
@ -1001,9 +1020,12 @@ def checkFilteredChars(injection):
debugMsg = " checking for filtered characters "
logger . debug ( debugMsg )
# 将当前的注入点保存到栈中
pushValue ( kb . injection )
# 设置当前的注入点
kb . injection = injection
# 生成一个随机数
randInt = randomInt ( )
# all other techniques are already using parentheses in tests
@ -1025,17 +1047,23 @@ def checkFilteredChars(injection):
kb . injection = popValue ( )
# 定义一个函数, 用于检查SQL注入
def heuristicCheckSqlInjection ( place , parameter ) :
# 如果配置文件中设置了跳过启发式测试, 则返回None
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 = " "
# 如果配置文件中设置了前缀或后缀,则获取前缀和后缀
if conf . prefix or conf . suffix :
if conf . prefix :
prefix = conf . prefix
@ -1043,52 +1071,82 @@ def heuristicCheckSqlInjection(place, parameter):
if conf . suffix :
suffix = conf . suffix
# 生成一个包含一个单引号和一个双引号的随机字符串
while randStr . count ( ' \' ' ) != 1 or randStr . count ( ' \" ' ) != 1 :
randStr = randomStr ( length = 10 , alphabet = HEURISTIC_CHECK_ALPHABET )
# 设置启发式模式为True
kb . heuristicMode = True
# 构造payload
payload = " %s %s %s " % ( prefix , randStr , suffix )
# 使用agent.payload方法构造payload
payload = agent . payload ( place , parameter , newValue = payload )
# 发送请求并获取页面和响应码
page , _ , code = Request . queryPage ( payload , place , content = True , raise404 = False )
# 将页面和响应码保存到kb中
kb . heuristicPage = page
kb . heuristicCode = code
# 设置启发式模式为False
kb . heuristicMode = False
# 解析页面中的文件路径
parseFilePaths ( page )
# 判断是否是数据库错误
result = wasLastResponseDBMSError ( )
# 构造提示信息
infoMsg = " heuristic (basic) test shows that %s parameter ' %s ' might " % ( " %s " % paramType if paramType != parameter else " " , parameter )
# 判断page中是否包含FORMAT_EXCEPTION_STRINGS中的任意一个字符串
def _ ( page ) :
return any ( _ in ( page or " " ) for _ in FORMAT_EXCEPTION_STRINGS )
# 判断page中是否包含FORMAT_EXCEPTION_STRINGS中的任意一个字符串, 且kb.originalPage中不包含
casting = _ ( page ) and not _ ( kb . originalPage )
# 如果没有进行类型转换, 且result为空, kb.dynamicParameter为真, origValue为数字, 且kb.heavilyDynamic为假
if not casting and not result and kb . dynamicParameter and origValue . isdigit ( ) and not kb . heavilyDynamic :
# 生成一个随机整数
randInt = int ( randomInt ( ) )
# 生成payload
payload = " %s %s %s " % ( prefix , " %d - %d " % ( int ( origValue ) + randInt , randInt ) , suffix )
# 使用agent.payload生成payload
payload = agent . payload ( place , parameter , newValue = payload , where = PAYLOAD . WHERE . REPLACE )
# 使用Request.queryPage查询页面
result = Request . queryPage ( payload , place , raise404 = False )
# 如果result为空
if not result :
# 生成一个随机字符串
randStr = randomStr ( )
# 生成payload
payload = " %s %s %s " % ( prefix , " %s . %d %s " % ( origValue , random . randint ( 1 , 9 ) , randStr ) , suffix )
# 使用agent.payload生成payload
payload = agent . payload ( place , parameter , newValue = payload , where = PAYLOAD . WHERE . REPLACE )
# 使用Request.queryPage查询页面
casting = Request . queryPage ( payload , place , raise404 = False )
# 根据casting和result的值, 设置kb.heuristicTest的值
kb . heuristicTest = HEURISTIC_TEST . CASTED if casting else HEURISTIC_TEST . NEGATIVE if not result else HEURISTIC_TEST . POSITIVE
# 如果kb.heavilyDynamic为真
if kb . heavilyDynamic :
# 输出debug信息
debugMsg = " heuristic check stopped because of heavy dynamicity "
logger . debug ( debugMsg )
# 返回kb.heuristicTest的值
return kb . heuristicTest
# 如果casting为真
if casting :
# 输出错误信息
errMsg = " possible %s casting detected (e.g. ' " % ( " integer " if origValue . isdigit ( ) else " type " )
# 获取url的后缀
platform = conf . url . split ( ' . ' ) [ - 1 ] . lower ( )
# 根据后缀,输出不同的错误信息
if platform == WEB_PLATFORM . ASP :
errMsg + = " %s =CInt(request.querystring( \" %s \" )) " % ( parameter , parameter )
elif platform == WEB_PLATFORM . ASPX :
@ -1101,45 +1159,68 @@ def heuristicCheckSqlInjection(place, parameter):
errMsg + = " ' ) at the back-end web application "
logger . error ( errMsg )
# 如果kb.ignoreCasted为空
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的值
kb . ignoreCasted = readInput ( message , default = ' Y ' if conf . multipleTargets else ' N ' , boolean = True )
# 如果result为真
elif result :
# 输出信息
infoMsg + = " be injectable "
# 如果Backend.getErrorParsedDBMSes()不为空
if Backend . getErrorParsedDBMSes ( ) :
# 输出信息
infoMsg + = " (possible DBMS: ' %s ' ) " % Format . getErrorParsedDBMSes ( )
logger . info ( infoMsg )
# 如果以上条件都不满足
else :
# 输出警告信息
infoMsg + = " not be injectable "
logger . warning ( infoMsg )
# 设置kb.heuristicMode为真
kb . heuristicMode = True
# 设置kb.disableHtmlDecoding为真
kb . disableHtmlDecoding = True
# 生成两个随机字符串
randStr1 , randStr2 = randomStr ( NON_SQLI_CHECK_PREFIX_SUFFIX_LENGTH ) , randomStr ( NON_SQLI_CHECK_PREFIX_SUFFIX_LENGTH )
# 生成value
value = " %s %s %s " % ( randStr1 , DUMMY_NON_SQLI_CHECK_APPENDIX , randStr2 )
# 生成payload
payload = " %s %s %s " % ( prefix , " ' %s " % value , suffix )
# 使用agent.payload生成payload
payload = agent . payload ( place , parameter , newValue = payload )
# 使用Request.queryPage查询页面
page , _ , _ = Request . queryPage ( payload , place , content = True , raise404 = False )
# 获取paramType
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 ( ) :
# 如果value的大写字母在page的大写字母中, 则执行以下代码
infoMsg = " heuristic (XSS) test shows that %s parameter ' %s ' might be vulnerable to cross-site scripting (XSS) attacks " % ( " %s " % paramType if paramType != parameter else " " , parameter )
# 输出信息, 表示参数可能存在XSS攻击
logger . info ( infoMsg )
if conf . beep :
# 如果配置文件中设置了beep, 则执行beep函数
beep ( )
for match in re . finditer ( FI_ERROR_REGEX , page or " " ) :
# 在page中查找FI_ERROR_REGEX, 如果找到, 则执行以下代码
if randStr1 . lower ( ) in match . group ( 0 ) . lower ( ) :
# 如果randStr1的小写字母在match.group(0)的小写字母中,则执行以下代码
infoMsg = " heuristic (FI) test shows that %s parameter ' %s ' might be vulnerable to file inclusion (FI) attacks " % ( " %s " % paramType if paramType != parameter else " " , parameter )
# 输出信息, 表示参数可能存在FI攻击
logger . info ( infoMsg )
if conf . beep :
# 如果配置文件中设置了beep, 则执行beep函数
beep ( )
break
@ -1157,6 +1238,7 @@ def checkDynParam(place, parameter, value):
"""
if kb . choices . redirect :
# 如果kb.choices.redirect为True, 则返回None
return None
kb . matchRatio = None
@ -1166,11 +1248,14 @@ def checkDynParam(place, parameter, value):
paramType = conf . method if conf . method not in ( None , HTTPMETHOD . GET , HTTPMETHOD . POST ) else place
infoMsg = " testing if %s parameter ' %s ' is dynamic " % ( " %s " % paramType if paramType != parameter else " " , parameter )
# 输出信息,表示正在测试参数是否动态
logger . info ( infoMsg )
try :
payload = agent . payload ( place , parameter , value , getUnicode ( randInt ) )
# 生成payload
dynResult = Request . queryPage ( payload , place , raise404 = False )
# 发送payload, 获取结果
except SqlmapConnectionException :
pass
@ -1184,40 +1269,51 @@ def checkDynamicContent(firstPage, secondPage):
This function checks for the dynamic content in the provided pages
"""
# 如果没有网络连接,则跳过动态内容检查
if kb . nullConnection :
debugMsg = " dynamic content checking skipped "
debugMsg + = " because NULL connection used "
logger . debug ( debugMsg )
return
# 如果没有提供页面内容,则无法检查动态内容
if any ( page is None for page in ( firstPage , secondPage ) ) :
warnMsg = " can ' t check dynamic content "
warnMsg + = " because of lack of page content "
logger . critical ( warnMsg )
return
# 如果提供了页面内容,并且页面内容长度超过最大长度,则无法计算相似度
if firstPage and secondPage and any ( len ( _ ) > MAX_DIFFLIB_SEQUENCE_LENGTH for _ in ( firstPage , secondPage ) ) :
ratio = None
else :
try :
# 获取当前线程的数据
seqMatcher = getCurrentThreadData ( ) . seqMatcher
# 设置第一个序列
seqMatcher . set_seq1 ( firstPage )
# 设置第二个序列
seqMatcher . set_seq2 ( secondPage )
# 计算相似度
ratio = seqMatcher . quick_ratio ( )
except MemoryError :
ratio = None
# 如果无法计算相似度,则跳过动态内容检查
if ratio is None :
kb . skipSeqMatcher = True
# In case of an intolerable difference turn on dynamicity removal engine
elif ratio < = UPPER_RATIO_BOUND :
# 如果比率小于等于上限比率, 则调用findDynamicContent函数
findDynamicContent ( firstPage , secondPage )
count = 0
# 当Request.queryPage()返回False时, 循环执行
while not Request . queryPage ( ) :
count + = 1
# 如果重试次数超过配置的最大重试次数, 则输出警告信息, 并将textOnly设置为True
if count > conf . retries :
warnMsg = " target URL content appears to be too dynamic. "
warnMsg + = " Switching to ' --text-only ' "
@ -1226,12 +1322,14 @@ def checkDynamicContent(firstPage, secondPage):
conf . textOnly = True
return
# 输出警告信息, 表示目标URL内容过于动态, sqlmap将重试请求
warnMsg = " target URL content appears to be heavily dynamic. "
warnMsg + = " sqlmap is going to retry the request(s) "
singleTimeLogMessage ( warnMsg , logging . CRITICAL )
kb . heavilyDynamic = True
# 重新查询页面内容
secondPage , _ , _ = Request . queryPage ( content = True )
findDynamicContent ( firstPage , secondPage )
@ -1249,17 +1347,22 @@ def checkStability():
infoMsg = " testing if the target URL content is stable "
logger . info ( infoMsg )
# 获取原始页面内容
firstPage = kb . originalPage # set inside checkConnection()
# 计算延迟时间
delay = MAX_STABILITY_DELAY - ( time . time ( ) - ( kb . originalPageTime or 0 ) )
delay = max ( 0 , min ( MAX_STABILITY_DELAY , delay ) )
time . sleep ( delay )
# 重新查询页面内容
secondPage , _ , _ = Request . queryPage ( content = True , noteResponseTime = False , raise404 = False )
# 如果存在重定向, 则返回None
if kb . choices . redirect :
return None
# 比较两个页面内容是否相同
kb . pageStable = ( firstPage == secondPage )
if kb . pageStable :
@ -1281,6 +1384,7 @@ def checkStability():
warnMsg + = " ' Page comparison ' "
logger . warning ( warnMsg )
# 提示用户如何继续
message = " how do you want to proceed? [(C)ontinue/(s)tring/(r)egex/(q)uit] "
choice = readInput ( message , default = ' C ' ) . upper ( )
@ -1288,6 +1392,7 @@ def checkStability():
raise SqlmapUserQuitException
elif choice == ' S ' :
# 如果用户选择字符串匹配, 则调用showStaticWords函数
showStaticWords ( firstPage , secondPage )
message = " please enter value for parameter ' string ' : "
@ -1307,6 +1412,7 @@ def checkStability():
raise SqlmapNoneDataException ( errMsg )
elif choice == ' R ' :
# 如果用户选择正则表达式匹配,则提示用户输入正则表达式
message = " please enter value for parameter ' regex ' : "
regex = readInput ( message )
@ -1324,6 +1430,7 @@ def checkStability():
raise SqlmapNoneDataException ( errMsg )
else :
# 如果用户选择继续, 则调用checkDynamicContent函数
checkDynamicContent ( firstPage , secondPage )
return kb . pageStable
@ -1334,12 +1441,15 @@ def checkWaf():
Reference : http : / / seclists . org / nmap - dev / 2011 / q2 / att - 1005 / http - waf - detect . nse
"""
# 如果配置中存在字符串匹配、不匹配、正则表达式匹配、假数据、离线模式或跳过WAF检测, 则返回None
if any ( ( conf . string , conf . notString , conf . regexp , conf . dummy , conf . offline , conf . skipWaf ) ) :
return None
# 如果原始HTTP状态码为404, 则返回None
if kb . originalCode == _http_client . NOT_FOUND :
return None
# 从哈希数据库中获取WAF检测结果
_ = hashDBRetrieve ( HASHDB_KEYS . CHECK_WAF_RESULT , True )
if _ is not None :
if _ :
@ -1348,6 +1458,7 @@ def checkWaf():
logger . critical ( warnMsg )
return _
# 如果原始页面内容为空, 则返回None
if not kb . originalPage :
return None
@ -1356,36 +1467,44 @@ def checkWaf():
logger . info ( infoMsg )
retVal = False
# 生成随机payload
payload = " %d %s " % ( randomInt ( ) , IPS_WAF_CHECK_PAYLOAD )
place = PLACE . GET
# 如果URI参数存在, 则将payload添加到URI参数中
if PLACE . URI in conf . parameters :
value = " %s = %s " % ( randomStr ( ) , agent . addPayloadDelimiters ( payload ) )
else :
value = " " if not conf . parameters . get ( PLACE . GET ) else conf . parameters [ PLACE . GET ] + DEFAULT_GET_POST_DELIMITER
value + = " %s = %s " % ( randomStr ( ) , agent . addPayloadDelimiters ( payload ) )
# 保存当前状态
pushValue ( kb . choices . redirect )
pushValue ( kb . resendPostOnRedirect )
pushValue ( conf . timeout )
# 设置重定向为True, 重发POST请求为False, 超时时间为IPS_WAF_CHECK_TIMEOUT
kb . choices . redirect = REDIRECTION . YES
kb . resendPostOnRedirect = False
conf . timeout = IPS_WAF_CHECK_TIMEOUT
try :
# 查询页面内容,并比较比率
retVal = ( Request . queryPage ( place = place , value = value , getRatioValue = True , noteResponseTime = False , silent = True , raise404 = False , disableTampering = True ) [ 1 ] or 0 ) < IPS_WAF_CHECK_RATIO
except SqlmapConnectionException :
retVal = True
finally :
kb . matchRatio = None
# 恢复之前的状态
conf . timeout = popValue ( )
kb . resendPostOnRedirect = popValue ( )
kb . choices . redirect = popValue ( )
# 将WAF检测结果写入哈希数据库
hashDBWrite ( HASHDB_KEYS . CHECK_WAF_RESULT , retVal , True )
# 如果检测到WAF, 则输出警告信息, 并提示用户是否继续
if retVal :
if not kb . identifiedWafs :
warnMsg = " heuristics detected that the target "
@ -1411,9 +1530,11 @@ def checkNullConnection():
Reference : http : / / www . wisec . it / sectou . php ? id = 472 f952d79293
"""
# 如果存在POST数据, 则返回False
if conf . data :
return False
# 从哈希数据库中获取NULL连接检测结果
_ = hashDBRetrieve ( HASHDB_KEYS . CHECK_NULL_CONNECTION_RESULT , True )
if _ is not None :
kb . nullConnection = _
@ -1426,10 +1547,12 @@ def checkNullConnection():
infoMsg = " testing NULL connection to the target URL "
logger . info ( infoMsg )
# 保存当前状态
pushValue ( kb . pageCompress )
kb . pageCompress = False
try :
# 使用HEAD方法测试NULL连接
page , headers , _ = Request . getPage ( method = HTTPMETHOD . HEAD , raise404 = False )
if not page and HTTP_HEADER . CONTENT_LENGTH in ( headers or { } ) :
@ -1438,6 +1561,7 @@ def checkNullConnection():
infoMsg = " NULL connection is supported with HEAD method ( ' Content-Length ' ) "
logger . info ( infoMsg )
else :
# 使用GET方法测试NULL连接
page , headers , _ = Request . getPage ( auxHeaders = { HTTP_HEADER . RANGE : " bytes=-1 " } )
if page and len ( page ) == 1 and HTTP_HEADER . CONTENT_RANGE in ( headers or { } ) :
@ -1446,6 +1570,7 @@ def checkNullConnection():
infoMsg = " NULL connection is supported with GET method ( ' Range ' ) "
logger . info ( infoMsg )
else :
# 使用skip-read方法测试NULL连接
_ , headers , _ = Request . getPage ( skipRead = True )
if HTTP_HEADER . CONTENT_LENGTH in ( headers or { } ) :
@ -1465,36 +1590,48 @@ def checkNullConnection():
return kb . nullConnection in getPublicTypeMembers ( NULLCONNECTION , True )
def checkConnection ( suppressOutput = False ) :
# 获取当前线程数据
threadData = getCurrentThreadData ( )
# 检查主机名是否为IP地址
if not re . search ( r " \ A \ d { 1,3} \ . \ d { 1,3} \ . \ d { 1,3} \ . \ d { 1,3} \ Z " , conf . hostname ) :
# 如果没有代理、Tor、Dummy或离线模式
if not any ( ( conf . proxy , conf . tor , conf . dummy , conf . offline ) ) :
try :
# 解析主机名
debugMsg = " resolving hostname ' %s ' " % conf . hostname
logger . debug ( debugMsg )
socket . getaddrinfo ( conf . hostname , None )
except socket . gaierror :
# 主机名不存在
errMsg = " host ' %s ' does not exist " % conf . hostname
raise SqlmapConnectionException ( errMsg )
except socket . error as ex :
# 解析主机名时出现问题
errMsg = " problem occurred while "
errMsg + = " resolving a host name ' %s ' ( ' %s ' ) " % ( conf . hostname , getSafeExString ( ex ) )
raise SqlmapConnectionException ( errMsg )
except UnicodeError as ex :
# 处理主机名时出现问题
errMsg = " problem occurred while "
errMsg + = " handling a host name ' %s ' ( ' %s ' ) " % ( conf . hostname , getSafeExString ( ex ) )
raise SqlmapDataException ( errMsg )
# 如果没有抑制输出, 并且不是Dummy或离线模式
if not suppressOutput and not conf . dummy and not conf . offline :
# 测试连接到目标URL
infoMsg = " testing connection to the target URL "
logger . info ( infoMsg )
try :
# 获取页面内容
kb . originalPageTime = time . time ( )
page , headers , _ = Request . queryPage ( content = True , noteResponseTime = False )
# 获取原始响应
rawResponse = " %s %s " % ( listToStrValue ( headers . headers if headers else " " ) , page )
# 如果提供了字符串,检查字符串是否在页面内容中
if conf . string :
infoMsg = " testing if the provided string is within the "
infoMsg + = " target URL page content "
@ -1506,6 +1643,7 @@ def checkConnection(suppressOutput=False):
warnMsg + = " URL raw response, sqlmap will carry on anyway "
logger . warning ( warnMsg )
# 如果提供了正则表达式,检查正则表达式是否匹配页面内容
if conf . regexp :
infoMsg = " testing if the provided regular expression matches within "
infoMsg + = " the target URL page content "
@ -1519,19 +1657,25 @@ def checkConnection(suppressOutput=False):
kb . errorIsNone = False
# 如果服务器头包含不兼容的服务器,关闭预连接机制
if any ( _ in ( kb . serverHeader or " " ) for _ in PRECONNECT_INCOMPATIBLE_SERVERS ) :
singleTimeWarnMessage ( " turning off pre-connect mechanism because of incompatible server ( ' %s ' ) " % kb . serverHeader )
conf . disablePrecon = True
# 如果没有原始页面, 并且最后一个响应是HTTP错误
if not kb . originalPage and wasLastResponseHTTPError ( ) :
# 如果最后一个请求的HTTP错误代码不在忽略代码中
if getLastRequestHTTPError ( ) not in ( conf . ignoreCode or [ ] ) :
errMsg = " unable to retrieve page content "
raise SqlmapConnectionException ( errMsg )
# 如果最后一个响应是DBMS错误
elif wasLastResponseDBMSError ( ) :
warnMsg = " there is a DBMS error found in the HTTP response body "
warnMsg + = " which could interfere with the results of the tests "
logger . warning ( warnMsg )
# 如果最后一个响应是HTTP错误
elif wasLastResponseHTTPError ( ) :
# 如果最后一个请求的HTTP错误代码不在忽略代码中
if getLastRequestHTTPError ( ) not in ( conf . ignoreCode or [ ] ) :
warnMsg = " the web server responded with an HTTP error code ( %d ) " % getLastRequestHTTPError ( )
warnMsg + = " which could interfere with the results of the tests "
@ -1539,14 +1683,20 @@ def checkConnection(suppressOutput=False):
else :
kb . errorIsNone = True
# 如果重定向为是, 并且最后一个重定向URL和最后一个请求UID相同
if kb . choices . redirect == REDIRECTION . YES and threadData . lastRedirectURL and threadData . lastRedirectURL [ 0 ] == threadData . lastRequestUID :
# 如果最后一个重定向URL以https://开头, 并且主机名在最后一个重定向URL中
if ( threadData . lastRedirectURL [ 1 ] or " " ) . startswith ( " https:// " ) and conf . hostname in getUnicode ( threadData . lastRedirectURL [ 1 ] ) :
# 将URL改为https://
conf . url = re . sub ( r " https?:// " , " https:// " , conf . url )
# 获取端口号
match = re . search ( r " :( \ d+) " , threadData . lastRedirectURL [ 1 ] )
port = match . group ( 1 ) if match else 443
# 将URL中的端口号改为最后一个重定向URL中的端口号
conf . url = re . sub ( r " : \ d+(/| \ Z) " , r " : %s \ g<1> " % port , conf . url )
except SqlmapConnectionException as ex :
# 如果提供了IPv6地址, 检查连接
if conf . ipv6 :
warnMsg = " check connection to a provided "
warnMsg + = " IPv6 address with a tool like ping6 "
@ -1555,13 +1705,16 @@ def checkConnection(suppressOutput=False):
warnMsg + = " any addressing issues "
singleTimeWarnMessage ( warnMsg )
# 如果HTTP错误代码为404
if any ( code in kb . httpErrorCodes for code in ( _http_client . NOT_FOUND , ) ) :
errMsg = getSafeExString ( ex )
logger . critical ( errMsg )
# 如果有多个目标
if conf . multipleTargets :
return False
# 提示用户是否退出
msg = " it is not recommended to continue in this kind of cases. Do you want to quit and make sure that everything is set up properly? [Y/n] "
if readInput ( msg , default = ' Y ' , boolean = True ) :
raise SqlmapSilentQuitException
@ -1570,12 +1723,16 @@ def checkConnection(suppressOutput=False):
else :
raise
finally :
# 将原始页面和页面模板设置为最后一个页面和最后一个代码
kb . originalPage = kb . pageTemplate = threadData . lastPage
kb . originalCode = threadData . lastCode
# 如果提供了cookie, 并且没有声明cookie, 也没有在httpHeaders中声明cookie, 也没有设置dropSetCookie
if conf . cj and not conf . cookie and not any ( _ [ 0 ] == HTTP_HEADER . COOKIE for _ in conf . httpHeaders ) and not conf . dropSetCookie :
# 获取cookie
candidate = DEFAULT_COOKIE_DELIMITER . join ( " %s = %s " % ( _ . name , _ . value ) for _ in conf . cj )
# 提示用户是否使用这些cookie
message = " you have not declared cookie(s), while "
message + = " server wants to set its own ( ' %s ' ). " % re . sub ( r " (=[^=;] {10} [^=;])[^=;]+([^=;] {10} ) " , r " \ g<1>... \ g<2> " , candidate )
message + = " Do you want to use those [Y/n] "
@ -1585,8 +1742,11 @@ def checkConnection(suppressOutput=False):
return True
# 检查网络连接
def checkInternet ( ) :
# 获取页面内容
content = Request . getPage ( url = CHECK_INTERNET_ADDRESS , checking = True ) [ 0 ]
# 判断页面内容是否包含指定的值
return CHECK_INTERNET_VALUE in ( content or " " )
def setVerbosity ( ) : # Cross-referenced function