最近被資安問題搞死了,筆記一下相關資訊。
一、檢查資料
1.後端可以用這幾個函式:
filter_input 可以用來處理前端輸入的資料,預設是不篩選,必須設定篩選參數。
filter_var 可以用來處理DB撈出來的資料,用法同上。
filter_input跟filter_var都要加上篩選的參數,不然等於沒有篩選,常用兩個參數:
FILTER_SANITIZE_STRING //只留文字
FILTER_SANITIZE_NUMBER_INT //只留數字跟+-
後端的輸出最好不要有HTML標記,如果有的話可以用:
HTML Purifier http://htmlpurifier.org/
這個套件處理,HTML Purifier會刪掉style、onclick等等的內容,保留常見如div、span、p、a等標籤,當然也可另外設定白名單。基本用法如下:
require_once './library/HTMLPurifier.auto.php';//引入
$config = HTMLPurifier_Config::createDefault();//引入預設設定值
$def = $config->getHTMLDefinition(true);//允許新增設定
$def->addAttribute('span', 'b', 'Text');//在span中可以有b屬性,內容是text
$def->addElement('h', 'Block', 'Flow', 'Common');//允許使用<h>標籤,後面三個參數大致如此
$purifier = new HTMLPurifier($config);
$purifier->purify(髒髒的html);//篩掉不合規定的html
後端的輸出記得加上 htmlspecialchars。
htmlspecialchars必須再加上幾個參數才完整:
htmlspecialchars($變數, ENT_QUOTES, 'UTF-8')
2.前端接到資料也要轉換
原生的innerHTML不會執行<script>的內容,後台得到的htmlspecialchars內容可以用下面函式,重新轉成html顯示在頁面上。
function htmldecode(s){
let div = document.createElement('div');
div.innerHTML = s;
return div.innerText || div.textContent;
}
使用JQuery時,不要直接用load()、html()把抓到的東西直接印在頁面上,因為這兩個函式會執行<script>的內容,比較偷懶方法可以先把元素清空(empty),再用append()追加內容,append不會執行<script>,不過還是防不了onclick等的js語法。最好的方法是用createElement,簡單用法如下:
$('<div>').text('xxx').append($(目標));
如果只要文字的話,可用下面函式:
function textOnly(input) {
let doc = new DOMParser().parseFromString(input, "text/html");
return doc.documentElement.textContent;
}
二、外部設定
1.在PHP.ini中設定禁用函式
disable_functions = system,exec,shell_exec,passthru,proc_open,proc_close, proc_get_status,checkdnsrr,getmxrr,getservbyname,getservbyport, syslog,popen,show_source,highlight_file,dl,socket_listen,socket_create,socket_bind,socket_accept, socket_connect, stream_socket_server, stream_socket_accept,stream_socket_client,ftp_connect, ftp_login,ftp_pasv,ftp_get,sys_getloadavg,disk_total_space, disk_free_space,posix_ctermid,posix_get_last_error,posix_getcwd, posix_getegid,posix_geteuid,posix_getgid, posix_getgrgid,posix_getgrnam,posix_getgroups,posix_getlogin,posix_getpgid,posix_getpgrp,posix_getpid, posix_getppid,posix_getpwnam,posix_getpwuid, posix_getrlimit, posix_getsid,posix_getuid,posix_isatty, posix_kill,posix_mkfifo,posix_setegid,posix_seteuid,posix_setgid, posix_setpgid,posix_setsid,posix_setuid,posix_strerror,posix_times,posix_ttyname,posix_uname
另一個減輕 XSS 攻擊的設定是 HttpOnly
session.cookie_httponly = True
隱藏 PHP 版本
expose_php = off
禁止執行外網程式
allow_url_fopen=Off
禁止上傳檔案
file_uploads=Off
2.eval也要禁用
從資料來看,eval的禁用方式比較麻煩,有下面幾種方式:
https://github.com/frontdevops/php-evil
https://github.com/sektioneins/suhosin7
https://github.com/mk-j/PHP_diseval_extension
但是這些extension都要編譯才能用,在windows中還沒有測試成功,有待驗證。
3.Apache
在httpd.conf中加入以下內容
# 限制被Frame的情形:sameorigin – 只允許來自同一個網域、deny – 禁止任何嵌入
Header always append X-Frame-Options "SAMEORIGIN "
Header always append Frame-Options "SAMEORIGIN"
# Enforce HTTPS connections for all requests, including subdomains
Header always append STRICT-TRANSPORT-SECURITY "max-age=16070400; includeSubDomains"
# IE8+ and variants, XSS Protection
Header always append X-XSS-Protection "1;mode=block"
# Protection from drive-by dynamic/executable IE files
Header always append X-Content-Type-Options "nosniff"
# Content-Security-Policy是直接設定能引入的外部資源白名單,可能會導致網站讀不到外部css、js而壞掉
Header always append Content-Security-Policy "default-src 'none'; script-src 'self'; connect-src: 'self'; img-src: 'self'; style-src: 'self';"
Header always append X-Content-Security-Policy "default-src 'none'; script-src 'self'; connect-src: 'self'; img-src: 'self'; style-src: 'self';"
Header always append X-WebKit-CSP "default-src 'none'; script-src 'self'; connect-src: 'self'; img-src: 'self'; style-src: 'self';"
留言
張貼留言