跳到主要內容

整理一下PHP的資安設定

最近被資安問題搞死了,筆記一下相關資訊。 

一、檢查資料

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';"


//只反映真實的路徑
AcceptPathInfo Off

//Disable HTTP TRACE
TraceEnable Off


在ssl.confhttpd.conf 中加入以下內容
SSLProtocol all -SSLv2 -SSLv3
SSLHonorCipherOrder on
SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:+HIGH:+MEDIUM:-LOW:!RC4:!NULL

關掉icons目錄顯示
在extra/httpd-autoindex.conf中 註解掉相關內容:
#<Directory "${SRVROOT}/icons">
#    Options Indexes MultiViews
#    AllowOverride None
#    Require all granted
#</Directory>

#AddIconByType (TXT,/icons/text.gif) text/*
下面一堆AddIconByType 都加上#

註解掉ScriptAlias
在 /apache/conf/extra/httpd-xampp.conf 中
# ScriptAlias /php-cgi/ "C:/xampp/php/"

留言

這個網誌中的熱門文章

網站掃描CSP弱點問題

 最近被網站弱點掃描的CSP問題困擾很久,CSP問題主要是兩種: 1.在CSP中允許內聯腳本執行 2.從CSP中缺少必要的指令 AppScan這兩個問題提供的處理方式都是「配置正確值的Content-Security-Policy」,等於沒說。 後來才發現AppScan無法處理多層的Content-Security-Policy,例如在httpd.conf中設定: default-src 'self' 'unsafe-inline'; 又在htaccess設定 script-src 'self'; 正常來說瀏覽器會採用htaccess的設定,即「script-src 'self';」而不是「script-src 'self' 'unsafe-inline'」,以安全性來說是符合的,但AppScan無法判斷,直接當你沒設定好CSP,解決方法只有不要重複設定,保留一項設定就好。

2016鳥取島根岡山之旅(三)

松江站身輕便(松江駅身がる便) 松江站提供的行李寄送服務,服務對象是宍道湖溫泉和玉造溫泉的住宿客,服務時間為早上九點到下午三點,三點以後會開始配送行李到各個旅館,通常五點前就會送到了。 對不想拎著行李逛街的人來說非常方便,反正都要寄放行李,不如寄到旅館,而且還只要500円,大型行李櫃都還要700円說,實在很划算。 能送到的旅館只限「松江市內」,也就是位在「宍道湖溫泉」和「玉造溫泉」的溫泉旅館。 參考網址: http://www.kankou-matsue.jp/information/service/ http://www.saninji.jp/1930 實際寄送方式如下: 1.到JR松江站以後抬頭就會看到一個看板,照著看板指示前往「南口」的「臨時寄物處」(荷物一時預り所)。 2.由於臨時寄物處在站外,如果一下子找不到的話可以先找到寄物櫃,也就是コインロッカー(Coin Lockers) 3.寄物櫃旁邊就會看到這個招牌,繼續沿著站外走。 4.路上會一直有標示,指引前往臨時寄物處。 5.這裡就是了,別看有派出所就怕了,就是這裡沒錯。 6.跟裡面的人說要寄到哪裡,他會幫你寫好寄送位置,你只要寫名字就好,寫跟旅館訂房間的名字,如果訂房時只有一個名字,寫那個人就可以了。 7.可能會問你有沒有手機號碼,不過大部分人就算有也打不通,說沒有也沒關係。 8.最後會拿到一張收據,理論上要憑收據到旅館櫃檯領行李,不過溫泉旅館秉著服務至上的精神,只要訂房名字沒錯的話,就會直接幫你放到房間裡。

Google 分析 (Google Analytics) 造成的「加密的階段作業 (SSL) Cookie 中遺漏安全屬性」

 Google 分析 (Google Analytics) 的cookies會造成「加密的階段作業 (SSL) Cookie 中遺漏安全屬性」的弱點,網路上有一種解決方式,在gtag中加上參數,如下: gtag('config', 'G-XXXXXXXXXX', {'cookieFlags': 'SameSite=Strict; Secure'}); 但我的系統卻無法使用,研究了一下,要拆開寫,如下   gtag('set', 'cookie_flags', 'SameSite=Strict;Secure');   gtag('config', 'G-XXXXXXXXXX'); 要拆成兩行,Secure就可以用了。 但更簡單的方法是在httpd.conf中加入這一行 Header edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure;SameSite=Strict 解決。