SQLmap注入启发式检测算法
Posted 疏桐
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SQLmap注入启发式检测算法相关的知识,希望对你有一定的参考价值。
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、异常类的处理以及自定义异常类使用