前言
今天時間不夠,中斷一下寫到一半的 Passport。
這是回答另一間公司的前測題目,應徵的職位是 PHP 後端工程師。
跟大家交流一下,希望看看不同的答案。
資安問題
請說明何謂 SQL Injection,請詳述原理,並且舉例說明
意思是注入不懷好意的 SQL 指令,如果輸入欄位不做一些防禦,這些指令就會一起被組合進去執行。
最經典的例子是在密碼欄位輸入 'or '1'='1
如果原本的語法是
select * from users where username = '$name' and password = '$pwd';
組合後變成
select * from users where username = 'admin' and password = '' or '1'='1'
由於1=1成立,所以攻擊者就能得到 admin 權限
承接上題,請詳細說明要如何防止 SQL Injection? PHP程式要如何處理 SQL Injection,請說明您認為最好的防止方法?
防禦概念是不要使用客戶端輸入的東西來組合 SQL 語句。
(1) 用 htmlspecialchars、escape 或 str_replace 等函式跳脫字元,我認為是比較不好的方法,單純防掉單引號或雙引號其實不夠,可能會有沒考慮到的漏洞。
(2) 使用 PDO,PDO 是一種程式,本身就提供防止 SQL Injection 方法,透過 Prepared Statment、bind value 以及轉換特殊字元來防禦。
我覺得使用公認資安專家的方法比較好,盡量不要自己想方法,例如使用 Laravel 盡量少用 raw SQL,如果有用戶端輸入資料盡量使用 Eloqunet 提供的方法(還是 PDO)。
請列出資安的攻擊方式(針對web網頁),並詳細說明手法的原理和阻擋的方式?
XSS : 一種網站被他人植入程式碼的攻擊方法,例如對方可以植入廣告、盜取cookie或使用 javascript 做的任何事。
防範手法:輸入驗證檢查,例如黑名單、跳脫字元,輸出encoding。
輸出encoding會是比較好的方法,因為可以植入的地方太多,Javascript、HTML、URL等,不好防範。
CSRF:偽造使用者發出請求。透過瀏覽器的機制,當發送請求時會把相關 cookie 傳送過去,當進入釣魚網站時使用者正好是登入狀態,就有可能送出包含資訊的請求。
阻擋方式:
從 server 端防禦:檢查 CSRF token、加上驗證碼或簡訊、檢查 header refer 是不是合法網站。
從 client 端防禦:不點擊可疑網站或圖片、使用有 same site cookie 的瀏覽器。
請說明 Cookie 與 Session 的差別,與兩者適合使用的情境或功能(越詳細越好)
cookie 和 session 都是要解決一些使用者暫存資料的方法,cookie 存在客戶端,session 存在伺服器端。
使用 session 是為了解決儲存 request 狀態的問題,由於 HTTP 是一種 stateless 的通訊機制,為了要讓請求變成 stateful 就有了 session。
cookie 是瀏覽器方便使用者,將一些使用者資訊存起來,附帶在 request 一起發送。
我們可以透過 cookie 來實作 session(但並不一定要這樣)。
至於實作方法有兩種:(1) Cookie-based session,是將 session 存在 cookie 並加密。(2)使用 SessionID,cookie 只存 server 發的 SessionID,機密資料仍保存在 server。
請說明 get 和 post 傳遞表單資料的差異,列出兩者的差異(越詳細越好)
GET 是為了取得資料,會走 URL 用 query string 去搜尋
缺點:
因為資料帶在網址上(不允許 body 帶資料),
大家都看得到,所以是比較不安全的傳遞方法、
長度限制、
資料只允許 ASCII。
優點:
也是因為資料帶在網址上,所以使用者可以把換頁情況保存下來。
POST 是將資料放在 body,不在網址上。
缺點:
無法儲存換頁,不能被加在書籤。
優點:
在封包沒有被劫走的情況下會比較安全。
長度不受限制。
資料不受限制。
cache
如果是用網址來做快取,使用 GET 請求同一網址可能會發生伺服器狀態已經變,但是仍取得舊資料的狀況。如果想避免,可以網址加上時間戳記,或改用 POST。
請問 PHP 如何取得使用者的 IP 資料?
header 常見存放使用者 IP 的地方是:
HTTP_CLIENT_IP
HTTP_X_FORWARDED_FOR (第一個 IP)
REMOTE_ADDR (最後一個來源 IP)
但是要注意 IP 是可以被偽造的,也要注意遭到 SQL Injection 攻擊。
可以使用 filter_var() 把內容轉成數字。
當然從 header 存入的數值也可能會遭到攻擊者竄改插入特殊字元嘗試 SQL Injection,因此存入值必須先經過過濾,或者使用 Prepared Statement 進行存放。
PHP 問題
請問要如何避免出現這段錯誤訊息,'Warning: Cannot modify header information – headers already sent' 。另外請列舉出有可能造成出現這段錯誤訊息的可能原因
錯誤訊息看起來是「不能修改 header,header 已經輸出」。有可能的原因:
(1) 檢查 sent 後面的行數,是不是在 header 前使用了 print、echo 等輸出
(2) 檢查 <?php 前後是不是有空格
如果一定要輸出的話,可以用 ob_start()、ob_end_flush() 包住輸出
請問什麼是 Trait ? 甚麼狀況下使用?
Trait 是 PHP 5.4 之後加入的新語法,Trait 是融合 interface 和 class 的產物,
由於 PHP 也不允許多重繼承,當想要重複使用程式碼(使用 interface 仍然要寫下重複的程式碼),但是不想要增加依賴關係時使用。
請問您有使用過 composer 的經驗嗎?如果有,請問使用 composer 有甚麼優點?
有使用過 JWT、charts 當想要使用別人寫好的套件時會使用。
優點是方便套件管理與升級,另外在 composer 註冊可以自動載入,這樣當類別多的時候,不會重複載入,統一由 autoload.php 管理。
總結
暫無
參考資料
- 如何正確的取得使用者 IP?
- PTT PHP 板 R: [請益] 網站資安需注意哪些?
https://www.ptt.cc/bbs/PHP/M.1527504207.A.92A.html @MoMoShota
https://www.ptt.cc/bbs/PHP/M.1528111425.A.0A8.html @GALINE
https://www.ptt.cc/bbs/PHP/M.1528122524.A.24B.html @MoMoShota - Servlet & JSP 教學手冊 第二版