php web開發安全之csrf攻擊的簡單演示和防範(一)

来源:http://www.cnblogs.com/yangtoude/archive/2017/05/06/php-web-csrf.html
-Advertisement-
Play Games

csrf攻擊,即cross site request forgery跨站(功能變數名稱)請求偽造,這裡的forgery就是偽造的意思。網上有很多關於csrf的介紹,比如一位前輩的文章淺談CSRF攻擊方式,參考這篇文章簡單解釋下:csrf 攻擊能夠實現依賴於這樣一個簡單的事實:我們在用瀏覽器瀏覽網頁時通常會打 ...


csrf攻擊,即cross site request forgery跨站(功能變數名稱)請求偽造,這裡的forgery就是偽造的意思。網上有很多關於csrf的介紹,比如一位前輩的文章淺談CSRF攻擊方式,參考這篇文章簡單解釋下:csrf 攻擊能夠實現依賴於這樣一個簡單的事實:我們在用瀏覽器瀏覽網頁時通常會打開好幾個瀏覽器標簽(或視窗),假如我們登錄了一個站點A,站點A如果是通過cookie來跟蹤用戶的會話,那麼在用戶登錄了站點A之後,站點A就會在用戶的客戶端設置cookie,假如站點A有一個頁面siteA-page.php(url資源)被站點B知道了url地址,而這個頁面的地址以某種方式被嵌入到了B站點的一個頁面siteB-page.php中,如果這時用戶在保持A站點會話的同時打開了B站點的siteB-page.php,那麼只要siteB-page.php頁面可以觸發這個url地址(請求A站點的url資源)就實現了csrf攻擊。

上面的解釋很拗口,下麵舉個簡單的例子來演示下。

1,背景和正常的請求流程

A站點功能變數名稱為html5.yang.com,它有一個/get-update.php?uid=uid&username=username地址,可以看到這個地址可以通過get方法來傳遞一些參數,假如這個頁面的邏輯是:它通過判斷uid是否合法來更新username,這個頁面腳本如下:

 

 1 <?php
 2 // 這裡簡便起見, 從data.json中取出數據代替請求資料庫
 3 $str = file_get_contents('data.json');
 4 $data = json_decode($str, true);
 5 
 6 // 檢查cookie和請求更改的uid, 實際應檢查資料庫中的用戶是否存在
 7 empty($_COOKIE['uid']) ||empty($_GET['uid']) || $_GET['uid'] != $data['id'] ? die('非法用戶') : '';
 8 // 檢查username參數
 9 $data['username'] = empty($_GET['username']) ? die('用戶名不能為空') : $_GET['username'];
10 
11 // 更新數據
12 $data['username'] = $_GET['username'];
13 if(file_put_contents('data.json', json_encode($data))) {
14     echo "用戶名已更改為{$data['username']}<br>";
15 } else {
16     die('更新失敗');
17 }

 

正常情況下這個頁面的鏈接是放在站點A下麵的,比如A站點的csrfdemo.php頁面,用戶登錄站點A以後可以通過點擊這個鏈接來發送請求,比如站點A有一個頁面腳本,包含了這個鏈接:

 1 <?php
 2 // 這裡用一個data.json文件保存用戶數據,模擬資料庫中的數據
 3 // 先初始化data.json中的數據為{"id":101,"username":"jack"}, 註意這句只讓它執行一次, 然後把它註釋掉
 4 // file_put_contents('data.json','{"id":101,"username":"jack"}');
 5 
 6 $data = json_decode(file_get_contents('data.json'), true);
 7 
 8 // 這裡為了簡便, 省略了用戶身份驗證的過程
 9 if ($data['username']) {
10     // 設置cookie
11     setcookie('uid', $data['id'], 0);
12     echo "登錄成功, {$data['username']}<br>";
13 }
14 ?>
15 
16  <a href="http://html5.yang.com/csrfdemo/get-update.php?uid=101&username=json">
17     更新用戶名為json
18  </a>

載入這個頁面如下:

用點擊頁面中的鏈接來到get-update.php頁面:

上面是正常的請求流程,下麵來看B站點是如何實現csrf攻擊的。

2,csrf攻擊的最簡單實現

B站點功能變數名稱為test.yang.com,它有一個頁面csrf.php,只要用戶在維持A站點會話的同時打開了這個頁面,那麼B站點就可以實現csrf攻擊。至於為什麼會打開......,其實這種情景在我們瀏覽網頁時是很常見的,比如我在寫這篇博客時,寫著寫著感覺對csrf某個地方不懂,然後就百度了,結果百度出來好多結果,假如說有個網站叫csrf百科知識,這個網站對csrf介紹的非常詳細、非常權威,那麼我很可能會點進去看,但是這個網站其實是個釣魚網站,它在某個訪問頻率很高的頁面中嵌入了我博客編輯頁面的url地址,那麼它就可以實現對我博客的csrf攻擊。好了,言歸正傳,下麵來看下csrf.php腳本代碼:

<?php
?>
<img src="http://html5.yang.com/csrfdemo/get-update.php?uid=101&username=jsonp">

可以看到上面的代碼沒有php代碼,只有一個img標簽,img標簽的src就是A站點的那個更新用戶名的鏈接,只不過把username改為了jsonp,訪問站點B的csrf.php這個頁面:

