AWVS14.7sql注入部分源码分析

AWVS-SQL注入部分源码分析

**PS:**在文章中我会对一些句式进行缩进,文字默认定格,输入缩进对应着代码缩进,所以请注意我的段落缩进。

classErrorBasedSQLInjection.inc

classSQLErrorMessages()

this.plainArray

存储常见的sql注入报错信息,如

'Microsoft OLE DB Provider for ODBC Drivers',
'Error Executing Database Query',
'Microsoft OLE DB Provider for SQL Server',
'ODBC Microsoft Access Driver',

this.regexArray

存储常见的sql注入的正则匹配信息,如

/(Incorrect\ssyntax\snear\s'[^']*')/,
/(Syntax error: Missing operand after '[^']*' operator)/,
/Syntax error near\s.*?\sin the full-text search condition\s/,
/column "\w{5}" does not exist/,
/near\s[^:]+?:\ssyntax\serror/,
/(pg_query\(\)[:]*\squery\sfailed:\serror:\s)/,
/('[^']*'\sis\snull\sor\snot\san\sobject)/,
/(ORA-\d{4,5}:\s)/,

**PS:**这里解释一下this.plainArray与this.regexArray的区别,二者都是对字符串进行匹配,但是this.plainArray直接将数组中的内容与字符串进行匹配,要求有完全吻合的变量才符合匹配要求,而this.regexArray则强调了一种正则匹配的规则,只要字符串中有符合匹配规则的内容,就视为符合匹配要求。

this.FalsePositivesPlainArray

存储sql注入报错时的明显特征,如

"Connection Timeout",
"(0x80131904)",
"org.apache.commons.dbcp.SQLNestedException: Cannot get a connection, pool error Timeout waiting for idle object"

this.FalsePositivesRegexArray

暂时为空,根据数组名判断是存储sql注入报错时的这则表达特征的。

classSQLErrorMessages.prototype.isFalsePositive = function (text)

功能

用于判断是否存在sql报错信息明显特征的函数。

内容

将获取的数据依次与this.FalsePositivesPlainArray中的数据进行匹配,如果存在返回true。

将获取的数据依次与this.FalsePositivesRegexArray中的数据进行匹配,如果存在返回true。

如果都没有返回false。

classSQLErrorMessages.prototype.searchOnText = function (text)

功能

通过字符串匹配的方式,判断字符串属于哪一种sql注入的特征。

内容

先声明一个变量 _in,默认值为body

将获取的数据进行匹配,如果识别到"HTTP/1."或"HTTP/0."则获取的信息识别为响应包,_in赋值为response

将获取的数据依次与this.plainArray中的数据进行匹配,如果存在返回highlightFromTextSearch(this.plainArray[i], text, _in),这个函数的作用是将text中匹配到的this.plainArray[i]值返回给_in

将获取的数据依次与this.regexArray中的数据进行匹配,如果存在返回highlightFromRegexMatch(m, _in),这个函数是将m中的正则匹配结果返回给**_in**,其中m=this.regexArray[i].exec(text)

如果都没有返回false。

InjectionResult(data, adItem)

功能

为类属性this.datathis.adItem赋值

内容

this.data = data;
this.adItem = adItem;

classErrorBasedSQLInjection(targetUrl, errorMessages, scheme, inputIndex, variationIndex, reflectionPoint)

功能

为类属性进行赋值,尤其是对输入内容(变化值)this.variations进行保存,并初始化部分类属性。

内容

先对一些类变量赋值

this.scheme = scheme;
this.targetUrl = targetUrl;
this.errorMessages = errorMessages;
this.inputIndex = inputIndex;
this.reflectionPoint = reflectionPoint;
this.foundVulnOnVariation = false;
this.lastJob = null;
this.lastJobConfirm = null;
this.disableSensorBased = false;

如果scheme不为空,则初始化this.currentVariationthis.origValue = this.getOrigValue();

如果scheme不为空且inputIndex不为空,创建数组this.variations,将inputIndex赋值给this.variations

如果scheme不为空但inputIndex为空,创建数组this.variations,将this.scheme.selectVariationsForInput(inputIndex)赋值给this.variations

classErrorBasedSQLInjection.prototype.isSQLInjection = function (sensorData, start, end)

功能

根据指纹特征判断数据库类型,并存储尝试注入的结果。

内容

