内容简介:Web服务越来越多地应用于各种领域,从nance和e-government到社交媒体。由于它们是基于Web技术构建的,因此它们也遭受了前所未有的攻击和渗透。在这些攻击中,那些针对SQL注入漏洞的攻击在过去几年一直排名第一。在上线Web服务之前进行测试以检测此类漏洞至关重要。我们在本文中提出了一种自动化测试方法,即μ4SQLi,以及它的基础变异算子集。μ4SQLi可以产生有效的输入,从而导致可执行和有害的SQL语句。可执行性是关键,否则不能利用注入漏洞。我们的评估表明,该方法对于检测SQL注入漏洞并产生绕过现
Web服务越来越多地应用于各种领域,从nance和e-government到社交媒体。由于它们是基于Web技术构建的,因此它们也遭受了前所未有的攻击和渗透。在这些攻击中,那些针对 SQL 注入漏洞的攻击在过去几年一直排名第一。在上线Web服务之前进行测试以检测此类漏洞至关重要。我们在本文中提出了一种自动化测试方法,即μ4SQLi,以及它的基础变异算子集。μ4SQLi可以产生有效的输入,从而导致可执行和有害的SQL语句。可执行性是关键,否则不能利用注入漏洞。我们的评估表明,该方法对于检测SQL注入漏洞并产生绕过现实世界中常见配置的应用程序防火墙是有效的。
介绍
在本文中,我们提出了一种针对SQLi漏洞的黑盒自动化测试方法,称为 μ4SQLi。
从一般的初始测试用例开始,我们的方法应用了一组特定设计的变异算子,以增加产生成功SQLi攻击的可能性
更具体的说,这种新的攻击模式是通过在同一输入上应用多个变异算子来生成。此外,我们的一些变异算子旨在模糊注入的SQL代码片段以绕过安全过滤器,例如Web应用程序防火墙(WAF),而其他则旨在修复可能由先前突变引起的SQL语法错误。因此,我们的方法可以生成测试输入,这些输入可以生成语法正确且可执行的SQL语句,这些语句可以揭示SQL漏洞(如果存在)。通过产生绕过防火墙并导致可执行SQL语句的SQLi攻击,我们确保找到可利用的漏洞而不是无法利用的漏洞,例如因为过滤器阻止了所有攻击。此外,我们的方法产生的具体样本攻击可以帮助开发人员x源代码或安全过滤器的配置。我们的方法是完全自动化的,并且由名为 Xavier3的 工具 提供支持。
我们已经在一些暴露Web服务接口的开源系统上评估了我们的方法。与称为Std的基线方法相比,该方法由最新的137种已知SQLi攻击模式组成,我们的方法更快,并且显着更有可能在有限的时间预算内检测漏洞。此外,当主题系统受到WAF保护时,Std产生的泄露漏洞的任何输入都不能通过防火墙,而我们的方法仍然可以产生大量输入,通过防火墙并显示全部已知的漏洞。
本文的其余部分安排如下:第2部分提供了有关SQLi漏洞和审查相关工作的背景知识。第3节介绍了我们提出的变异算子和安全测试方法和工具。第4节介绍了评估以及对结果和有效性威胁的讨论。最后,第5节总结了这项工作。
背景和相关工作
本节提供有关Web服务和SQLi漏洞的简要背景,并回顾以前有关SQLi测试的工作。
背景
在使用数据库的系统(例如基于Web的系统)中,用于访问后端数据库的SQL语句通常由本机应用程序代码视为字符串。这些字符串是通过根据用户选择或应用程序的控制来连接不同的字符串片段而形成的流。一旦形成SQL语句,就会使用特殊函数将SQL语句发送到要执行的数据库服务器。例如,SQL语句形成如下(在案例研究中,我们的一个Web服务的简化示例):
$sql = "Select * From hotelList where country ='"; $sql = $sql . $country; $sql = $sql . '"'; $result = mysql_query($sql) or die(mysql_error());
变量 $country
是用户提供的输入,它与SQL语句的其余部分拼接,然后存储在字符串变量 $sql
中。字符串然后传递给函数 mysql_query 查询,该查询将SQL语句发送到要执行的数据库服务器。
SQLi是一种攻击技术,攻击者将恶意SQL代码片段注入这些输入参数。当输入参数直接在SQL语句中使用而没有经过适当的验证或消毒时,这种攻击是可能的。攻击者可能以改变生成的SQL语句行为的方式构造输入值,使攻击者能够对数据库执行操作,而不是应用程序开发人员所希望的操作。这些操作可能导致敏感数据暴露,未经授权插入或更改数据,丢失数据,甚至控制数据库服务器。
在前面的示例中,如果输入 $country
的值为 ‘ or 1 = 1 – 生成的SQL语句将是:
Select * From hotelList where country='' or 1 = 1 --'
第一个引号闭合原语句中的引号,最后的双短划线注释掉原语句最后的一个引号,使得结果SQL语句在语法上有效。子句 or 1 = 1 是重言式,即条件将始终为真,绕过where子句中的原始条件并返回表中的所有行。
为避免此类攻击,应用程序开发人员使用过滤器来防止恶意输入影响应用程序的行为。开发人员必须小心,不要阻止可能类似于恶意输入的有效输入。例如,使用拒绝单引号输入的过滤器可以防止前一个示例中的攻击。但是,过滤器也会拒绝单引号参与的有效输入(例如,O’Brian)
Web服务是面向服务的体系结构的基本模块,它提供了在Web上轻松访问和交换信息的工具。每个Web服务都提供一组可由客户端调用的操作。操作类似于传统编程语言中的方法,它具有一组输入参数并返回结构化输出。 Web服务的接口和功能通常由公共可用的Web服务描述语言(WSDL)文件描述。
在本文中,我们考虑被测服务的输入参数的SQLi漏洞:如果输入参数在服务实现的任何SQL语句中使用,并且通过此参数,攻击者可以发送,则输入参数容易受到SQLi攻击恶意输入,可以更改SQL语句的预期逻辑。要利用此类漏洞,攻击者必须提供导致可执行SQL语句的输入。否则,结果语句将被数据库拒绝,因此无法访问或更改数据。
相关工作
之前关于SQLi检测的研究使用了白盒和黑盒方法来检测漏洞。几种白盒方法使用污点分析来识别无效输入
进入SQL语句。 Fu和Qian 建议使用符号执行来识别需要满足的约束以导致SQLi攻击。 Shar等人。 使用源代码的数据挖掘来预测漏洞。除了要求访问源代码之外,正如我们之前提到的那样,并非总是可能的,这些方法中的大多数在其算法的某些方面依赖于一组已知的漏洞模式。
在生成测试用例时,现有的黑盒方法也依赖于已知的注入模式。Ciampa等提出了一种方法,分析合法和恶意测试用例的输出,包括错误消息,以了解有关后端数据库的类型和结构的更多信息。然后,此信息用于制作更有可能成功揭示漏洞的攻击输入。 Antunes等还分析了使用恶意和合法输入来检测漏洞时应用程序行为的差异。黄等人使用了一种使用已知攻击模式的测试生成方法。
各种学术和在线安全源已经列举和讨论了已知的 SQLi 模式。但是,依赖这些模式可能不足以测试应用程序,因为攻击者总是找到利用漏洞的新技术。此外,对于相同的模式,可能存在大量不同的表示,例如,使用不同的编码
一些方法提出了 运行时预防技术 而不是测试技术。在大多数这些方法中,静态分析用于收集程序可以生成的所有可能形式的SQL语句。在运行时,如果SQL语句的结构与这些收集的表单中的任何一个都不匹配,则该语句为被视为潜在的攻击。 Sekar结合了污点分析和策略来检测运行时的注入攻击。运行时预防方法是测试方法的补充,也可以用作测试的有效预言。
在我们之前的论文中,我们发现使用运行时预防技术为 oracle 提高了 SQLi 测试的检测率。我们还确定了对更复杂的 oracle 的需求,该 oracle 可以推断已发现漏洞的可利用性。在本文中,我们尝试通过增强 oracle 来评估形成的攻击的可执行性来解决这个问题。恶意输入可以成功地规避所有安全机制,但由此产生的攻击可能会产生不可执行的SQL语句,因此不会提供漏洞可利用的证据。
已经提出并广泛研究了变异测试作为评估测试套件充分性的方法,其中测试程序被变异以模拟故障。 Shahriar和Zulkernine 定义了SQLi特定的变异算子来评估测试套件在解决SQLi漏洞方面的有效性。 Fonseca等人也使用突变分析比较商业安全测试工具的有效性。我们在本文中提出的变异算子会改变测试输入,以增加触发漏洞的可能性,而不是测试中的程序,以评估测试套件在发现故障时的有效性。
霍勒等人提出了一种名为 LangFuzz 的方法,通过改变输入代码来测试解释器的安全漏洞,例如内存安全问题。该方法已成功应用于发现 Mozilla JavaScript和 PHP 解释器中的缺陷。但是,我们的方法在各方面都有所不同:
(1)我们针对需要不同变异算子和测试生成技术的SQL注入漏洞; (2)在SQL漏洞的情况下,失败的可观察性比寻找崩溃更具挑战性;
我们需要拦截SUT与其数据库之间的通信,以分析SQL语句的可执行性和漏洞检测。
方法
我们提出了一种自动化技术,即 μ4SQLi,用于检测SQLi漏洞。我们的技术依赖于一组变异操作符,这些操作符操纵输入(合法的)以创建新的测试输入以触发SQLi攻击。
此外,这些运算符可以以不同的方式组合,并且多个运算符可以应用于相同的输入。这使得生成包含新攻击模式的输入成为可能,从而增加了检测漏洞的可能性。
具体而言,我们希望生成可绕过Web应用程序防火墙并生成可执行SQL语句的测试输入。WAF可能会阻止SQLi攻击并阻止易受攻击的Web服务被利用。因此,有效的测试输入需要通过WAF才能到达服务。此外,它们应该导致可执行的SQL语句,否则不太可能出现安全问题,因为数据库引擎会拒绝它们,因此不会泄漏或泄露任何数据。
本节介绍我们提出的用于生成测试数据的变异算子。对于每个变异算子及其定义,提供了一个具体的例子。在一些运算符中,我们还讨论了它们关于输入和先前应用的运算符的前提条件。然后,我们将讨论我们的测试生成技术和我们开发的支持该技术的自动化工具。
变异算子
变异操作符(MO)可以按其用途分为以下三类:行为改变,语法修复和混淆。表1提供了所有变异算子的摘要。
表一:变异运算符摘要分为行为改变,语法修复和混淆运算符。
行为改变
- 向输入添加OR子句
- 在输入中添加AND子句
- 添加分号后跟另外的SQL语句
这类变异操作符会改变输入,目的是在应用程序易受SQLi攻击时更改应用程序的预期行为。例如,突变输入可能导致应用程序返回比预期更多的数据库行,从而将敏感数据暴露给未经授权的用户。我们定义了以下改变行为的运算符:
运算符:MO_or
将 OR x = x 添加到SQL语句的WHERE子句中,其中x是随机数或用单引号或双引号括起来的字符。
示例:
来自原始输入:1; MO_or 产生突变输入:1 OR 1 = 1。因此,如果接受输入的SQL语句预先定义为
"SELECT * FROM table WHERE id = "+ input
则输入将更改语句的逻辑并将其转换如下:
SELECT * FROM table WHERE id = 1 OR 1 = 1
运算符:MO_and
将 AND x = y 添加到SQL语句的WHERE子句中,其中x和y是随机数或用单引号或双引号括起来的单个字符,x不等于y。
示例:
原始输入:1,突变输入:1 AND 1 = 2。
例如,这将转变为预定语句:
"SELECT * FROM table WHERE id ="+ input
变成:
SELECT * FROM table WHERE id = 1 AND 1 = 2
因此,否定原始语句的逻辑。
运算符:MO_semi
在输入中添加分号(;)后跟另外的SQL语句。生成的查询的格式为sql stmt1; sql stmt2,其中sql stmt1是原始SQL语句,sql stmt2是从预定列表中随机选择的SQL语句。
示例:
原始输入:1,变异输入:1; SELECT waitfor(5) FROM dual
这改变了预定语句:
"SELECT * FROM users WHERE id = "+ input
变成:
SELECT * FROM users WHERE id = 1; SELECT waitfor(5) FROM dual
语法修复
- 将括号附加到有效输入
- 向输入添加注释命令( - 或#)
- 为输入添加单引号或双引号
如前所述,SQLi攻击旨在通过注入恶意输入来更改应用程序的行为。因此,恶意输入本身应包含SQL语句片段。与常规有效输入不同,这种类型的输入在与其目标(即预定义的SQL语句)组合时可能导致SQL语法错误。
由于我们提出的方法是一种黑盒技术,因此测试生成器不知道预定义的SQL语句语法,因此生成不会导致语法错误的输入很困难。这类变异操作符会改变输入,目的是在遇到SQL语法错误时尝试修复它们。我们在这个类中定义的变异运算符如下:
运算符:MO_par
在输入的末尾附加右括号。
示例:
原始输入:67,变异输入:67).当用 MO_or MO_cmt 进一步突变输入时,获得的突变输入将是:67)OR 1 = 1 -{}-。让我们考虑一个预定语句:
"SELECT * FROM table WHERE character = CHR("+input+")"
其中函数CHR将整数转换为其对应的Unicode字符。更改的SQL语句:
SELECT * FROM table WHERE character = CHR(67) OR 1 = 1 -)
运算符:MO_cmt
向输入添加SQL注释命令(双短划线和#)。注释命令后面的任何SQL都不会执行。
示例:
原始输入:67,在使用MO_or 和 MO_Par 变异后:67) or 1 = 1。这会将预定义语句
"SELECT * FROM table WHERE character = CHR("+input+")"
更改为组合语句,这会导致语法错误:
SELECT * FROM table WHERE character = CHR(67)OR 1 = 1 )
然后我们应用MO_cmt来获得:67)OR 1 = 1# 最终的语句:
SELECT * FROM table WHERE character = CHR(67) OR 1 = 1#)
应用此突变会导致解析器忽略最后一个括号,从而避免由于括号数不均衡而导致的解析器错误。
运算符:MO_qot
向突变体添加单引号(’)或双引号(“)。
示例:
原始输入:Smith,用MO突变或:Smith OR 1 = 1。这会将预定语句:
"SELECT * FROM table WHERE name ='"+input+"'"
更改为组合语句,这不会导致所需的行为更改,因为将突变体视为字符串文字:
SELECT * FROM table WHERE name ='Smith OR 1 = 1')
在使用MO_qot和 MO_cmt进一步变异后:Smith’ OR 1 = 1#,最终的语句是
SELECT * FROM table WHERE name ='Smith' OR 1 = 1#)
这在语法上是正确的并且改变了逻辑原始声明。
混淆运算符
- 更改空格的编码
- 更改用引号括起来的字符文字的编码
- 将输入的编码更改为HTML实体编码
- 将输入的编码更改为百分比编码
- 重写布尔表达式,同时保留它的真值
- 通过随机化大写和插入注释来混淆SQL关键字
一些应用程序使用输入过滤器(例如,web应用程序防火墙)来防御SQLi攻击。本质上,WAF检查每个输入以检查SQLi攻击中通常使用的可疑字符串模式,例如SQL关键字,并阻止它们。例如,WAF使用黑名单来定义禁止的字符或字符串,以确定输入是否可疑。在实践中,许多安全关键系统受到这些过滤器的保护。例如,处理信用卡数据的软件系统必须使用WAF来防止攻击并符合行业安全标准。混淆变异操作符试图通过将输入变为语义上等效的输入但是以不同的形式来避免过滤。这可能会阻止过滤器识别变异输入中的禁用字符/字符串。我们定义了以下混淆变异运算符:
运算符:MO_wsp
用语义等效字符(+,/**/ 或unicode编码:%20,%09,%0a,%0b,%0c,%0d和%a0)替换空格。
示例:
原始输入:1 OR 1 = 1,突变输入:1 + OR + 1 = 1。这会更改预定义语句:
"SELECT * FROM table WHERE id ="+ input
为:
SELECT * FROM table WHERE id = 1 + OR + 1 = 1
运算符:MO_chr
用等效表示替换用引号(’c’)括起来的字符文字,其中c是任意可打印的ASCII字符。等效表示是:
- 短二进制表示,例如,’a’被替换为b’1100001’。
- 长二进制表示,例如,’a’被替换为二进制’1100001’。
- Unicode表示,例如,’a’被替换为n’a’。
- 十六进制表示,例如,’a’被替换为x’61’。
示例:
原始输入:1,用 MO_or:1 OR’a’=’a’,进一步用 MO_chr突变:1 or ‘a’= x’61’。这改变了预定语句:
"SELECT * FROM table WHERE id ="+ input
为:
SELECT * FROM table WHERE id = 1 OR'a'= x'61'。
运算符:MO_html
使用HTML实体编码更改突变体的编码。在HTML实体编码中,字符可以用两种方式编码:
(a)形式为&#N的数字字符引用,其中N是十进制或十六进制表示中使用的字符集中字符的代码位置; (b)形式为&SymbolicName的字符实体引用。例如,“是单引号字符(’)的编码。
示例:
原始输入:1,用 MO_or :1 OR’a’=’a’,进一步用 MO_html 突变:1 or “a”: = “a” 这将转换预定语句:
"SELECT * FROM table WHERE id =" + input
为:
SELECT * FROM table WHERE id = 1 OR "a" = "a"。
运算符:MO_per
使用百分比编码更改突变体的编码:%HH,其中HH是指向字符ASCII码的两位十六进制值。例如,单引号字符(’)编码为%27。
示例:
原始输入:1,用 MO_or:1 OR’a’=’a’,进一步用MO_Per进行突变:1 OR%20’a’=’a’。
这将转换预定语句:
"SELECT * FROM table WHERE id ="+ input
为:
SELECT table WHERE id = 1 OR%20'a'='a'
运算符:MO_bool
用等效的布尔表达式替换布尔表达式。例如,布尔表达式1 = 1在MO中使用或者可以被混淆为not false = !!1。两个表达式都评估为true,在混淆之后保持突变体的相同语义。
示例:
原始输入:1,用MO_or:1 OR 1 = 1,进一步用 MO_bool突变:1 OR not false = !! 1
这将预定义语句
"SELECT * FROM table WHERE id ="+ input
为:
SELECT * FROM table WHERE id = 1 OR not false = !! 1
运算符:MO keyw
使用不同的技术对SQL关键字和运算符进行混淆:随机更改某些字母的大小写,在关键字中间添加注释或使用替代表示替换关键字。大多数SQL解析器都不区分大小写,例如关键字 select,SELECT或SeLeCt都是有效的。一些解析器接受在关键字中间包含注释的关键字(例如sel / comment here / ect.)。最后,一些关键字具有替代形式,例如OR也可以表示为 ||。
示例:
原始输入:1,用MO_or:1 OR 1 = 1,MO键的进一步突变:1 || 1 = 1。这会更改预定义语句:
"SELECT * FROM table WHERE id ="+input
为:
SELECT * FROM table WHERE id = 1 || 1 = 1。
测试生成
可以将单个或多个不同类型的变异算子应用于单个输入参数以生成所需输入。后一种情况旨在检测细微的漏洞,这些漏洞只能通过组合多个变异算子生成的输入来触发。例如,考虑一个通过搜索可以使用其中一个行为改变运算符生成的已知攻击模式来输入输入的应用程序。要形成成功的攻击,必须首先应用行为改变运算符,然后应用一个或多个混淆运算符。
每个突变链都必须从一个有效的测试用例开始,这样可以满足被测应用程序的输入验证。从有效的测试用例开始,可以确保避免生成由于输入或不太可能随机生成的复杂输入结构之间的依赖性而被应用程序直接拒绝的测试用例。
此外,有效的测试用例具有更有可能满足输入验证并到达应用程序的关键部分(例如SQL查询)的好处。例如,如果某个应用程序需要信用卡号码以及我们希望改变的其他输入,则信用卡号码必须遵循一种良好的格式;否则测试用例会立即被拒绝。使用所提出的方法,可以重用现有功能测试套件中的有效测试用例,或者,如果不存在此类测试套件,则可以使用SoapUI4和类似工具手动创建有效的测试用例。
算法1正式定义了测试生成算法:从有效的测试用例开始,每个输入都被预定的次数变异。apply_MO(第4行)函数随机将一个或多个变异运算符应用于当前输入。该函数使用一种简单的语法,该语法定义了组合运算符的不同合法方法,并确保应用运算符的所有前提条件都得到满足。然后使用更新的测试用例TC0调用被测操作。如果是oracle存在漏洞,则会检查因调用而发出的所有SQL语句。如果可执行SQL语句的百分比(即,不包含语法错误的语句)高于预定阈值P,则将输入报告为易受攻击并保存测试用例以帮助测试工程师进行调试并解决漏洞(第5-8行在我们的实验中,我们选择P = 100%,这意味着所有触发的SQL语句都必须是可执行的。
算法1测试生成算法:
输入
TC:测试用例:ArrayOf(input)
OP:要测试的Web服务操作输出
TS:针对SQLi漏洞的测试套件
V:易受攻击的输入集
下图显示了由我们的方法生成的SOAP消息(测试用例)的示例。这里参数minPrice,maxPrice和start的输入值与原始测试用例保持一致,而参数country的输入值已经变异以包含SQLi攻击。
测试oracle
当恶意输入发送到目标系统时,如果成功,可能会导致系统出现异常。在大多数情况下,异常行为的表现可能是从目标系统返回的结果(例如,显示非预期内容的网页)或周围环境(例如,崩溃,对操作系统的非法调用或对数据的非预期访问)提供服务。在我们的实验中,因为我们专注于SQL注入,所以我们部署了一个数据库代理,它拦截目标系统与其数据库之间的通信,以识别输入是否有潜在危害。例如,我们可以将 GreenSQL 用于此目的。之前的一项将 GreenSQL 与类似工具进行比较的研究发现,它在检测SQL注入攻击方面是最有效的。
在我们之前的工作中已经讨论了使用数据库代理作为oracle的细节。通常,使用正常的数据库访问来部署和训练数据库代理。这些训练数据是系统的常规使用或现有功能测试套件的执行的结果。基于训练数据,代理学习合法SQL语句的规则模式。一旦经过培训,代理将继续观察系统与其数据库之间的流量,并在识别可疑数据库查询时发出警报。
每个警报对应一个数据库SQL语句,一个测试用例可能导致多个SQL语句,从而导致多个警报。为避免因训练不完整而导致误报,可能需要手动检查以验证所有已标记的 SQL语句实际上指向了系统中的漏洞。
工具
提出的变异方法已经实现为 Java 工具,称为Xavier6。它可用于测试基于SOAP的Web服务的SQLi漏洞。下图显示了该工具的关键组件(测试生成器和监视器)以及它在实践中的使用方式。测试生成器将要测试的Web服务的WSDL文件作为输入,并为每个必须测试的Web服务操作提供示例测试用例。
这样的样本测试用例可以通过专业工具(如SoapUI)或现有方法轻松生成。然后,该工具检查示例测试用例以查找操作的所有输入参数,并使用我们的突变方法生成的SQLi攻击替换每个参数,一次一个。修改过的测试用例将被发送到被测试的Web服务(图中的SUT)。在某些设置中,可能会在测试生成器和SUT之间部署Web应用程序防火墙(WAF组件)。 oracle组件(gure中的DB代理组件)观察SUT与其数据库之间的交互以检测恶意SQL语句。
最后,Xavier的Monitor组件不断查询 oracle 组件,以了解生成的输入是否显示SQLi漏洞。在Xavier中,我们集成了GreenSQL来拦截SQL语句。数据库代理使用学习方法来检测SQLi漏洞。因此,必须在学习阶段对其进行培训,以识别合法的SQL语句。在检测阶段,代理将所有先前未学习的截获语句视为SQLi攻击
如果它形成语法正确的SQL,则会进一步分析每个可疑的恶意语句。攻击者只能利用SQLi漏洞,如果他能够以产生的SQL语句没有语法错误的方式注入恶意输入。否则,攻击者无法达到他的目标,例如,获取/修改数据或改变应用程序的控制
如果没有执行恶意声明。 MySQL-Proxy7工具用于监视SQL语句是否已执行或执行期间是否存在错误。
结论
我们在本文中介绍了一种针对SQL注入漏洞的自动变异技术,该工具由一个工具支持,该工具专注于改变Web服务参数的输入值。该技术利用一组变异算子,能够
(1)生成具有修改服务行为的高可能性的输入,
(2)纠正输入以消除由于突变导致的可能的语法错误
(3)混淆攻击以增加他们通过防火墙进行攻击的机会。
我们技术的最终目标是生成随机输入,以通过可执行的SQL语句检测SQL漏洞,通过防火墙,并过度暴露或破坏数据库中的数据。我们的实验结果表明,我们的技术和工具比实践状态标准攻击模式表现更好,并且检测SQL注入漏洞的概率很高,即使存在防火墙,并且具有合理数量的测试每个服务中每个输入参数的大小写执行。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
算法导论(原书第2版)
[美] Thomas H.Cormen、Charles E.Leiserson、Ronald L.Rivest、Clifford Stein / 潘金贵 等 / 机械工业出版社 / 2006-9 / 85.00元
这本书深入浅出,全面地介绍了计算机算法。对每一个算法的分析既易于理解又十分有趣,并保持了数学严谨性。本书的设计目标全面,适用于多种用途。涵盖的内容有:算法在计算中的作用,概率分析和随机算法的介绍。书中专门讨论了线性规划,介绍了动态规划的两个应用,随机化和线性规划技术的近似算法等,还有有关递归求解、快速排序中用到的划分方法与期望线性时间顺序统计算法,以及对贪心算法元素的讨论。此书还介绍了对强连通子图......一起来看看 《算法导论(原书第2版)》 这本书的介绍吧!