1. 程式人生 > >SQLmap註入啟發式檢測算法

SQLmap註入啟發式檢測算法

current defaults sys basic 產生 PV new sql str

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 2、啟發式註入檢測 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、異常類的處理以及自定義異常類使用

SQLmap註入啟發式檢測算法