先初始化itemsitems = sensorData.getItems(“SQL_Query”),这里的sensorData.getItems大家可以理解为一个对http请求包进行抓取分析的函数。

如果items为空null

items中依次取出值item

​ 如果item不为空,初始化dbType = “mysql” addData = item.additional

​ 如果addData长度大于等于2,db = addData[1]

​ 如果在db中匹配到database=,db = db.substr(9) dbType = db.toLowerCase()

item.dataList中依次取出值entry

​ 如果在entry中匹配到变量start字符串

​ 若dbType == 'mysql’ax.util.testForInjection(entry, ax.util.InjectionType.MySQL, start, end) 不等于空(尝试注入函数返回值不为空),则返回InjectionResult(entry, item)

​ 若dbType == 'mssql’dbType == 'mssql_or_access’ax.util.testForInjection(entry, ax.util.InjectionType.MySQL, start, end) 不等于空,则返回InjectionResult(entry, item)

​ 若dbType == 'pg’ax.util.testForInjection(entry, ax.util.InjectionType.MySQL, start, end) 不等于空,则返回InjectionResult(entry, item)

​ 若dbType == 'sqlite’ax.util.testForInjection(entry, ax.util.InjectionType.MySQL, start, end) 不等于空,则返回InjectionResult(entry, item)

​ 若dbType == 'oracle’ax.util.testForInjection(entry, ax.util.InjectionType.MySQL, start, end) 不等于空,则返回InjectionResult(entry, item)

​ 若dbType == 'sybase’ax.util.testForInjection(entry, ax.util.InjectionType.MySQL, start, end) 不等于空,则返回InjectionResult(entry, item)

​ 若dbType不符合上述情况,且ax.util.testForInjection(entry, ax.util.InjectionType.MySQL, start, end) 不等于空,则返回InjectionResult(entry, item)

否则返回false

classErrorBasedSQLInjection.prototype.getOrigValue = function ()

功能

匹配输入数据(this.inputIndex)是否已经输入过。

内容

初始化变量value,初始值为空。

从this.variations(此数组为classErrorBasedSQLInjection中存储的输入内容)中依次取值,将输入的数据(this.inputIndex)与之前存储的数据(this.variations)进行匹配,匹配结果为varValue,如果存在包含关系(variations包含输入的数据this.inputIndex)。若value为空且varValue不为空,则将value赋值为varValue,并退出循环,返回value

classErrorBasedSQLInjection.prototype.request = function (value)

功能

为当前变体(variation)附一个值value并发送HTTP请求。

内容

如果存在文件上传(this.scheme.hasFileInput)且输入的数据存在关键标志(this.scheme.getInputFlags(this.inputIndex))且上传的数据是文件(INPUT_FLAG_IS_FILE),则设定上传文件名(setInputFileName)为value,设定上传文件类型(setInputContentType)为image/png,设定上传文件值(setInputValue)为value。否则设定上传文件值为value

初始化lastJob(this.lastJob = new THTTPJob()),为this.lastJob.url赋值为this.targetUrl

如果targetHasAcuSensor(this.scheme.targetHasAcuSensor)中的值不为空,则 调用this.lastJob.addAspectHeaders()

调用populateRequest,传入lastjob (this.scheme.populateRequest(this.lastJob))

PS:调用populateRequest的作用就是填充完善请求头。

如果请求头中不存在字符串Referer,则调用函数addHeader添加请求头Referer

随后向lastJob发包(this.lastJob.execute())。

初始化变量tmp = false

如果请求结果不报错(wasError))且可以收到响应包,则向reflectionPoint发包,将响应包数据复制到lastJob响应包中,将tmp赋值为wasError的值。

最后返回 !this.lastJob.wasError && !tmp

classFileInclusion.prototype.requestProof = function (value, dontEncode)

功能

提取证明,判断提取证明(Proof)是否存在。

内容

如果存在文件上传(this.scheme.hasFileInput)且输入的数据存在关键标志(this.scheme.getInputFlags(this.inputIndex))且上传的数据是文件(INPUT_FLAG_IS_FILE),则设定上传文件名(setInputFileName)为value,设定上传文件类型(setInputContentType)为image/png

​ 如果dontEncode == TRUE,调用setEncodedInputValue,设定编码的输入值(this.inputIndex)为value (this.scheme.setEncodedInputValue(this.inputIndex, value)),否则设定输入值(this.inputIndex)为value

否则

