1、经过setTargetEnv()就进入了checkWaf()的环节
def checkWaf():
"""
Reference: http://seclists.org/nmap-dev/2011/q2/att-1005/http-waf-detect.nse
"""
if any((conf.string, conf.notString, conf.regexp, conf.dummy, conf.offline, conf.skipWaf)):
return None
_ = hashDBRetrieve(HASHDB_KEYS.CHECK_WAF_RESULT, True)
if _ is not None:
if _:
warnMsg = "previous heuristics detected that the target "
warnMsg += "is protected by some kind of WAF/IPS/IDS"
logger.critical(warnMsg)
return _
infoMsg = "checking if the target is protected by "
infoMsg += "some kind of WAF/IPS/IDS"
logger.info(infoMsg)
retVal = False
payload = "%d %s" % (randomInt(), IDS_WAF_CHECK_PAYLOAD)
value = "" if not conf.parameters.get(PLACE.GET) else conf.parameters[PLACE.GET] + DEFAULT_GET_POST_DELIMITER
value += agent.addPayloadDelimiters("%s=%s" % (randomStr(), payload))
pushValue(conf.timeout)
conf.timeout = IDS_WAF_CHECK_TIMEOUT
try:
retVal = Request.queryPage(place=PLACE.GET, value=value, getRatioValue=True, noteResponseTime=False, silent=True)[1] < IDS_WAF_CHECK_RATIO
except SqlmapConnectionException:
retVal = True
finally:
kb.matchRatio = None
conf.timeout = popValue()
if retVal:
warnMsg = "heuristics detected that the target "
warnMsg += "is protected by some kind of WAF/IPS/IDS"
logger.critical(warnMsg)
if not conf.identifyWaf:
message = "do you want sqlmap to try to detect backend "
message += "WAF/IPS/IDS? [y/N] "
if readInput(message, default='N', boolean=True):
conf.identifyWaf = True
if conf.timeout == defaults.timeout:
logger.warning("dropping timeout to %d seconds (i.e. '--timeout=%d')" % (IDS_WAF_CHECK_TIMEOUT, IDS_WAF_CHECK_TIMEOUT))
conf.timeout = IDS_WAF_CHECK_TIMEOUT
hashDBWrite(HASHDB_KEYS.CHECK_WAF_RESULT, retVal, True)
return retVal
def heuristicCheckSqlInjection(place, parameter):
if kb.nullConnection:
debugMsg = "heuristic check skipped because NULL connection used"
logger.debug(debugMsg)
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
if conf.suffix:
suffix = conf.suffix
while randStr.count('\'') != 1 or randStr.count('\"') != 1:
randStr = randomStr(length=10, alphabet=HEURISTIC_CHECK_ALPHABET)
kb.heuristicMode = True
payload = "%s%s%s" % (prefix, randStr, suffix)
payload = agent.payload(place, parameter, newValue=payload)
page, _, _ = Request.queryPage(payload, place, content=True, raise404=False)
kb.heuristicPage = page
kb.heuristicMode = False
parseFilePaths(page)
result = wasLastResponseDBMSError()
infoMsg = "heuristic (basic) test shows that %s parameter " % paramType
infoMsg += "'%s' might " % parameter
def _(page):
return any(_ in (page or "") for _ in FORMAT_EXCEPTION_STRINGS)
casting = _(page) and not _(kb.originalPage)
if not casting and not result and kb.dynamicParameter and origValue.isdigit():
randInt = int(randomInt())
payload = "%s%s%s" % (prefix, "%d-%d" % (int(origValue) + randInt, randInt), suffix)
payload = agent.payload(place, parameter, newValue=payload, where=PAYLOAD.WHERE.REPLACE)
result = Request.queryPage(payload, place, raise404=False)
if not result:
randStr = randomStr()
payload = "%s%s%s" % (prefix, "%s.%d%s" % (origValue, random.randint(1, 9), randStr), suffix)
payload = agent.payload(place, parameter, newValue=payload, where=PAYLOAD.WHERE.REPLACE)
casting = Request.queryPage(payload, place, raise404=False)
kb.heuristicTest = HEURISTIC_TEST.CASTED if casting else HEURISTIC_TEST.NEGATIVE if not result else HEURISTIC_TEST.POSITIVE
if casting:
errMsg = "possible %s casting " % ("integer" if origValue.isdigit() else "type")
errMsg += "detected (e.g. \"$%s=intval($_REQUEST['%s'])\") " % (parameter, parameter)
errMsg += "at the back-end web application"
logger.error(errMsg)
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 = readInput(message, default='Y' if conf.multipleTargets else 'N', boolean=True)
elif result:
infoMsg += "be injectable"
if Backend.getErrorParsedDBMSes():
infoMsg += " (possible DBMS: '%s')" % Format.getErrorParsedDBMSes()
logger.info(infoMsg)
else:
infoMsg += "not be injectable"
logger.warn(infoMsg)
kb.heuristicMode = True
randStr1, randStr2 = randomStr(NON_SQLI_CHECK_PREFIX_SUFFIX_LENGTH), randomStr(NON_SQLI_CHECK_PREFIX_SUFFIX_LENGTH)
value = "%s%s%s" % (randStr1, DUMMY_NON_SQLI_CHECK_APPENDIX, randStr2)
payload = "%s%s%s" % (prefix, "'%s" % value, suffix)
payload = agent.payload(place, parameter, newValue=payload)
page, _, _ = Request.queryPage(payload, place, content=True, raise404=False)
paramType = conf.method if conf.method not in (None, HTTPMETHOD.GET, HTTPMETHOD.POST) else place
if value.lower() in (page or "").lower():
infoMsg = "heuristic (XSS) test shows that %s parameter " % paramType
infoMsg += "'%s' might be vulnerable to cross-site scripting attacks" % parameter
logger.info(infoMsg)
for match in re.finditer(FI_ERROR_REGEX, page or ""):
if randStr1.lower() in match.group(0).lower():
infoMsg = "heuristic (FI) test shows that %s parameter " % paramType
infoMsg += "'%s' might be vulnerable to file inclusion attacks" % parameter
logger.info(infoMsg)
break
kb.heuristicMode = False
return kb.heuristicTest
首先是对sql注入的检测
|
1
|
payload = "%s%s%s" % (prefix, randStr, suffix)
|
randStr就是随机生成的可导致sql语句因闭合问题而报错的字符,这个payload不是用来注入的,而是将其产生的页面作为启发式注入标准页面(kb.heuristicPage),与不注入产生的正常页面(kb.originalPage)作为一个基准性对比。
接下来是一个关键变量casting
|
1
|
casting = _(page) and not _(kb.originalPage)
|
_()函数如下
|
1
2
|
def _(page):
return any(_ in (page or "") for _ in FORMAT_EXCEPTION_STRINGS)
|
FORMAT_EXCEPTION_STRINGS 是一些在Web服务中常见的sql语句关于变量类型出错的报错
('Type mismatch', 'Error converting', 'Conversion failed', 'String or binary data would be truncated', 'Failed to convert', 'unable to interpret text value', 'Input string was not in a correct format', 'System.FormatException', 'java.lang.NumberFormatException', 'ValueError: invalid literal', 'DataTypeMismatchException', 'CF_SQL_INTEGER', ' for CFSQLTYPE ', 'cfqueryparam cfsqltype', 'InvalidParamTypeException', 'Invalid parameter type', 'is not of type numeric', '<cfif Not IsNumeric(', 'invalid input syntax for integer', 'invalid input syntax for type', 'invalid number', 'character to number conversion error', 'unable to interpret text value', 'String was not recognized as a valid', 'Convert.ToInt', 'cannot be converted to a ', 'InvalidDataException')
casting为false就代表这种注入样例因为变量类型不统一而无法使用,所以用户可以选择跳过这些样例
第二个关键变量 result
|
1
|
result = wasLastResponseDBMSError()
|
函数如下
|
1
2
3
4
5
6
|
def wasLastResponseDBMSError():
"""
Returns True if the last web request resulted in a (recognized) DBMS error page
"""
threadData = getCurrentThreadData()
return threadData.lastErrorPage and threadData.lastErrorPage[0] == threadData.lastRequestUID
|
如果启发式注入标准页面是可识别的,则返回ture,否则返回false
这也作为sqlmap启发性测试结果的标志,为true就代表可能存在注入,为false就可能不存在注入
接下来就是对于非sql注入漏洞的检测,sqlmap会随机生成可引发其他类型漏洞报错的字符,然后进行注入测试,在sqlmap源码中可以看出除了sql注入,还测试了xss与文件包含漏洞
1、内部类,java编译器生成的内部类的字节码文件的名字和通常的不同,内部类对应的字节码文件名字的格式是“外嵌类名&内部类类名”,如果将内部类添加修饰词static,则可以这样调用, RedCowForm.RedCow redCow=new RedCowForm.RedCow(122,232,333);
public class NeiBuLai {
public static void main(String[] args) {
// TODO Auto-generated method stub
RedCowForm form=new RedCowForm("德纳司");
form.showMessage();
RedCowForm.RedCow redCow=new RedCowForm.RedCow(122,232,333);
}
}
class RedCowForm{
static String formName;
RedCow cow;
RedCowForm(){
}
RedCowForm(String s){
cow=new RedCow(12,23,34);
formName=s;
}
public void showMessage(){
cow.speak();
}
static class RedCow{
String cowName="bed wos";
int height,weight,price;
// int t=0;int w=0;int p=0;
RedCow(int h, int w,int p){
height=h;
weight=w;
price=p;
}
void speak(){
System.out.println("mingzi"+cowName+"shenggao"+height+"tizhong"+weight+"shenghuozai"+formName);
}
}
}
2、匿名类匿名类继承父类的方法一个可以重写父类的方法,匿名类必须是内部类。用匿名类创建对象时直接使用父类的构造方法。
public class NiMingLei {
public static void main(String[] args) {
// TODO Auto-generated method stub
ShowBoard board=new ShowBoard();
board.showMessge(new OutPutEnglish());//这是一个OutPutAlpaabe的子类对象
board.showMessge(new OutPutAlphabe(){ public void output(){
for(char c='@';c<'*';c++)
System.out.printf("%3c",c);
}
}
);//这里是OutPutAlphabe的一个匿名类也是他的一个子类对象
}
}
abstract class OutPutAlphabet{
public abstract void output();
}
class OutPutEnglish extends OutPutAlphabet{
public void output(){
for(char c='a';c<'z';c++){
System.out.printf("%3c",c);
}
}
}
class ShowBoard{
void showMessge(OutPutAlphabet show){
show.output();
}
}
3、接口匿名类
public class JieKouNiMIng {
public static void main(String[] args) {
// TODO Auto-generated method stub
HelloMachine machine=new HelloMachine();
machine.turnON(new SpeakHello(){
public void spaek(){
System.out.println("Hello ,you are wellcome");
}
@Override
public void speak() {
// TODO Auto-generated method stub
}
});
machine.turnON(new SpeakHello(){
public void spaek(){
System.out.println("Hello ");
}
@Override
public void speak() {
// TODO Auto-generated method stub
}
});
}
}
interface SpeakHello{
void speak();
}
class HelloMachine{
public void turnON(SpeakHello hello){
hello.speak();
}
}
4、异常类的处理以及自定义异常类使用