最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

PHP開發(fā)中csrf攻擊的簡單演示和防范

 更新時(shí)間:2017年05月07日 16:33:40   作者:yangtoude  
CSRF的全名為Cross-site request forgery,它的中文名為 跨站請求偽造(偽造跨站請求【這樣讀順口一點(diǎn)】)CSRF是一種夾持用戶在已經(jīng)登陸的web應(yīng)用程序上執(zhí)行非本意的操作的攻擊方式。相比于XSS,CSRF是利用了系統(tǒng)對頁面瀏覽器的信任,XSS則利用了系統(tǒng)對用戶的信任。

csrf攻擊,即cross site request forgery跨站(域名)請求偽造,這里的forgery就是偽造的意思。網(wǎng)上有很多關(guān)于csrf的介紹,比如一位前輩的文章CSRF的攻擊方式詳解,參考這篇文章簡單解釋下:csrf 攻擊能夠?qū)崿F(xiàn)依賴于這樣一個(gè)簡單的事實(shí):我們在用瀏覽器瀏覽網(wǎng)頁時(shí)通常會打開好幾個(gè)瀏覽器標(biāo)簽(或窗口),假如我們登錄了一個(gè)站點(diǎn)A,站點(diǎn)A如果是通過cookie來跟蹤用戶的會話,那么在用戶登錄了站點(diǎn)A之后,站點(diǎn)A就會在用戶的客戶端設(shè)置cookie,假如站點(diǎn)A有一個(gè)頁面siteA-page.php(url資源)被站點(diǎn)B知道了url地址,而這個(gè)頁面的地址以某種方式被嵌入到了B站點(diǎn)的一個(gè)頁面siteB-page.php中,如果這時(shí)用戶在保持A站點(diǎn)會話的同時(shí)打開了B站點(diǎn)的siteB-page.php,那么只要siteB-page.php頁面可以觸發(fā)這個(gè)url地址(請求A站點(diǎn)的url資源)就實(shí)現(xiàn)了csrf攻擊。

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

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

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

<?php
// 這里簡便起見, 從data.json中取出數(shù)據(jù)代替請求數(shù)據(jù)庫
$str = file_get_contents('data.json');
$data = json_decode($str, true);

// 檢查cookie和請求更改的uid, 實(shí)際應(yīng)檢查數(shù)據(jù)庫中的用戶是否存在
empty($_COOKIE['uid']) ||empty($_GET['uid']) || $_GET['uid'] != $data['id'] ? die('非法用戶') : '';
// 檢查username參數(shù)
$data['username'] = empty($_GET['username']) ? die('用戶名不能為空') : $_GET['username'];

// 更新數(shù)據(jù)
$data['username'] = $_GET['username'];
if(file_put_contents('data.json', json_encode($data))) {
  echo "用戶名已更改為{$data['username']}<br>";
} else {
  die('更新失敗');
}

正常情況下這個(gè)頁面的鏈接是放在站點(diǎn)A下面的,比如A站點(diǎn)的csrfdemo.php頁面,用戶登錄站點(diǎn)A以后可以通過點(diǎn)擊這個(gè)鏈接來發(fā)送請求,比如站點(diǎn)A有一個(gè)頁面腳本,包含了這個(gè)鏈接:

<?php
// 這里用一個(gè)data.json文件保存用戶數(shù)據(jù),模擬數(shù)據(jù)庫中的數(shù)據(jù)
// 先初始化data.json中的數(shù)據(jù)為{"id":101,"username":"jack"}, 注意這句只讓它執(zhí)行一次, 然后把它注釋掉
// file_put_contents('data.json','{"id":101,"username":"jack"}');

$data = json_decode(file_get_contents('data.json'), true);

// 這里為了簡便, 省略了用戶身份驗(yàn)證的過程
if ($data['username']) {
  // 設(shè)置cookie
  setcookie('uid', $data['id'], 0);
  echo "登錄成功, {$data['username']}<br>";
}
?>

 <a  rel="external nofollow" >
  更新用戶名為json
 </a>

加載這個(gè)頁面如下:

用點(diǎn)擊頁面中的鏈接來到get-update.php頁面:

