PHP面試(三)

weixin_34185560發表於2017-05-23

XSS攻擊是什麼


4651473-9a1a069f74c67eed.png
XSS

常見的 XSS 輸入
XSS 輸入通常包含 JavaScript 指令碼,如彈出惡意警告框:<script>alert("XSS");</script>
XSS 輸入也可能是 HTML 程式碼段,譬如:
網頁不停地重新整理** <meta http-equiv="refresh" content="0;">**
嵌入其它網站的連結 <iframe src=http://xxxx width=250 height=250></iframe>

如何預防XSS

目前防禦XSS的方式:

PHP 提供了htmlspecialchars()函式可以將 HTML 特殊字元轉化成在網頁上顯示的字元實體編碼。這樣即使使用者輸入了各種 HTML 標記,在讀回到瀏覽器時,會直接顯示這些 HTML 標記,而不是解釋執行。htmlspecialchars()函式可以將以下五種 HTML 特殊字元轉成字元實體編碼:
- &轉成 &
- “轉成 "
- <轉成 <
- ·>轉成 & g t;
- ‘轉成 '

當直接呼叫 htmlspecialchars($str)時, & " < > 被轉義。
當設定 ENT_QUOTES 標記時, 即呼叫htmlspecialchars($str, ENT_QUOTES)時,單引號也被轉義。
當設定 ENT_NOQUOTES 標記時,單引號和雙引號都不會被轉義。即呼叫 htmlspecialchars($str, ENT_NOQUOTES)時,只有& < > 被轉義。

<?php
    if (isset($_POST['name'])){
    $str = trim($_POST['name']);  //清理空格
    $str = strip_tags($str);   //過濾html標籤
    $str = **htmlspecialchars**($str);   //將字元內容轉化為html實體
    $str = addslashes($str);
    echo $str;
}
?>
<form method="post" action="">
<input name="name" type="text">
<input type="submit" value="提交" >
</form>

PHP 提供了strpos()、strstr()、preg_match()等函式可用於檢測非法字元和字串;preg_replace() 函式可用於替換非法字串。

CRSF(Cross-site request forgery),中文名稱:跨站請求偽造
那麼CSRF到底能夠幹嘛呢?你可以這樣簡單的理解:攻擊者可以盜用你的登陸資訊,以你的身份模擬傳送各種請求。攻擊者只要藉助少許的社會工程學的詭計,例如通過QQ等聊天軟體傳送的連結(有些還偽裝成短域名,使用者無法分辨),攻擊者就能迫使Web應用的使用者去執行攻擊者預設的操作。例如,當使用者登入網路銀行去檢視其存款餘額,在他沒有退出時,就點選了一個QQ好友發來的連結,那麼該使用者銀行帳戶中的資金就有可能被轉移到攻擊者指定的帳戶中。

所以遇到CSRF攻擊時,將對終端使用者的資料和操作指令構成嚴重的威脅;當受攻擊的終端使用者具有管理員帳戶的時候,CSRF攻擊將危及整個Web應用程式。

4651473-093e9b3e644edff9.png
image.png

從上圖可以看出,要完成一次CSRF攻擊,受害者必須依次完成兩個步驟 :

  1. 登入受信任網站A,並在本地生成Cookie 。

  2. 在不退出A的情況下,訪問危險網站B。

看到這裡,讀者也許會問:“如果我不滿足以上兩個條件中的任意一個,就不會受到CSRF的攻擊”。是的,確實如此,但你不能保證以下情況不會發生:
你不能保證你登入了一個網站後,不再開啟一個tab頁面並訪問另外的網站,特別現在瀏覽器都是支援多tab的。
你不能保證你關閉瀏覽器了後,你本地的Cookie立刻過期,你上次的會話已經結束。
上圖中所謂的攻擊網站,可能是一個存在其他漏洞的可信任的經常被人訪問的網站。
因此對於使用者來說很難避免在登陸一個網站之後不點選一些連結進行其他操作,所以隨時可能成為CSRF的受害者。
CSRF攻擊主要是因為Web的隱式身份驗證機制,Web的身份驗證機制雖然可以保證一個請求是來自於某個使用者的瀏覽器,但卻無法保證該請求是使用者批准傳送的。

服務端的預防CSRF攻擊的方式方法有多種,但思想上都是差不多的,主要從以下2個方面入手:

  1. 正確使用GET,POST和Cookie;

  2. 在非GET請求中增加偽隨機數;

一般而言,普通的Web應用都是以GET、POST為主,還有一種請求是Cookie方式。我們一般都是按照如下方式設計應用:

  1. GET常用在檢視,列舉,展示等不需要改變資源屬性的時候;

  2. POST常用在下達訂單,改變一個資源的屬性或者做其他一些事情

接下來我就以Java語言來舉例說明,如何限制對資源的訪問方法:

Blade.regRoute("/user/:uid", IndexRoute.class, "getuser", HttpMethod.GET);
Blade.regRoute("/user/:uid", IndexRoute.class, "modifyuser", HttpMethod.POST);

程式碼是blade框架的寫法。

這樣處理後,因為我們限定了修改只能使用POST,當GET方式請求時就拒絕響應,所以上面圖示中GET方式的CSRF攻擊就可以防止了,但這樣就能全部解決問題了嗎?當然不是,因為POST也是可以模擬的。

因此我們需要實施第二步,在非GET方式的請求中增加隨機數,這個大概有三種方式來進行:

