<< web_security

Web

页面中的常用数据隐藏手段:

2. SQL Injection

2.1 基础注入方式

常规登陆的SQL语句写法

SELECT * FROM database WHERE username='username' and password = 'password'; 

这里的usernamepassword是用户输入数据.

构造password' or '1' = '1使得原SQL查询语句结构变成

password = '' or '1' = '1'; 

注意到在构造出的' or '1' = '1中,最前面的单引号用于封闭查询语句中前面的单引号,之后的语句用于构造一个恒等式,最后的单引号由查询语句提供。

对于这种简单的注入有很多种构造注入语句的方法,上面是比较好理解的一类,实际上可以写成更简单的形式:' or '1, 那么构造后的语句成为

password = '' or '1';

这样做可行的原理是php字符串强制转化为bool型时的转化规则:(特别要注意的是php类型转换规则非常特立独行)即空字符串和’0’为false而其他任何字符串为true. 所以这里的’1’会被强制类型转换为true, 和上面的表达式的效果一样. 为什么这个简化如此重要呢?因为并不是所有情况下我们都能够完全控制注入方式,例如在MD5注入中,//TODO

我们发现上面的两种注入方式都需要用到or语句,但是如果or被过滤掉了怎么办呢?还有一类构造要求同时控制usernamepassword, 同时输入1'='0'='. 这里涉及的具体php和sql的执行机制暂时不是非常明确,有待测试,但是实践上表明这样操作的确是可行的. // TODO

$sql = "username='1'='0' and password='1'='0'"

$sql = 'username='=' and password='=''

解决方案:禁止用户输入可能引起注入的危险字符', or等等。

2.2 报错注入

报错注入故意构造某些错误的语句,诱导错误信息产生,从而得到关于后台的某些信息。

还是考虑通常的登陆入口

SELECT * FROM database WHERE username='username' and password = 'password'; 

假设我们强行在其中插入某些可执行语句并故意构造错误,就有可能使得错误信息在前端反馈出来,常见的有extractvalue语句和updatexml等.

例如如果我们构造username = extractvalue(1, concat(0x5c,(select database())))

解释一下这里的函数结构:外层的extractvalue是查询xml信息的语句,第一个参数是目标xml文档,第二个参数是xml路径,我们在这里需要利用的性质是:当路径的格式存在错误时,extractvalue函数将会在前端dump出错误信息,其中包含了所写的错误路径。那么现在有两个问题:如何在其中写入想要的信息,以及使其是错误的路径呢?

为了获取想要的信息我们需要构造sql语句,例如这里特殊的select database()返回当前查询的数据库名,这就意味着通过这种方式我们把语句中的database信息给提取了出来(事实上只要没有过滤,这个地方可以写任意的sql语句,从而提取任何想要的信息);concat的作用是强行加入一个不应该出现在路径名中的字符(这里是0x5c也就是\, 通常也会使用0x7e也就是~),从而保证路径格式是有问题的。

2.3 过滤绕过

server端为了避(chu)免(ti)sql注入常常会使用某些方式过滤掉某些敏感字符串(涉及到过滤时web题中时常会给出被处理过的字符串是什么样的,如果没有的话就需要自己看报错信息判断了),这时候我们就需要根据被过滤掉的字符来采取一定的措施去规避。以下讨论均假设原先需要构造的语句写作

SELECT flag FROM flag

针对关键字被过滤的绕过

针对空格过滤的绕过