上面是正常的請求流程,下面來看B站點(diǎn)是如何實(shí)現(xiàn)csrf攻擊的。

2,csrf攻擊的最簡單實(shí)現(xiàn)

B站點(diǎn)域名為test.yang.com,它有一個(gè)頁面csrf.php,只要用戶在維持A站點(diǎn)會話的同時(shí)打開了這個(gè)頁面,那么B站點(diǎn)就可以實(shí)現(xiàn)csrf攻擊。至于為什么會打開......,其實(shí)這種情景在我們?yōu)g覽網(wǎng)頁時(shí)是很常見的,比如我在寫這篇博客時(shí),寫著寫著感覺對csrf某個(gè)地方不懂,然后就百度了,結(jié)果百度出來好多結(jié)果,假如說有個(gè)網(wǎng)站叫csrf百科知識,這個(gè)網(wǎng)站對csrf介紹的非常詳細(xì)、非常權(quán)威,那么我很可能會點(diǎn)進(jìn)去看,但是這個(gè)網(wǎng)站其實(shí)是個(gè)釣魚網(wǎng)站,它在某個(gè)訪問頻率很高的頁面中嵌入了我博客編輯頁面的url地址,那么它就可以實(shí)現(xiàn)對我博客的csrf攻擊。好了,言歸正傳,下面來看下csrf.php腳本代碼:

<?php
?>
<img src="http://html5.yang.com/csrfdemo/get-update.php?uid=101&username=jsonp">
可以看到上面的代碼沒有php代碼,只有一個(gè)img標(biāo)簽,img標(biāo)簽的src就是A站點(diǎn)的那個(gè)更新用戶名的鏈接,只不過把username改為了jsonp,訪問站點(diǎn)B的csrf.php這個(gè)頁面:

下面再來訪問下A站點(diǎn)的csrfdemo.php頁面:

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

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

3,簡單防范措施

其實(shí)防范措施也比較簡單,A站點(diǎn)可以在get-update.php腳本中判斷請求頭的來源,如果來源不是A站點(diǎn)就可以截?cái)嗾埱?,下面在get-update.php增加些代碼: 

<?php
// 檢查上一頁面是否為當(dāng)前站點(diǎn)下的頁面
if (!empty($_SERVER['HTTP_REFERER'])) {
  if (parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST) != 'html5.yang.com') {
    // 可以設(shè)置http錯(cuò)誤碼或者指向一個(gè)無害的url地址
    //header('HTTP/1.1 404 not found');
    //header('HTTP/1.1 403 forbiden');
    header('Location: http://html5.yang.com/favicon.ico');
    // 這里需要注意一定要exit(), 否則腳本會接著執(zhí)行
    exit();
  }
 }

$str = file_get_contents('data.json');
// 代碼省略

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

<?php
$url = 'http://html5.yang.com/csrfdemo/get-update.php?uid=101&username=jsonp';
$refer = 'http://html5.yang.com/';
// curl方法發(fā)起csrf攻擊
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
// 設(shè)置Referer
curl_setopt($ch, CURLOPT_REFERER, $refer);
// 這里需要攜帶上cookie, 因?yàn)锳站點(diǎn)get-update.php對cooke進(jìn)行了判斷
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">
這樣同樣可以實(shí)現(xiàn)csrf攻擊的目的。那么就沒有比較好的防范方法了嗎?

4,小結(jié)

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