下麵再來訪問下A站點的csrfdemo.php頁面:

可以看到用戶名被修改為了jsonp。

簡單分析下:B站點的這個csrf.php利用了html中的img標簽,我們都知道img標簽有個src屬性,屬性值指向需要載入的圖片地址,當頁面載入時,載入圖片就相當於向src指向的地址發起http請求,只要把圖片的地址修改為某個腳本地址,這樣自然就實現了最簡單的csrf攻擊。如此說來,其實csrf很容易實現,只不過大家都是“正人君子”,誰沒事會閑著去做這種“下三濫”的事情。但是害人之心不可有,防人之心不可無。下麵看下如何簡單防範這種最簡單的csrf攻擊。

3,簡單防範措施

其實防範措施也比較簡單,A站點可以在get-update.php腳本中判斷請求頭的來源,如果來源不是A站點就可以截斷請求,下麵在get-update.php增加些代碼: 

 1 <?php
 2 // 檢查上一頁面是否為當前站點下的頁面
 3 if (!empty($_SERVER['HTTP_REFERER'])) {
 4     if (parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST) != 'html5.yang.com') {
 5         // 可以設置http錯誤碼或者指向一個無害的url地址
 6         //header('HTTP/1.1 404 not found');
 7         //header('HTTP/1.1 403 forbiden');
 8         header('Location: http://html5.yang.com/favicon.ico');
 9         // 這裡需要註意一定要exit(), 否則腳本會接著執行
10         exit();
11     }
12  }
13 
14 $str = file_get_contents('data.json');
15 // 代碼省略

但是,這樣就萬事大吉了嗎,如果http請求頭被偽造了呢?A站點升級了防禦,B站點同時也可以升級攻擊,通過curl請求來實現csrf,修改B站點的csrf.php代碼如下:

<?php
$url = 'http://html5.yang.com/csrfdemo/get-update.php?uid=101&username=jsonp';
$refer = 'http://html5.yang.com/';
// curl方法發起csrf攻擊
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
// 設置Referer curl_setopt($ch, CURLOPT_REFERER, $refer);
// 這裡需要攜帶上cookie, 因為A站點get-update.php對cooke進行了判斷 curl_setopt($ch, CURLOPT_COOKIE, 'uid=101'); curl_exec($ch); curl_close($ch); ?> <img src="http://html5.yang.com/csrfdemo/get-update.php?uid=101&username=jsonp">

這樣同樣可以實現csrf攻擊的目的。那麼就沒有比較好的防範方法了嗎?

4,小結

下麵我們回到問題的開始,站點A通過cookie來跟蹤用戶會話,在cookie中存放了重要的用戶信息uid,get-update.php腳本通過判斷用戶的cookie正確與否來決定是否更改用戶信息,看來靠cookie來跟蹤會話並控制業務邏輯是不太安全的,還有最嚴重的一點:get-update.php通過get請求來修改用戶信息,這個是大忌。所以站點A可以接著升級防禦:用session來代替cookie來跟蹤用戶會話信息,將修改用戶信息的邏輯重寫,只允許用post方法來請求用戶信息。站點B同樣可以升級攻擊:curl可以構造post請求,劫持session等等,不過這些我還沒研究過,後續再說吧。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • MVC HtmlHelper擴展類(PagingHelper) 後臺Controller代碼 前臺頁面代碼 最終效果圖: 作者:長毛象 微博:http://weibo.com/5567742196/info 博客:http://www.cnblogs.com/xiangyisheng/ 本文版權歸作 ...
  • 練習使用angularjs實現一個select下拉列表: <div ng-app="selectApp" ng-controller="selectController"> <select ng-model="mySelect" ng-options="sd for sd in selectData ...
  • https://developer.xamarin.com/samples/xamarin-forms/Navigation/MasterDetailPage/ https://blog.xamarin.com/material-design-for-your-xamarin-forms-andro... ...
  • /// <summary> /// 加密 /// </summary> /// <param name="Text"></param> /// <returns></returns> public static string Encrypt(string Text) { return Encrypt ...
  • C 訪問修飾符 分類 C 訪問修飾符一共有五種,分別為private, internal, protected, protected internal, public。 它們都可以用來修飾類中的成員,如欄位,屬性,方法,事件等。對於修飾class,enum,struct,嵌套類,及其各自預設修飾符的 ...
  • 重放攻擊 重放攻擊是指黑客通過抓包的方式,得到客戶端的請求數據及請求連接,重覆的向伺服器發送請求的行為。 比如你有一個 “購買” 的操作,當你點擊購買按鈕時,向伺服器發送購買的請求。而這時黑客對你的請求進行了抓包,得到了你的傳輸數據。 因為你填寫的都是真實有效的數據,是可以購買成功的,因此他不用做任 ...
  • .NET Core 2.0預覽版及.NET Standard 2.0 Preview 這個月也就要發佈了。 具體相關信息可以查看之前的文章 ".NET Core 2.0及.NET Standard 2.0" 。 今天來實際體驗.NET Core 2.0,正式版發佈還需要一段時間。 .NET Core ...
  • 詳情見:cookie與session的區別與聯繫 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...