PHP中的session安全嗎?
做PHP開(kāi)發(fā)這么長(zhǎng)時(shí)間,還真沒(méi)有真正關(guān)注過(guò)安全的問(wèn)題,每次都是以完成項(xiàng)目為主,最近在網(wǎng)上看到了一篇關(guān)于安全的文章,看完以后才注意到自己以前的項(xiàng)目都存在著很大的安全漏洞,于是挑了一個(gè)項(xiàng)目進(jìn)行了測(cè)試,發(fā)現(xiàn)很容易就中招兒了。在這里我會(huì)分享自己寫(xiě)的一個(gè)測(cè)試的例子來(lái)說(shuō)明PHP中的session是如何不安全的,以及在項(xiàng)目中如何加強(qiáng)其安全性。
對(duì)于session的原理機(jī)制,網(wǎng)上有很多好的文章來(lái)介紹,我們可以自行查閱。下面直接分享測(cè)試用的例子。
這個(gè)測(cè)試的例子主要就是一個(gè)登錄頁(yè),登錄成功以后可以修改密碼,就這樣一個(gè)簡(jiǎn)單的功能。
界面如下
首先是在項(xiàng)目入口的地方使用函數(shù) session_start() 開(kāi)啟了session。這樣當(dāng)客戶端發(fā)起請(qǐng)求的時(shí)候,會(huì)產(chǎn)生一個(gè)身份標(biāo)識(shí) 也就是 SessionID。通過(guò)cookie的方式保存在客戶端,客戶端和服務(wù)端每次的通信都是靠這個(gè)SessionID來(lái)進(jìn)行身份識(shí)別的。
登錄成功以后,會(huì)將 用戶id、用戶名存入session中
$_SESSION[‘userid'] = 用戶id $_SESSION[‘uname'] = 用戶名
以后所有的操作都是通過(guò)判斷 $_SESSION[‘userid']是否存在來(lái)檢查用戶是否登錄。代碼如下:
if(isset($_SESSION['userid'])) return true;
對(duì)于修改密碼接口的調(diào)用是通過(guò)ajax post的方式將數(shù)據(jù)傳輸?shù)椒?wù)端的。
$.post("接口*******", { oldpass:oldpass, newpass:newpass, userid:uid, }, function(data){ data = eval('(' +data+ ')'); $('.grant_info').html(infos[data.info]).show(); } );
注意,我這里將這段代碼寫(xiě)在了html頁(yè)面中,所以說(shuō)如果看到了html代碼,也就知道了接口地址了。
修改密碼的接口是這樣實(shí)現(xiàn)的,首先是判斷用戶是否登錄,如果登錄才會(huì)進(jìn)行密碼的修改操作。
測(cè)試?yán)拥膶?shí)現(xiàn)思路大概就是上面介紹的那樣。
利用SessionID攻擊
1. 首先是獲取SessionID,當(dāng)然攻擊者獲取此標(biāo)識(shí)的方式有很多,由于我的水平有限,至于如何獲取我在這里不做介紹。我們可以模擬一下,先正常訪問(wèn)此項(xiàng)目,然后通過(guò)瀏覽器查看SessionID,以此得到一個(gè)合法的用戶標(biāo)識(shí)??梢栽谡?qǐng)求頭中看到此項(xiàng)ID
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3 Connection: keep-alive Cookie: Hm_lvt_bf1154ec41057869fceed66e9b3af5e7=1450428827,1450678226,1450851291,1450851486; PHPSESSID=2eiq9hcpu3ksri4r587ckt9jt7; Host: ****** Referer: ****** User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:41.0) Gecko/20100101 Firefox/41.0
得到sessionID以后,如果此用戶登錄成功,那么服務(wù)端的session里就有此用戶的信息了。
2. 獲取到SessionID以后,假如攻擊者已經(jīng)知道修改密碼的接口,就可以直接修改此用戶的密碼了。如果攻擊者還沒(méi)有得到接口地址,可以通過(guò)查看頁(yè)面代碼找出接口地址??梢允褂萌缦碌拿?br />
#curl --cookie "PHPSESSID=2eiq9hcpu3ksri4r587ckt9jt7" 頁(yè)面地址
上面我們說(shuō)過(guò),在此例子中ajax代碼是寫(xiě)在html頁(yè)面中的,所以在此頁(yè)面可以查看到接口地址
部分html代碼如下
<html xmlns="http://www.w3.org/1999/xhtml"> <head> …… var uid = $(".userid").val(); $.post("/User/User/modifypass_do", { oldpass:oldpass, newpass:newpass, userid:uid, }, function(data){ data = eval('(' +data+ ')'); $('.grant_info').html(infos[data.info]).show(); } ); …… <span><input type="password" name="oldpass" id="textfield_o" placeholder="原密碼"></span> <span><input type="password" name="newpass" id="textfield_n" placeholder="新密碼"></span> <span><input type="password" name="confirmpass" id="textfield_c" placeholder="確認(rèn)密碼"></span> <input type="button" class="btn_ok" value="確認(rèn)修改" />
3. 得到接口以后可以通過(guò)curl 模擬post發(fā)送數(shù)據(jù)來(lái)修改密碼
命令如下
# curl --cookie "PHPSESSID=2eiq9hcpu3ksri4r587ckt9jt7" -d oldpass=111111 -d newpass=000000 -d userid=用戶id 接口地址
如果此用戶已經(jīng)登錄,那么攻擊者可以通過(guò)執(zhí)行以上命令修改用戶的密碼。
解決方法
對(duì)于以上方式的攻擊,我們可以通過(guò)使驗(yàn)證方式復(fù)雜化來(lái)加強(qiáng)其安全性。其中一種方式就是利用請(qǐng)求頭中的User-Agent項(xiàng)來(lái)加強(qiáng)其安全性
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3 Connection: keep-alive Cookie: Hm_lvt_bf1154ec41057869fceed66e9b3af5e7=1450428827,1450678226,1450851291,1450851486; PHPSESSID=2eiq9hcpu3ksri4r587ckt9jt7; Host: ****** Referer: ****** User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:41.0) Gecko/20100101 Firefox/41.0
在項(xiàng)目開(kāi)始的時(shí)候最初我們只是用了session_start()函數(shù)來(lái)開(kāi)啟session?,F(xiàn)在我們可以在session_start() 下面 添加這段代碼
$_SESSION[‘User_Agent'] = md5($_SERVER[‘HTTP_USER_AGENT']);
然后在每次判斷是否登錄的時(shí)候,添加判斷條件如下
If(isset($_SESSION[‘userid']) && $_SESSION[‘User_Agent'] == md5($_SERVER[‘HTTP_USER_AGENT'])){ return true; }
這樣就可以避免上述簡(jiǎn)單的攻擊。
總結(jié):
當(dāng)然,實(shí)際情況中的攻擊遠(yuǎn)非這么簡(jiǎn)單,首先在獲取SessionID這一步就比較困難,然后就是和服務(wù)端交互的代碼盡量加密,可以避免上述的情況。在我們第二次修改代碼以后,可以增加攻擊的復(fù)雜程度,并不能杜絕攻擊。攻擊的方式多種多樣,這里只是一種簡(jiǎn)單的方式,僅提供一種思路,但是原理是一樣的,在實(shí)際情況中可以根據(jù)實(shí)際情況增強(qiáng)我們代碼的安全程度。
這里只是分享自己在工作中碰到的問(wèn)題,權(quán)當(dāng)拋磚引玉,希望大家可以進(jìn)一步深入學(xué)習(xí)。
- PHP session有效期session.gc_maxlifetime
- php session安全問(wèn)題分析
- PHP session會(huì)話的安全性分析
- 簡(jiǎn)單的方法讓你的后臺(tái)登錄更加安全(php中加session驗(yàn)證)
- PHP中怎樣保持SESSION不過(guò)期 原理及方案介紹
- 教你如何使用php session
- PHP中session變量的銷(xiāo)毀
- Session的工作機(jī)制詳解和安全性問(wèn)題(PHP實(shí)例講解)
- ThinkPHP的模版中調(diào)用session數(shù)據(jù)的方法
- php中實(shí)現(xiàn)精確設(shè)置session過(guò)期時(shí)間的方法
相關(guān)文章
PHP創(chuàng)建word文檔的方法(平臺(tái)無(wú)關(guān))
這篇文章主要介紹了PHP創(chuàng)建word文檔的方法,結(jié)合實(shí)例形式分析了與平臺(tái)無(wú)關(guān)的生成word文檔的方法,非常簡(jiǎn)單實(shí)用,需要的朋友可以參考下2016-03-03php類(lèi)自動(dòng)加載失敗的處理方案及實(shí)例代碼
在本篇文章里小編給大家整理了一篇關(guān)于php類(lèi)自動(dòng)加載失敗的處理方案及實(shí)例代碼,有興趣的朋友們可以學(xué)習(xí)參考下。2021-09-09淺談PHP中類(lèi)和對(duì)象的相關(guān)函數(shù)
下面小編就為大家?guī)?lái)一篇淺談PHP中類(lèi)和對(duì)象的相關(guān)函數(shù)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-04-04PHP實(shí)現(xiàn)二維數(shù)組按照指定的字段進(jìn)行排序算法示例
這篇文章主要介紹了PHP實(shí)現(xiàn)二維數(shù)組按照指定的字段進(jìn)行排序算法,涉及php針對(duì)數(shù)組的遍歷、排序等相關(guān)操作技巧,需要的朋友可以參考下2019-04-04php實(shí)現(xiàn)建立多層級(jí)目錄的方法
這篇文章主要介紹了php實(shí)現(xiàn)建立多層級(jí)目錄的方法,需要的朋友可以參考下2014-07-07PHP采用XML-RPC構(gòu)造Web Service實(shí)例教程
這篇文章主要介紹了PHP采用XML-RPC構(gòu)造Web Service,需要的朋友可以參考下2014-07-07