相關(guān)文章

  • Yii 框架使用數(shù)據(jù)庫(databases)的方法示例

    Yii 框架使用數(shù)據(jù)庫(databases)的方法示例

    這篇文章主要介紹了Yii 框架使用數(shù)據(jù)庫(databases)的方法,結(jié)合實(shí)例形式分析了Yii 框架使用數(shù)據(jù)庫(databases)的相關(guān)配置、創(chuàng)建活動(dòng)、動(dòng)作實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2020-05-05
  • PHP跨文件傳遞參數(shù)的8種常見方法

    PHP跨文件傳遞參數(shù)的8種常見方法

    這篇文章主要介紹了PHP傳遞參數(shù)(跨文件)的8種常見方法,本文通過詳細(xì)說明和示例代碼給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧
    2025-04-04
  • zend框架實(shí)現(xiàn)支持sql server的操作方法

    zend框架實(shí)現(xiàn)支持sql server的操作方法

    這篇文章主要介紹了zend框架實(shí)現(xiàn)支持sql server的操作方法,結(jié)合實(shí)例形式分析了zend框架的相關(guān)代碼修改、配置文件設(shè)置與相關(guān)問題注意事項(xiàng),需要的朋友可以參考下
    2016-12-12
  • php并發(fā)加鎖示例

    php并發(fā)加鎖示例

    本文介紹了php并發(fā)加鎖示例,對數(shù)據(jù)進(jìn)行加鎖,只容許一個(gè)用戶在一個(gè)時(shí)間內(nèi)進(jìn)行操作,這個(gè)時(shí)候就需要用到鎖了,需要的朋友可以了解一下。
    2016-10-10
  • typecho插件編寫教程(一):Hello World

    typecho插件編寫教程(一):Hello World

    這篇文章主要介紹了typecho插件編寫教程(一):Hello World,本文講解了插件的文件結(jié)構(gòu)、插件信息、插件結(jié)構(gòu)、插件流程等內(nèi)容,需要的朋友可以參考下
    2015-05-05
  • Destoon旺旺無法正常顯示,點(diǎn)擊提示“會員名不存在”的解決辦法

    Destoon旺旺無法正常顯示,點(diǎn)擊提示“會員名不存在”的解決辦法

    這篇文章主要介紹了Destoon旺旺無法正常顯示,點(diǎn)擊提示“會員名不存在”的解決辦法,需要的朋友可以參考下
    2014-06-06
  • PHP array_key_exists檢查鍵名或索引是否存在于數(shù)組中的實(shí)現(xiàn)方法

    PHP array_key_exists檢查鍵名或索引是否存在于數(shù)組中的實(shí)現(xiàn)方法

    下面小編就為大家?guī)硪黄狿HP array_key_exists檢查鍵名或索引是否存在于數(shù)組中的實(shí)現(xiàn)方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-06-06
  • 詳解PHP的Sodium加密擴(kuò)展函數(shù)

    詳解PHP的Sodium加密擴(kuò)展函數(shù)

    Sodium 出現(xiàn)的目的也是為了代替Mcrypt這個(gè)原來的加密擴(kuò)展。在 PHP7.2 之后,Mcrypt已經(jīng)被移除,在PHP7.1時(shí)就已經(jīng)被標(biāo)記為過時(shí)。不過,Sodium擴(kuò)展的應(yīng)用也并不是很多,大部分情況下我們都會使用OpenSSL來進(jìn)行加密操作,所以,我們這篇文章只做了解即可。
    2021-06-06
  • PHP搭建大文件切割分塊上傳功能示例

    PHP搭建大文件切割分塊上傳功能示例

    一般情況下,我們都需要對上傳的文件大小做限制,防止出現(xiàn)意外的情況,本篇文章主要介紹了PHP搭建大文件切割分塊上傳功能示例,有興趣的可以了解一下。
    2017-01-01
  • PHP中實(shí)現(xiàn)crontab代碼分享

    PHP中實(shí)現(xiàn)crontab代碼分享

    這篇文章主要介紹了PHP中實(shí)現(xiàn)crontab代碼分享,本文給出了實(shí)現(xiàn)代碼和使用方法,需要的朋友可以參考下
    2015-03-03

最新評論

西充县| 西城区| 左贡县| 林芝县| 论坛| 淮阳县| 会宁县| 抚州市| 梓潼县| 当雄县| 黑水县| 葵青区| 宣武区| 辽宁省| 弋阳县| 清远市| 古蔺县| 公安县| 宁国市| 扎鲁特旗| 黄龙县| 奉新县| 保亭| 永州市| 从化市| 古浪县| 洪洞县| 封丘县| 新乐市| 桃园市| 柏乡县| 涞水县| 竹溪县| 城步| 镇远县| 诸暨市| 印江| 津南区| 晋城| 南投市| 光山县|