开头: 废话不多说,直接进主题。
0x01 CSRF介绍:
CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本XSS,但它与XSS非常不同,XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。
0x02 CSRF环境搭建:
环境搭建嘛,肯定要PHP的咯,不过别担心,这不有俺在嘛 我给你尝尝代码的味道。
CSRF测试代码:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
<?phpheader( "Content-Type:text/html;charset=utf-8" ); if (isset( $_POST [ 'sub' ])){ $username = $_POST [ 'username' ]; $password = $_POST [ 'password' ]; $conn = mysql_connect( "localhost" , "root" , "root" ); $db =mysql_select_db( "test" ); $query = mysql_query( "SET NAMES 'gbk'" ); $sql = "INSERT INTO `adminsql` (`id` ,`username` ,`password`)VALUES (13 , '$username' , '$password')" ; $row =mysql_query( $sql ); //执行sql插入语句 $sql = "SELECT * FROM adminsql" ; if ( $row =mysql_query( $sql )){ while ( $rows = mysql_fetch_array( $row )){ echo "user:{$rows['username']}-----pass:{$rows['password']}" . "<br/>" ; } } } ?> <!DOCTYPE html> <html> <head> <title>CSRF利用场所</title> </head> <body> <b><h2>CSRF测试环境</h2></b> <form action= "" method= "post" > <b>user:<input type= "text" name= "username" /></b> <b>pass:<input type= "password" name= "password" /></b> <input type= "submit" value= "Ok" name= "sub" /> </form> </body> </html> |
0x03 上层代码解释:
代码:<?php ?> 开始和结束 没一门编程语言都有
代码:header("Content-Type:text/html;charset=utf-8"); 将页面的编码设置为UTF-8
代码:代码
1
2
3
|
if (isset( $_POST [ 'sub' ])){ $username = $_POST [ 'username' ]; $password = $_POST [ 'password' ]; |
解释:
代码:
没错 又到了这里 看过我的细说SQL注入的就知道 我解释过一遍了 没看过那篇帖子的也没事哈 我再解释一遍。
1
2
3
4
5
6
7
8
9
|
$conn = mysql_connect( "localhost" , "root" , "root" ); //连接数据库 mysql_connect("HOST你的网站","你数据库账号","你数据库密码"); 赋值给$conn变量 $db =mysql_select_db( "test" ); //mysql_select_db("test"); mysql_select_db()函数是设置数据库, 第一个参数是你数据库名 注意: 是数据库名 不是表名! $query = mysql_query( "SET NAMES 'gbk'" ); //mysql_query()函数是执行一条sql语句 他这里是设置数据库字符编码为gbk $sql = "INSERT INTO `adminsql` (`id` ,`username` ,`password`)VALUES (13 , '$username' , '$password')" ; //SQL语句 INSERT INTO(插入) INSERT INTO 后 面的反引号是你的数据表名 就是数据库test下的表 |
再后面的括号(`id`,`username`,`password`); 这里是数据表里面的值 我有三个字段表 分别是id、usernam、 password这三个
后面的VALUES (13 , '$username' , '$password')"; //第一个参数是id 我没设置那个自增长ID(详 `` 情:http://jingyan.baidu.com/article/fcb5aff7b3a025edaa4a7130.html)
在后面的就懂了吧 就是我前面吧HTML表单的值赋值给那个变量:
1
2
|
$username = $_POST [ 'username' ]; $password = $_POST [ 'password' ]; |
懂俺意思了吧 嘻嘻 就是啊 你单击提交的数据 会插入到数据库的深处
代码:
1
2
3
4
5
|
$sql = "SELECT * FROM adminsql" ; //SELECT(查询) from要查询的表 adminsql if ( $row =mysql_query( $sql )){ //判断sql语句是否执行了 while ( $rows = mysql_fetch_array( $row )){ //执行就把数据库里面的数据表里面的所有字段表用while循环取出来 echo "user:{$rows['username']}-----pass:{$rows['password']}" . "<br/>" ; //echo 输出到页面上 前面的mysql_fetch_array()函数是一行一行获取 值 他吧值赋给了$rows变量 这个函数获取到的值全是array数组 所以要 $rows['username']; 这样取值 输出 } |
我把数据库发给你们吧
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
|
[ table =98%,none] [tr=none ][td][align= right ][align= right ][ size =1em]1[/align] [align= right ][ size =1em]2[/align] [align= right ][ size =1em]3[/align] [align= right ][ size =1em]4[/align] [align= right ][ size =1em]5[/align] [align= right ][ size =1em]6[/align] [align= right ][ size =1em]7[/align] [align= right ][ size =1em]8[/align] [align= right ][ size =1em]9[/align] [align= right ][ size =1em]10[/align] [align= right ][ size =1em]11[/align] [align= right ][ size =1em]12[/align] [align= right ][ size =1em]13[/align] [align= right ][ size =1em]14[/align] [align= right ][ size =1em]15[/align] [align= right ][ size =1em]16[/align] [align= right ][ size =1em]17[/align] [align= right ][ size =1em]18[/align] [align= right ][ size =1em]19[/align] [align= right ][ size =1em]20[/align] [align= right ][ size =1em]21[/align] [align= right ][ size =1em]22[/align] [align= right ][ size =1em]23[/align] [align= right ][ size =1em]24[/align] [align= right ][ size =1em]25[/align] [align= right ][ size =1em]26[/align] [align= right ][ size =1em]27[/align] [align= right ][ size =1em]28[/align] [align= right ][ size =1em]29[/align] [align= right ][ size =1em]30[/align] [align= right ][ size =1em]31[/align] [align= right ][ size =1em]32[/align] [align= right ][ size =1em]33[/align] [align= right ][ size =1em]34[/align] [align= right ][ size =1em]35[/align] [align= right ][ size =1em]36[/align] [align= right ][ size =1em]37[/align] [align= right ][ size =1em]38[/align] [align= right ][ size =1em]39[/align] [align= right ][ size =1em]40[/align] [align= right ][ size =1em]41[/align] [align= right ][ size =1em]42[/align] [align= right ][ size =1em]43[/align] [align= right ][ size =1em]44[/align] [align= right ][ size =1em]45[/align] [align= right ][ size =1em]46[/align] [align= right ][ size =1em]47[/align] [align= right ][ size =1em]48[/align] [/align][/td][td][align= right ][ size =1em][ size =1em] -- phpMyAdmin SQL Dump [ size =1em] -- version phpStudy 2014 [ size =1em] -- [ size =1em] -- 主机: localhost [ size =1em] -- 生成日期: 2017 年 06 月 23 日 21:14 [ size =1em] -- 服务器版本: 5.5.53 [ size =1em] -- PHP 版本: 5.3.29 [ size =1em] SET SQL_MODE= "NO_AUTO_VALUE_ON_ZERO" ; [ size =1em] SET time_zone = "+00:00" ; [ size =1em]/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; [ size =1em]/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; [ size =1em]/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; [ size =1em]/*!40101 SET NAMES utf8 */; [ size =1em] -- [ size =1em] -- 数据库: `test` [ size =1em] -- [ size =1em] -- -------------------------------------------------------- [ size =1em] -- [ size =1em] -- 表的结构 `adminsql` [ size =1em] -- [ size =1em] CREATE TABLE IF NOT EXISTS `adminsql` ( [ size =1em] `id` int (11) NOT NULL , [ size =1em] `username` varchar (32) NOT NULL , [ size =1em] ` password ` varchar (32) NOT NULL [ size =1em]) ENGINE=InnoDB DEFAULT CHARSET=utf8; [ size =1em] -- [ size =1em] -- 转存表中的数据 `adminsql` [ size =1em] -- [ size =1em] INSERT INTO `adminsql` (`id`, `username`, ` password `) VALUES [ size =1em](1, 'aaaa' , '' ), [ size =1em](1, 'aaaa' , '' ), [ size =1em](1, 'aaaa' , 'xss' ), [ size =1em](1, 'aaaa' , 'xss' ), [ size =1em](1, 'csrf' , 'csrf' ); [ size =1em]/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; [ size =1em]/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; [ size =1em]/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; [/align][/td][/tr] [/ table ] |
在mysql的SQL哪里 插入这些代码 然后执行即可
0x04 进入正题:
好了 有了环境 我们就更方便测试了 访问代码页:
构建环境:
ok 假设我现在是一枚网站管理员 现在localhost是我网站 localhost/php/xss/fanshexing.php 是我后台 现在我的同伴他说想帮我管理我的后台 我就把他创建了一个用户 用户名为(escape) 密码为(admin888)
点击ok 提交数据
OK 现在admin是我的号 而escape是我同伴的号 不过在此之前有一个黑客发现我的后台没有用token令牌 存在csrf漏洞 于是他就构造了一个html的文件
代码如下:
01
02
03
04
05
06
07
08
09
10
11
12
|
< script > function s(){ document.getElementById('fuck').submit(); //这里是javascript的代码(详情:[url]http://www.jquerycn.cn/a_10756[/url]) } </ script > < body onload = s ()> < input type = 'hidden' name = "username" value = "heike" > < input type = 'hidden' name = "password" value = "888888" > < input type = 'hidden' name = "sub" value = "123456" > </ form > </ body > |
构建环境:
攻击者视角:好 我现在的身份是一枚"非法用户" 我现在要去拿这个构造的页面发给笨蛋管理员 嘿嘿
假设现在我发送QQ邮件给管理员发了个文件 就是我构造的页面 发给了他
如果管理员打开了 就会自动提交
<input type='hidden' name="username" value="heike"> 用户
<input type='hidden' name="password" value="888888"> 密码
OK 到了管理员视角:
管理员:嘿 escape伙伴 快来瞧瞧 是一个html的文件 是一位叫构造者发给我们的 我们瞧瞧
escape:OK瞧瞧看
点击。。。
当然 这些用户是我从数据库取出来的 在项目中可不会这样 所以说 笨蛋管理员还不知道 我已经在他的后台构造了一个我的用户
0x05 如何构造一个添加管理员的页面?(没安装burpsuite请看:https://bbs.ichunqiu.com/forum.p ... mp;page=1#pid284388):
前面的构造页面太多的代码了 难道我需要全部背下来吗??当然不需要 下来我来教大家怎么构造一个CSRF的添加管理员页面
1、打开burpsuite神器(https://bbs.ichunqiu.com/forum.p ... mp;page=1#pid284388)
OK 打开后要代理服务端才能收到请求的数据
2、代理服务器
在burpsuite的主页面中的proxy里的Options
在浏览器这里设置代理服务器(详情:http://jingyan.baidu.com/article/f0e83a25da4d8222e591019d.html)
我用的是2345浏览器在工具哪里可以设置代理服务器
点击进入Internet后 点击连接
局域网设置
在我下面图画箭头的地方打钩
点击确定即可
3、开始构造
打开我们的管理员后台
查看后台现在有几个管理用户:
现在还有3个管理员
环境构造:
ok 现在我是一名"非法用户" 我发现了这个网站的后台登录地址 而且发现了木有存在token验证
我首先打开了他们的管理员登录的人口地方
user:test pass:test 开启浏览器服务器代理
开启burpsuite
代理好了服务器 开启了burpsuite 就点击ok
OK 接受到了 右击burpsuite界面 Engagement tooles 里面的 Generrate CSRFPoC
可以看到 他已经自己给你构造了一个页面:
复制代码 创建一个HTML文件
如果想修改账号 就吧 <input type="hidden" name="username" value="test" /> value="账号在这里 可以随便修改其他的 这里我就修改为test1"
OK了 Ctrl+s 就可以保存了
查询一下 现在有用户:
有三个用户 我们把这个文件发给管理员
环境构造:我现在又是管理员了 我打开了这个文件 并且在我没有退出登录和销毁cookie的情况下 打开了这个文件
件
点击提交
添加成功:
根据以上流程 我写下了一个具体的流程图:
到了这里 恐怕有很多人会问我 怎么去看这些漏洞是否存在?
答:你要是单单只是看看漏洞是否存在 可以看cookie或者post包中有没有token这种东西 如果存在token那就不能利用了 token就是个验证的玩意 只有服务器和后台有 所以你burpsuite是搜不到的
0x06 CSRF的检测以及防御:CSRF出现的地方通常在权限控制的地方 如会员中心、后台管理、用户注册、发布帖子、用户后台处、交易管理处这几个地方
防御就是开启token验证 token验证能干什么?你开启了token验证后 客服端请求的值必须和服务端的值相同 不能进行修改 这样你burpsuite就不能在改了 就彻底防御了这个漏洞
也可以看看cookie或者post包中有没有token这种东西