開頭: 廢話不多說,直接進主題。
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這種東西