构建攻击模块
攻击模块SDK包括SampleSQLi攻击模块,可用于构建自定义攻击模块。SampleSQLi攻击模块注入的攻击负载故意包含无效的SQL语法,然后在响应中查找常见的SQL错误。SampleSQLi模块用于攻击参数攻击点,并且只有特定于这些攻击点的代码。您可以类似地攻击其他攻击点,但函数ICSModule::RunAttack的实现看起来会有所不同。
创建配置文件
中特定于模块的子目录中至少要创建两个文件来注册攻击模块C:\ProgramFiles(x86)\Rapid7\AppSpider 6\ScanEngine\Modules
.请在目录中创建目录“samplesqli”C:\ProgramFiles(x86)\Rapid7\AppSpider 6\ScanEngine\Modules\
.然后复制到'SampleSQLi'目录attack.cfg
和module.cfg
SampleSQLi示例中的文件。
创建DLL项目
SampleSQLi示例已经有一个创建DLL的项目设置,因此不需要创建新项目。如果你创建了一个新的模块,你就必须创建一个新的c#类库项目。
实现类工厂
为了能够创建一个模块,AppSpider希望Attack module DLL实现一个名为CSModuleFactory
,派生自ICSModuleFactory接口。每次创建模块时,AppSpider都会实例化工厂并调用ICSModuleFactory: CreateModule
方法。
下面是CSModuleFactory类的实现:
类
CSModuleFactory
:ICSModuleFactory
{
公共图书馆
创建模块(指南
moduleGuid,输出模块
模块)
{
指南
correctGuid =新的``Guid
(“25A9426A-3E12-4B98-A573-5208460C91A1”);
如果
(correctGuid = = moduleGuid)
模块=新“SampleSQLi
();
其他的
模块=零
;
返回
模块! =零
;
}
}
请注意,同一个攻击模块DLL可以承载多个攻击模块。类工厂将通过使用参数'moduleGuid'知道应该创建哪个攻击模块类,该参数包含AppSpider想要创建的模块的GUID。
实现ICSModule接口
攻击模块必须实现ICSModule接口(详见c#接口部分)。模块的最小实现应该包括以下功能的实现:
负载
CalculateNumberOfAttacks
RunAttack(针对发送网络请求的主动攻击)或RunPassiveAttack(针对分析爬虫响应而不发送网络请求的被动攻击)
实现ICSModule:负载
每次创建模块实例时都会调用此函数。这个函数的目的是让AttackModule连接到专门为这个AttackModule实例创建的ModuleRunner对象。下面是在SampleSQLi示例中实现的ICSModule::Load方法的代码:
类
样本QLI
:ICSModule
{
AttackerCOMLib。IModuleRunner
_moduleRunner;
公共空间
装载(无符号整型
模块(NNERID)
{
_模内=新
AttackerCOMLib。模内
();
_moduleRunner.SetModuleInstanceID(moduleRunnerId);
}
.....
}
如您所见,该类有一个成员变量_moduleRunner,该变量在ICSModule::Load函数中初始化。模块将在后续调用中使用成员_moduleRunner访问特定于该模块实例的数据:攻击点、攻击配置等。
实现ICSModule::CalculateEnumberOfattacks
这个函数的目的是让模块告诉AppSpider在给定的攻击点和给定的攻击配置上需要运行多少攻击。下面是示例SampleSQLi中的函数实现:
公共单位
CalculateEnumberOfattacks()
{
AttackerCOMLib。IAttackPoint
attackPoint = _moduleRunner.GetAttackPoint ();
如果
(attackPoint.Type==AttackerCOMLib。AttackPointType
.ATTACKPOINT_PARAMETER)
{
//此模块仅执行参数攻击。
返回1
;
}
其他的
{
//其他攻击点包括:
//爬行结果
//文件
//目录
//主人
返回
0;
}
}
因为该模块只攻击参数攻击点,并且每个参数运行一次攻击,所以它为参数攻击点返回一次,为所有其他攻击点返回零。
在这里给出的示例中,使用的唯一标准是攻击点的类型,并且只计划了一次攻击。然而,攻击模块可根据攻击点中的信息完全自行决定使用其他标准。这可能会导致返回值为零攻击,或多个攻击。在攻击阶段,使用每次攻击的索引调用RunAttack。例如,如果CalculateEnumberOfattacks返回3,则使用索引0到2调用RunAttack。
例如,如果攻击点需要满足特定攻击相关的特定标准,可以在这里确定,并通过返回0将攻击点排除在攻击之外。这将防止不必要的攻击调度。或者,一个攻击模块可以有一定数量的变体来尝试。CalculateNumberOfAttacks可以返回这个数字,以便每个变体都能获得自己对RunAttack的调用。
此函数的实现应与module.cfg和attacks.cfg文件中AttackConfig结构和AttackModulePolicy结构的AttackPoints成员兼容。特别是,攻击点类型的测试通常应相同。例如,如果配置文件中的AttackPoints仅指定文件攻击Points,但CalculateEnumberOfattacks仅允许目录攻击点,则不会计划任何攻击。这是因为框架将仅为文件攻击点调用CalculateEnumberOfattacks。虽然在这两个位置检查相同的攻击点类型是多余的,但这确实有助于澄清。
实现ICSModule::RunAttack
在ICSModule::RunAttack中,SampleSQLi模块执行以下操作:
从模块运行器访问数据
提供自定义攻击负载
发送请求
分析响应
创造漏洞
从模块运行器访问数据
正如前面提到的,几乎所有攻击所需的信息都是通过ModuleRunner对象提供给模块的。SampleSQLi模块使用ModuleRunner来检索执行攻击所需的对象。下面是来自示例的代码:
AttackerCOMLib。IATACK配置
attackConfig=_moduleRunner.GetAttackConfig();
AttackerCOMLib。IAttackPoint
attackPoint = _moduleRunner.GetAttackPoint ();
AttackerCOMLib。Iparametatock点
parameterAttackPoint = (AttackerCOMLib.IParameterAttackPoint) attackPoint;
AttackerCOMLib。IParameterAttack
parameterAttack = parameterAttackPoint.GetParameterAttack ();
请注意,ModuleRunner::GetAttackPoint返回一个IAttackPoint接口。由于模块攻击参数攻击点,因此需要将“attackPoint”强制转换为接口IPareMetatackPoint,以访问允许攻击参数的功能。
提供自定义攻击有效载荷
攻击参数攻击点的典型攻击执行两个操作:
它将攻击负载注入到参数中。
它检查响应中是否存在表示漏洞的内容。
下面来自SampleSQLi模块的代码将攻击负载注入到参数值中:
1.一串
worialvalue = parameterAttackpoint.AttackParameter.orginalValue;
2.一串
attackString=attackConfig.CustomParameters.GetParameter(“attackString”);
3.一串
attackValue=attackString+原始值;
4 ParameterTack.ParameterValue=攻击值;
下面是每一行发生的情况的细分:
1号线-模块读取参数的原始值,即爬虫程序发现的值。
第2行- 模块通过攻击模块API从攻击配置文件(请参阅文件模块和攻击)读取攻击有效负载。
3号线—将攻击负载附加到该参数的原始值上。
4号线-该模块告诉AppSpider使用参数的新值(带有攻击负载)。
将请求发送到服务器
模块向AppSpider提供攻击负载后,需要发送包含攻击负载的参数值的请求。SampleSQLi模块通过以下调用来实现:
AttackerCOMLib。IResponse
attackResponse=parameterAttack.SendNextRequest();
该方法的名称包含单词“next”,这是其上下文的关键:序列。参数攻击和CrawlResult攻击可以是多个步骤序列的一部分。根据各种标准,框架在给定的序列中选择一个或多个步骤进行攻击。每一种攻击都被认为是单独的攻击,并且需要单独调用RunAttack。框架在调用RunAttack之前按照攻击步骤之前的顺序预运行步骤。然后,攻击模块继续运行攻击步骤,以及它希望执行的序列中的其他步骤,每个步骤都单独调用SendNextRequest。当序列完成时,SendNextRequest返回null而不是发送请求。为简单起见,框架将非序列的攻击视为只有一个步骤的序列。
注意:RunAttack的uint参数不表示序列步骤。它是攻击id,与CalculateEnumberOfattacks返回的数字相关,如上所述。API不会告诉模块序列的当前步骤,也不会告诉模块有多少步骤。
SendNextRequest通常应该在一个循环中运行,当SendNextRequest返回null时退出。简化后的版本是这样的:
为
(; ; )
{
AttackerCOMLib。IResponse
originalResponse = parameterAttack.OriginalResponse;
AttackerCOMLib。IResponse
attackResponse=parameterAttack.SendNextRequest();
如果
(attackResponse==null)
打破
;//序列结束
如果
(!parameteratack.PreProcessResponse())
持续
;//内置检查没有通过
// todo:分析回复
}
SendNextRequest之后,应通过调用PrepreprocessResponse来执行一组内置检查。对于所有攻击类型,它都会验证AttackConfig中的几个条目:Discard404、ResponseCode、ForbiddenResponseCode、ResponseContentCharset和ResponseContentType。
对于序列攻击,PreProcessResponse会根据“可攻击性”标准额外检查序列的每个步骤。也就是说,如果框架不会将序列的给定步骤安排为攻击步骤,那么在攻击步骤之后执行时,应该将其排除在发现漏洞的范围之外。
例如,如果框架计划了五步序列的第二步进行攻击,那么攻击模块可以(而且可能应该)发送第二步到第五步的请求。但是,如果第三步本身没有被安排进行攻击,那么攻击模块不应该为该步骤找到漏洞,即使必须执行该步骤才能从第二步到第四步和第五步,这可能会允许存在漏洞。在这种情况下,预处理响应将为返回false第三步,但后续步骤仍可能返回true(取决于其他检查)。
使用预处理响应并不是绝对必需的。但是,除非有特定于攻击模块的非常好的理由,否则应始终调用该模块并尊重其返回值。
分析响应并添加漏洞
iPareMetatack::SendNextRequest返回包含服务器响应的IResponse对象。可以分析此响应以检测漏洞。如果响应通过预处理响应的检查,则可以在模块中执行进一步的检查。鉴于SampleSQLi模块故意注入无效的SQL语法,它希望在响应中发现一些常见的SQL错误。这是通过以下代码实现的:
一串
vulnRegex=attackConfig.CustomParameters.GetParameter(“vulnRegex”);
匹配
匹配=正则表达式
.Match(响应。身体,vulnRegex,枚举
(b)忽略情况);
如果
(比赛成功)
{
//检查匹配的原始响应,以防止误报。
一串
errorString=match.Value;
一串
originalBody = originalResponse.Body;
匹配=正则表达式
.match(原始的,vulnregex,枚举
(b)忽略情况);
如果
(match.Success&&errorString==match.Value)
持续
;//匹配的字符串在原始响应中
AttackerCOMLib。IResult
结果= parameterAttack.createresult();
result.AttackValue=AttackValue;
result.ErrorString=match.Value;
_moduleRunner.SaveResult(结果);
}
上面介绍了检查误报的一种典型方法。相同的正则表达式应用于攻击响应和原始响应。如果获得相同的结果,则将其作为漏洞排除,并继续执行序列。这可能适用于也可能不适用于任何单个攻击,但此处包含它是为了说明典型的实现。
注意:用于此目的或类似目的的原始请求和/或响应必须在调用SendNextRequest之前从攻击对象处获得。示例代码显示了这一点(参见上文)。一旦调用SendNextRequest,底层迭代器将在序列中向前移动一步,并且对于当前步骤不正确。
当模块检测到漏洞时,需要创建一个IResult对象,并使用漏洞细节对其进行初始化。上面的代码展示了SampleSQLi模块如何实现这一点。
SendNextRequest vs SendRequest
参数攻击和爬网结果攻击源自接口ISequenceCapableAttack。对于这些攻击,可以使用SendNextRequest。所有其他攻击必须改用SendRequest。这些攻击与主机、目录和文件攻击点相关。在这些情况下,必须首先使用CreateRequest设置攻击。完成此操作后,将使用SendRequest发送攻击模块配置的请求。
对于参数攻击,通常使用SendNextRequest,但也可以使用CreateRequest/SendRequest对。通常,这样做是为了在为攻击提供的序列之外发送请求。可以发送所需数量的CreateRequest/SendRequest对,而不会影响框架中序列的进度。但是,应该小心,因为这可能会影响服务器端序列的行为。
或者,可以使用CreateRequest替换序列中的步骤。在这种情况下,调用CreateRequest,然后是SendNextRequest,没有中间的SendRequest。确保这是所需要的。对于参数攻击,这种方法可能永远不会用于序列的攻击步骤(即,在第一次调用SendNextRequest之前),因为它将替换包含更改的参数值(由ParameterTack.ParameterValue设置)的请求。
返回值
RunAttack可以多次迭代运行。这由RunAttack的返回值控制。通常,只会有一次迭代,RunAttack应该返回false。但是,如果返回值为true,则会重新运行攻击。使用相同的索引立即调用RunAttack。如果涉及到一个序列,它将从一开始就开始,就像RunAttack的第一次迭代一样,并且序列的指定攻击步骤保持不变。在以下情况下,应使用此选项,而不是使用CalculateEnumberOfattacks的较大返回值:
在至少执行一次攻击之前,可能无法知道何时应重新运行攻击。
当一系列攻击变体应该一起运行时,将它们的结果相互比较。这是可能的,因为当RunAttack的返回值为false时,对象状态在对RunAttack的调用之间保持。这是故意的。
利用多个RunAttack迭代的攻击模块的一个示例是盲SQL,其中必须发送一系列请求并比较结果。
其他要点:
不要将攻击迭代与序列步骤或攻击指标混淆。具有给定攻击索引的攻击可以迭代(重新运行)任意次数(通过从RunAttack返回false),每一次都将重新启动序列(如果存在的话)。
应注意通过确保RunAttack在有限的迭代次数后返回false来避免无限循环。
使用CSModule基类实现ICSModule
NTO已经创建了一个c#基类,可以用来帮助创建攻击模块:类CSModule。这个类继承自ICSModule接口,并且已经提供了大量实现攻击模块所必需的样板代码。自定义攻击模块可以从CSModule继承并覆盖适当的方法来完成ICSModule的实现。CSModule的使用完全是可选的,但即使没有使用,它也为规范攻击提供了一般的参考。
关于CSModule类,请注意以下几点:
CSModule没有实现ICSModuleFactory。工厂方法CreateModule仍然需要由自定义模块实现。
Load由CSModule实现,不需要由派生的自定义类实现。
ICSModule.CalculateEnumberOfAttacks在CSModule中有一个存根实现。如果涉及主动攻击,则派生类必须重写它。
ICSModule.RunAttack由CSModule实现,通常不需要由派生类重写。相反,根据攻击的类型,应该覆盖从RunAttack调用的适当方法。
CSModule基类的参数攻击
攻击模块SDK附带的SampleSQLi_CSM攻击模块中包含使用CSModule类的示例参数攻击。该功能与SampleSQLi示例相同,但它使用基类CSModule。
在参数攻击的情况下,运行攻击需要覆盖的相应CSModule方法是SetupParameterTack和ProcessSequenceCapableAttackResponse。
覆盖SetupParameterAttack
CSModule。CSModule RunAttack调用。SetupAttack(总是),对于参数攻击点,它反过来调用SetupParameterAttack。主要任务是设置IParameterAttack对象的ParameterValue属性的值。如果由于某种原因,在设置攻击时出现了问题,这个函数可以返回false,并且攻击将不会执行。
在示例代码中,SetupParameterAttack还存储了一些局部变量:攻击值(一个字符串)和对attack Config对象的引用。这些成员稍后将在ProcessSequenceCapableAttackResponse中使用。如上所述,在调用接口ICSModule中的函数之间,无法保证攻击模块的状态。然而,在单个这样的调用期间,对象状态是可以安全依赖的。因为SetupParameterAttack方法和ProcessSequenceCapableAttackResponse方法最终都是从ICSModule的单个调用中调用的。RunAttack,使用成员变量是非常安全的。
在SetupParameterAttack和ProcessSequenceCapableAttackResponse之间
在使用setupParameterTack设置攻击后,CSModule.RunAttack将调用CSModule.RunAttackLoop,它执行活动攻击的标准活动。其中包括检索原始响应对象以进行比较、调用SendNextRequest和调用PrepreprocessResponse。除非有令人信服的理由不做这些事情或以不同的方式做这些事情,否则建议不要重写RunAttackLoop。
重写ProcessSequenceCapableAttackResponse
在执行标准的主动攻击操作集后,RunAttackLoop将调用ProcessSequenceCapableAttackResponse。相同的函数用于参数攻击和爬网结果攻击。
在SamplesQli_csm模块中,process sequenceCapableAtTackResponse的实现执行了正则表达式比较,并根据需要创建Iresult对象。此函数的返回值确定是否应继续序列(如果有一个)。通常会继续延续,持续的返回值是正确的。
使用CSModule基类的爬网结果攻击
攻击模块SDK附带的SampleCSRF攻击模块中包含使用CSModule类的爬行结果攻击示例。在CrawlResult攻击的情况下,为使RunAttack发挥作用,需要覆盖的相应CSModule方法是SetupCrawlResultAttack和ProcessSequenceCapableAttackResponse。此示例还用于说明使用攻击模块API的一些其他方面,如下所述。
使用calculatenumberattacks检查攻击点类型以外的其他标准
如上所述,CalculateEnumberOfattacks可用于应用确定是否应计划攻击所需的任何条件。在本示例模块中,CalculateEnumberOfattacks除了简单地检查攻击点类型外,还应用了其他一些条件。请注意,这些特定检查特定于此模块,而不是以某种方式链接到CrawlResult攻击与其他类型的攻击相比,不应泛化。它们仅用于说明目的。
攻击点响应的响应代码必须为200或302。
原始响应不能是“404”响应。注意,没有直接检查响应代码。相反,IResponse。Is404。许多网站使用HTTP 404,但其他网站可能使用带有200响应的自定义页面来表示“未找到”条件。在爬行阶段,NTO扫描引擎应用一个专有算法来确定“未找到”的页面或特定于被扫描网站的响应。IResponse。Is404用于确定特定响应是否符合确定的“未找到”条件。
原始请求必须具有POST正文。此实现通过迭代请求的可攻击参数列表并检查其中一个是否具有POST位置来确定是否存在这种情况。
注意:攻击模块API中的术语与配置文件的AttackPoints成员不匹配。攻击模块API指的是“CrawlResult”攻击点,配置文件指的是“Web资源”攻击点。为了进行攻击,这些是同义词。要使爬网结果攻击生效,配置文件中的AttackPoints成员需要包含“Web资源”,代码需要测试爬网结果攻击点。有关详细信息,请参阅相关参考部分。
覆盖设置爬网结果跟踪
CSModule.RunAttack调用CSModule.SetupAttack(始终),对于爬行结果攻击点,它反过来调用setupcrawresultatck。上面所有关于覆盖SetupParameterTack的注释都适用于此处,但有一个注释除外:在要设置的IPParameterTack对象上没有单个ParameterValue。相反,有三个选项可用:
使用“icrawlresultatackpoint”设置多个参数值。GetParameter获取单个IAttackerParameter对象,然后调用ICrawlResultAttack。SetParameterValue设置所需的值。
使用ICrawlResultAttack.AttackedRequest检索原始请求,并根据需要修改请求。
使用IBaseAttack.CreateRequest创建一个全新的请求,并根据需要进行设置。
在示例代码中,使用了修改检索到的AttackedRequest的选项。可能想知道为什么不使用设置“referer”攻击者参数的方法。在这种情况下,原始请求中可能没有“referer”,因此没有此类参数。因此,通过调用IRequest.SetHeader添加(或更改,如果存在)referer标头。
重写ProcessSequenceCapableAttackResponse
与参数攻击一样,RunAttackLoop将调用ProcessSequenceCapableAttackResponse。
在此特定示例中,正则表达式不用于检测漏洞。而是使用响应签名。NTO响应签名使用专有算法来描述页面的一般结构,同时允许细节上的差异。这允许检测两个响应的“相等性”,这两个响应可能包含来自同一数据库的不同记录集,但在其他方面结构相同。在本例攻击中,如果带有伪造引用器的响应与不带伪造引用器的响应具有相同的签名,则该攻击被视为发现了漏洞。
在参数攻击示例中使用正则表达式查找漏洞,在爬网结果攻击示例中使用签名查找漏洞,不应被视为暗示概念之间的联系。当然,签名和正则表达式可以用于任何攻击类型。
与CSModule基类的其他类型的攻击
要实现非参数攻击点,CSModule基类具有要重写的其他函数。基类实现的逻辑以及包含的注释应用于指导实现者决定应重写哪些方法。通常,应重写的唯一方法是如果未被覆盖,at将抛出NotImplementedException。如示例所示,并非所有的at都需要覆盖,但只需要攻击点所需的覆盖由该模块使用。如果未选择正确的方法,这通常会在使用NotImplementedException进行调试期间显示。覆盖除这些方法之外的其他方法当然是可能的,但仅适用于例外情况。