為每個使用者生成一個唯一的cookie token,所有表單都包含同一個偽隨機值,這種方案最簡單,因為攻擊者不能獲得第三方的Cookie(理論上),所以表單中的資料也就構造失敗,但是由於使用者的Cookie很容易由於網站的XSS漏洞而被盜取,所以這個方案必須要在沒有XSS的情況下才安全。

每個請求使用驗證碼,這個方案是完美的,因為要多次輸入驗證碼,所以使用者友好性很差,所以不適合實際運用。

不同的表單包含一個不同的偽隨機值

一次完整的網路請求
4651473-280f301966aa2321.png
一次完整的網路請求.png
PCNTL

PHP使用PCNTL系列的函式也能做到多程式處理一個事務。比如我需要從資料庫中獲取80w條的資料,再做一系列後續的處理,這個時候,用單程式?你可以等到明年今天了。。。所以應該使用pcntl函式了。
假設我想要啟動20個程式,將1-80w的資料分成20份來做,主程式等待所有子程式都結束了才退出:

$max = 800000;
$workers = 20;
$pids = array();
for($i = 0; $i < $workers; $i++){
    $pids[$i] = pcntl_fork();
    switch ($pids[$i]) {
        case -1:
        echo "fork error : {$i} \r\n";
        exit;
    case 0:
        $param = array(
            'lastid' => $max / $workers * $i,
            'maxid' => $max / $workers * ($i+1),
        );
        $this->executeWorker($input, $output, $param);
        exit;
    default:
        break;
}

}

foreach ($pids as $i => $pid) {
if($pid) {
    pcntl_waitpid($pid, $status);
}

}
這裡當pcntl_fork出來以後,會返回一個pid值,這個pid在子程式中看是0,在父程式中看是子程式的pid(>0),如果pid為-1說明fork出錯了。

使用一個$pids陣列就可以讓主程式等候所有程式完結之後再結束了

PHP socket

Socket是什麼

socket的英文原義是“孔”或“插座”。作為BSD UNIX的程式通訊機制,取後一種意思。通常也稱作”套接字”,用於描述IP地址和埠,是一個通訊鏈的控制程式碼。在Internet上的主機一般執行了多個服務軟體,同時提供幾種服務。每種服務都開啟一個Socket,並繫結到一個埠上,不同的埠對應於不同的服務。

以上內容來自百度百科

簡單說來,socket可以幫助不同的服務在不同的埠進行通訊。

PHP curl

cURL 是一個利用URL語法規定來傳輸檔案和資料的工具,支援很多協議和選項,如HTTP、FTP、TELNET等,能提供 URL 請求相關的各種細節資訊。最爽的是,PHP 也支援 cURL 庫

陣列函式array_merge和+的區別:
$a=array('a'=>1,'b'=>2,'c'=>3);
$b=array('b'=>5,'c'=>6,'d'=>7);

print_r(array_merge($a,$b));
print_r($a+$b);

就輸出:
array(
[a]=>1
[b]=>5
[c]=>6
[d]=>7
)
array
(
[a]=>1
[b]=>2
[c]=>3
[d]=>7
)

array_merge()
如果輸入的陣列中有相同的字串鍵名,則該鍵名後面的值將覆蓋前一個值。對於使用+合併陣列
如果陣列中有相同的字串鍵名(不管是不是數字),則會把最先出現的值作為最終結果返回,而把後面的陣列擁有相同鍵名的那些值拋棄掉 。

isset如果變數存在(非NULL)則返回TRUE,否則返回FALSE.變數設定為NULL,返回也是FALSE.PHP的isset()函式 一般用來檢測變數是否設定
empty.如果變數時非空和非零的值,則empty返回FALSE,換句話說,NULL,FALSE,0,$var未定義。以及沒有屬性的物件都被認為是空的。如果var為空,則返回true。**PHP的empty()函式 判斷值為否為空 **

TCP和UDP的區別

TCP:面向連線、傳輸可靠(保證資料正確性,保證資料順序)、用於傳輸大量資料(流模式)、速度慢,建立連線需要開銷較多(時間,系統資源)。
UDP:面向非連線、傳輸不可靠、用於傳輸少量資料(資料包模式)、速度快。

資料庫的事務:
  1. 事務具有原子性,就是把多個資料庫操作合併成一個操作,讓它具有原子性,有一個操作失敗會回滾。(多個操作,會有出錯的,有一個失敗的話,整個操作會回滾。)
    2。 可移植性
    會把自己操作過的資料設定一個所,在這個資料沒有結束之前,其他人都不能操作這個資料。
兩個資料庫的操作

兩個資料庫需要兩次連結
兩次都需要啟動事務,每個事務都成功之後,在提交。
A資料庫 執行兩條語句,成功
B資料庫 執行三條語句,成功
之後再提交。

索引的作用

從資料結構角度想:B+樹。
存在葉子節點上面的是資料,innodb。
存在葉子結點上面的是實體地址,MYiSAM.
對於這種自己不會的問題,引導到自己會的問題上面。

連表查詢和巢狀查詢的那個效率更高:

如果自己不知道哪一個效率高,這個應該考慮的是優化的問題,你可以說,我還沒有做過實驗,但是可以用explain做一下實踐。
優化就是sql的關鍵點。
哪種效率最高,哪種最優。

  1. 誰用了索引,數取資料的行數少,誰的效率就搞,它就好。不管它是group by, order, join.

還有對於自己簡歷上面的寫的東西,自己一定要會。

相關文章