​ 如果dontEncode == TRUE,调用setEncodedInputValue,设定编码的输入值(this.inputIndex)为value (this.scheme.setEncodedInputValue(this.inputIndex, value)),否则设定输入值(this.inputIndex)为value

初始化this.lastJobProof = new THTTPJob()

初始化this.lastJobProof.url = this.targetUrl

如果targetHasAcuSensor(this.scheme.targetHasAcuSensor)中的值不为空,则 调用this.lastJob.addAspectHeaders()

调用populateRequest,传入lastjob (this.scheme.populateRequest(this.lastJob))

如果请求头中不存在字符串Referer,则调用函数addHeader添加请求头Referer

随后向lastJob发包(this.lastJob.execute())。

返回 !this.lastJobProof.wasError

classFileInclusion.prototype.extractProofOfExploit = function (testValue)

功能

尝试提取漏洞利用证明

内容

初始化proof = false

初始化proof_title = false

初始化proof_contents = false

初始化regex = false

如果testValue以**http://**开头,则

testValue = "http://bxss.me/t/fit.txt?";
regex = /(63c19a6da79816b21429e5bb262daed863c19a6da79816b21429e5bb262daed8)/;
proof_title = "URL - http://bxss.me/t/fit.txt";

否则

testValue = "../../../../../../../../proc/version";
regex = /(Linux\sversion\s\d.*?\s\(.*?\)\s\(gcc\sversion\s\d.*?\(.*?\)\s*\)\s\#.*?[A-Z]{3}\s\d{4})/;
proof_title = "File - /proc/version";

如果regex不为空

​ 如果testValue提取证明结果为flase,则返回false

​ 将变量match赋值为this.lastJobProof.response.toString().match(regex),这里是将regex(正则匹配规则)对testValue中的请求包的信息进行匹配后返回的匹配结果。

​ 如果match不为空且match(数组)长度大于1,则将proof_contents赋值为match[1]

​ 如果proof_contents不为空,则返回[proof_title, proof_contents]。

返回 proof。

classFileInclusion.prototype.alert = function (testValue, matchedText, sourceFile, sourceLine, additionalInfo, acuSensor)

功能

为扫描器生成报告项。

内容

初始化this.foundVulnOnVariation = true

初始化flags=[]

如果acuSensor == TRUE,则向flags内写入值verifiedacusensor

如果this.reflectionPoint不为空,则向flags内写入值stored

初始化proof_title = false

初始化proof_contents = false

初始化常量proof = this.extractProofOfExploit(testValue)

如果proof存在且proof(数组)长度为2,则proof_title = proof[0]proof_contents = proof[1]

如果proof_titleproof_contents都不为空,则向flags内写入值verified

初始化newVuln

var newVuln = {
    typeId: "File_inclusion.xml",
    path: this.scheme.path,
    tags: flags,
    highlights: [matchedText],
    details: {
        input_type: this.scheme.getInputTypeStr(this.inputIndex),
        input_name: this.scheme.getInputName(this.inputIndex),
        proof_title: proof_title ? proof_title : false,
        proof_contents: proof_contents ? proof_contents : false,
        test_value: testValue,
        matched_text: matchedText ? matchedText : false,
        reflection_point: this.reflectionPoint ? this.reflectionPoint.url.url : false
    },
    http: this.lastJob.getNativeObject(),
    ssl: scriptArg.target.url.protocol == 'https',
    parameter: this.scheme.getInputName(this.inputIndex),
    attackVector: testValue
};

如果sourceFile不为空或者additionalInfo不为空,则为newVuln增添值

newVuln.sensor = {
    file: sourceFile,
    line: sourceLine,
    additional: additionalInfo
};

newVuln添加到scanState (scanState.addVuln(newVuln))

classFileInclusion.prototype.testInjection = function (value, dontEncode)

功能

尝试进行sql注入,如果尝试注入失败就生成报告项。

内容

初始化sensorPayload = value.includes(this.injectionValidator.startMark)

如果**!this.request(value, dontEncode)true**,则返回false

初始化job = this.lastJob

创建data = this.disableSensorBased,如果为空则调用getSensorData(this.lastJob)

如果datasensorPayload不为空,则初始化变量injRes = this.isFileInclusion(value, data)

​ 如果injResinjRes.adItem不为空,则为变量additional赋值,additional = "File: " + injRes.data + “\r\n” + injRes.adItem.additional[0],生成报告项this.alert(value, “”, injRes.adItem.fileName, injRes.adItem.fileNo, additional, 1)并返回false

否则,初始化this.disableSensorBased = true

​ 如果this.reflectionPoint为空,为变量matchedText赋值,matchedText = this.injectionPatterns.searchOnText(job.response.toString()),这里将job的响应包返回的信息与injectionPatterns中的信息进行匹配,将匹配到的结果赋值给matchedText

​ 如果matchedText不为空,生成报告项this.alert(value, matchedText)并返回false

返回true

classFileInclusion.prototype.testInjectionSelfInclude = function (value)

功能

尝试进行sql注入,如果尝试注入失败就生成报告项。

内容

如果发送http请求失败(!this.request(value, 0)),则返回false

初始化job = this.lastJob

match赋值,match = job.response.toString().match(/(<%@[^%]+?%>)/),这里将正则匹配方法<%@[^%]+?%>job的响应包进行匹配,如果job.response中有符合匹配规则的字符串,则将其赋值给match

如果matchmatch[1]不为空则生成报告项this.alert(value, match[1])并返回false

返回true

classFileInclusion.prototype.startTesting = function ()

功能

主函数,用于测试所有输入变化。

内容

初始化inputType = this.scheme.getInputTypeStr(this.inputIndex)

初始化inputName = this.scheme.getInputName(this.inputIndex)

this.variations中依次取出值

​ 如果this.foundVulnOnVariation == false则退出循环。

​ 赋值变量this.currentVariation = i

​ 如果targetHasAcuSensorreflectionPoint不为空

​ 如果reflectionPoint为空,则this.injectionValidator.startMark = rnd.randStrDigits(6)this.injectionValidator.endMark = rnd.randStrDigits(6)

​ 如果尝试注入结果为false,则继续循环。

!this.testInjection(`1${this.injectionValidator.startMark}/../../xxx\\..\\..\\${this.injectionValidator.endMark}`)

​ 否则,this.injectionValidator.startMark = rnd.randStrDigits(6)this.injectionValidator.endMark = rnd.randStrDigits(6)

​ 如果尝试注入结果为false,则继续循环。

!this.testInjection(`1${this.injectionValidator.startMark}/../../xxx\\..\\..\\${this.injectionValidator.endMark}`)

​ 如果this.injectionPatterns不为空,赋值origValue = this.getOrigValue(),初始化extension = “jpg”

​ 如果origValue不为空且origValue中包含字符点".",取最后一个点(.)后面的字符串,赋值给extension

​ 初始化schemeExtension = ""

​ 初始化schemePath = scheme.path

​ 如果schemePath不为空且chemePath中包含字符点".",取最后一个点(.)后面的字符串,赋值给schemeExtension;取最后一个反斜杠(/)后面的字符串,赋值给schemeFileName

​ 如果尝试注入结果为false,则继续循环。

!this.testInjection("http://some-inexistent-website.acu/some_inexistent_file_with_long_name%3F." + extension, 1)

​ 如果尝试注入结果为false,则继续循环。

!this.testInjection("1some_inexistent_file_with_long_name%00." + extension, 1)

​ 如果尝试注入结果为false,则继续循环。

!this.testInjection("Http://" + AcuMonitor_AMServer + "/t/fit.txt", 1)

​ 如果尝试注入结果为false,则继续循环。

!this.testInjection("http://" + AcuMonitor_AMServer + "/t/fit.txt%3F." + extension, 1)

​ 如果尝试注入结果为false,则继续循环。

!this.testInjection(AcuMonitor_AMServer, 0)

​ 如果schemeExtension == 'jsp’origValue中包含字符串反斜杠(/)

​ 如果尝试注入结果为false,则继续循环。

!this.testInjectionSelfInclude(schemePath)

​ 如果尝试注入结果为false,则继续循环。

!this.testInjectionSelfInclude(schemePath.replace(/^\/[^\/]+/, ""))

​ 如果尝试注入结果为false,则继续循环。

!this.testInjectionSelfInclude(schemePath.replace(/^\/[^\/]+/, "").replace(/^\/[^\/]+/, ""))

​ 如果尝试注入结果为false,则继续循环。

!this.testInjectionSelfInclude(schemePath.replace(/^\/[^\/]+/, "").replace(/^\/[^\/]+/, "").replace(/^\/[^\/]+/, ""))

​ 如果schemeExtension == ‘jsp’

​ 如果尝试注入结果为false,则继续循环。

!this.testInjectionSelfInclude(schemeFileName)

​ 如果尝试注入结果为false,则继续循环。

!this.testInjectionSelfInclude("./" + schemeFileName)

​ 如果尝试注入结果为false,则继续循环。

!this.testInjectionSelfInclude("/" + schemeFileName)

SQL_Injection_In_Basic_Auth.script

功能

先判断访问网站知否符合sql注入的要求,处理好URL,调用至多四次testInjection函数来判断是否存在SQL注入。

尝试用户名

尝试密码

单引号用户名,双引号密码

双引号用户名,单引号密码

包含

#include constants.inc;
#include classErrorBasedSQLInjection.inc;

自定义函数

function alert(path, value, job, matchedText, sourceFile, sourceLine, additionalInfo, acuSensor)

AWVS用于报告漏洞情况的函数,当判断出存在漏洞后,调用此函数用于上报漏洞,回显对应漏洞信息。这个只需要知道大概作用就好,认真分析还要牵扯大量调用函数,所以就先不赘述了。

function request(dir, withAop, path, value)

初始化变量

lastJob = new THTTPJob();
lastJob.url = dir.url;
lastJob.uri = path;
lastJob.autoAuthenticate = false;

在lastJob请求头中添加字头名Authorization,值为value的值。(lastJob.request.addHeader(“Authorization”, value, true))

如果withAop == True则调用添加请求头的函数lastJob.addAspectHeaders()

发包lastJob.execute()

返回**!lastJob.wasError**

function testInjection(dir, withAop, path, value, tester)

为变量sensorPayload赋值

sensorPayload = value.includes("MUFDVVNUQVJUJ1wiKi9cclxuIFx0QUNVRU5EOmFhYWE=") || value.includes("YWFhYToxQUNVU1RBUlQnXCIqL1xyXG4gXHRBQ1VFTkQ=")
MUFDVVNUQVJUJ1wiKi9cclxuIFx0QUNVRU5EOmFhYWE=
BASE64解密结果
1ACUSTART'\"*/\r\n \tACUEND:aaaa

YWFhYToxQUNVU1RBUlQnXCIqL1xyXG4gXHRBQ1VFTkQ=
BASE64解密结果
aaaa:1ACUSTART'\"*/\r\n \tACUEND

如果请求结果为false(request(dir, withAop, path, value)),则返回false

初始化job = lastJob

data = getSensorData(job)

如果data不为空且sensorPayload判断结果不为空,则赋值变量**injRes = tester.isSQLInjection(data, ACUINJSTART, ACUINJEND)**判断是否存在sql注入。

​ 如果injRes和injRes.adItem不为空则赋值变量additional = "SQL query: " + injRes.data + “\r\n” + injRes.adItem.additional[0]并调用alert函数(alert(path, value, job, “”, injRes.adItem.fileName, injRes.adItem.fileNo, additional, 1))并返回false

否则初始化变量matchedText = errorMessages.searchOnText(job.response.body)

​ 如果matchedText不为空,则调用alert函数(alert(path, value, job, matchedText))并返回false

返回true

主函数

初始化dir = getCurrentDirectory()

如果请求后状态码为401且请求头中变量名WWW-Authenticate的变量值中包含Basic则初始化变量

var lastJob = null;
var errorMessages = new classSQLErrorMessages();
var dirName = dir.fullPath;

​ 如果URL结尾不是反斜杠(/),则在URL结尾添加反斜杠(/) (if (dirName.charAt(dirName.length - 1) != ‘/’) dirName = dirName + ‘/’)

​ 赋值变量**tester = new classErrorBasedSQLInjection(scanURL, errorMessages, null, 0)**功能是为类属性进行赋值(this.variations)。

​ 如果dir.hasAcuSensor不为空

​ 如果testInjection(dir, true, dirName, “Basic MUFDVVNUQVJUJ1wiKi9cclxuIFx0QUNVRU5EOmFhYWE=”, tester)返回结果为true【尝试用户名】,则调用函数testInjection (testInjection(dir, true, dirName, “Basic YWFhYToxQUNVU1RBUlQnXCIqL1xyXG4gXHRBQ1VFTkQ=”, tester))【尝试密码】。

​ 否则

​ 如果testInjection(dir, false, dirName, “Basic Jzoi”)返回结果为true【单引号用户,双引号密码】,则调用函数testInjection (testInjection(dir, false, dirName, ‘Basic Ijon’))【双引号用户,单引号密码】。

SQL_Injection_In_URI.script

功能

先判断访问网站知否符合sql注入的要求,处理好URL,调用至多六次testInjection函数来判断是否存在SQL注入。

包含

#include constants.inc;
#include classErrorBasedSQLInjection.inc;
#include dir_listing_helpers.inc;

自定义函数

function alert(path, value, job, matchedText, sourceFile, sourceLine, additionalInfo, acuSensor)

AWVS用于报告漏洞情况的函数,当判断出存在漏洞后,调用此函数用于上报漏洞,回显对应漏洞信息。

function request(dir, withAop, path)

初始化变量

lastJob = new THTTPJob();
lastJob.url = dir.url;
lastJob.uri = path;

如果withAop == True则调用添加请求头的函数lastJob.addAspectHeaders()

添加请求头

lastJob.request.addHeader('User-Agent', '1\'"2000', true);
lastJob.request.addHeader('referer', '1\'"3000', true);
lastJob.request.addHeader('client-ip', '1\'"4000', true);
lastJob.request.addHeader('x-forwarded-for', '1\'"5000', true);
lastJob.request.addHeader('accept-language', '1\'"6000', true);
lastJob.request.addHeader('via', '1\'"7000', true);

发包lastJob.execute()

返回**!lastJob.wasError**

function testInjection(dir, withAop, path, value, tester)

赋值变量sensorPayload = value.includes(ACUINJSTART)

如果请求结果为false(request(dir, withAop, path, value)),则返回false

初始化job = lastJob

data = getSensorData(job)

如果data不为空且sensorPayload判断结果不为空,则赋值变量**injRes = tester.isSQLInjection(data, ACUINJSTART, ACUINJEND)**判断是否存在sql注入。

​ 如果injResinjResinjRes都不为空,则赋值变量additional = "SQL query: " + injRes.data + “\r\n” + injRes.adItem.additional[0]并调用alert函数(alert(path, value, job, “”, injRes.adItem.fileName, injRes.adItem.fileNo, additional, 1))并返回false

否则初始化变量matchedText = errorMessages.searchOnText(job.response.body)

​ 如果matchedText不为空,则调用alert函数(alert(path, value, job, matchedText))并返回false

返回true

主函数

初始化dir = getCurrentDirectory()

如果请求后状态码为200,则初始化变量matches = new classDirListingMatches()

​ 如果**matches.searchOnText(dir.response.body)**为空,则初始化变量

var lastJob = null;
var errorMessages = new classSQLErrorMessages();
var dirName = dir.fullPath;

​ 如果URL结尾不是反斜杠(/),则在URL结尾添加反斜杠(/) (if (dirName.charAt(dirName.length - 1) != ‘/’) dirName = dirName + ‘/’)

​ 赋值变量**tester = new classErrorBasedSQLInjection(scanURL, errorMessages, null, 0)**功能是为类属性进行赋值(this.variations)。

​ 如果dir.hasAcuSensor不为空

​ 如果testInjection(dir, true, dirName, dirName + `1 A C U I N J S T A R T ′ " {ACUINJSTART}'" ACUINJSTART"{ACUINJEND}`, tester, dirName)返回为false,则返回true。【简单构建】

​ 如果testInjection(dir, true, dirName, dirName + `index/1KaTeX parse error: Can't use function '\'' in math mode at position 14: {ACUINJSTART}\̲'̲"{ACUINJEND}`, tester, dirName)返回为false,则返回true。【index构建】

​ 如果testInjection(dir, true, dirName, dirName + `?id=1KaTeX parse error: Can't use function '\'' in math mode at position 14: {ACUINJSTART}\̲'̲"{ACUINJEND}`, tester, dirName)返回为false,则返回true。【带有参数的构建】

​ 如果matchedText为空

​ 如果testInjection(dir, false, dirName, dirName + "1’\“1000”)返回值为false,则返回true。【简单构建】

​ 如果testInjection(dir, false, dirName, dirName + "index/1’\“1000”)返回值为false,则返回true。【index构建】

​ 如果testInjection(dir, false, dirName, dirName + "?id=1’\“1000”)返回值为false,则返回true。【带有参数的构建】

猜你喜欢

转载自blog.csdn.net/weixin_46706771/article/details/124208693