保護 OpenClinica
安裝、配置和保護 OpenClinica [OC] 社群版 [CE] 絕對是一次冒險,需要掌握計算機科學各個方面的知識。但是,透過大量的谷歌搜尋和奉獻精神,任何對 Linux 有一定了解的人都可以做到。我並非計算機科學專業人士,但仍然承擔了在 Web 伺服器上部署 OC 的任務,最終成功地使其執行起來。不過,也有一些時候,我希望有一份關於如何管理此過程的詳盡指南。透過這篇文章,我想填補這一空白,至少在 OC 的安全方面,為任何嘗試執行相同任務的人提供幫助。
我採取的措施是從眾多來源中找到的,我不能保證這些措施涵蓋了保護 OC 時可以/應該採取的所有措施。正如我之前提到的,我不是該領域的專家,本指南僅僅是我大量搜尋和反覆試驗的結果。請謹慎對待這裡的所有內容,如果您認為自己有更好的方法,請不要猶豫進行更改。也請隨時建議改進/增加此過程,以便我們都能從這些集體知識中受益。
我儘可能認真地對待安全性,因為截至 2020 年,OC CE 所需的軟體早已過時,因此盡一切可能使其安全至關重要,尤其是在處理患者資料時。
我選擇的設定如下
- OpenClinica CE 3.15
- CentOS 8
- PostgreSQL 8.4.22
- Tomcat 7.0.52
- JVM 1.7.0
我按照 此安裝指南 進行操作,因為我找不到 v3.15 的指南。獲得上面列出的一些特定軟體版本頗具挑戰性,如果我不得不重新開始,我會考慮使用 CentOS 6,因為此版本原生支援其中一些較舊的依賴項。CentOS 6 也已於今年停止支援,因此在選擇它時請仔細考慮。
根據上述指南的指示,執行 OC 所需的所有元件的根資料夾位於:/usr/local
話不多說,我們開始吧
首先,訪問 Web 伺服器(如果是遠端伺服器)應該得到保護。每天都有數百次嘗試使用常見使用者名稱登入 Web 伺服器,因此這確實應該是您的第一道安全防線。
此檔案位於 `/etc/ssh/sshd_config` 下,並控制對伺服器的 SSH 訪問。在對其進行任何更改之前,請確保已對其進行了備份。在檔案中,修改以下引數
僅允許需要訪問伺服器的使用者
- AllowUsers <username1> <username2>
停用 root 登入
- PermitRootLogin no
- ChallengeResponseAuthentication no
將您的 SSH 金鑰複製到伺服器後(使用 ssh-copy-id 或手動,透過複製您的公鑰並將其貼上到伺服器上的 `~/.ssh/authorized_keys` 檔案中),您應該停用密碼身份驗證。這樣,僅可以透過 SSH 金鑰身份驗證登入。
- PasswordAuthentication no
為了提高安全性,還可以將 UsePAM 設定為 `no`,但是,這會弄亂我的 SSH 身份驗證過程,我不得不將其設定回 `yes`。
所有內容配置完成後,重新啟動 sshd 服務
sudo systemctl restart sshd
此軟體包透過禁止在 x 次身份驗證失敗後嘗試 SSH 身份驗證的 IP 地址來提供額外的 SSH 安全性。這裡有一篇關於配置 fail2ban 的 很棒的指南。
sudo yum install epel-release
sudo yum install fail2ban
在 `/etc/fail2ban` 下建立一個名為 `jail.local` 的檔案,並將以下內容貼上到其中(使用您自己的電子郵件地址)
[DEFAULT] # Ban hosts for one hour: bantime = 3600 maxretry = 5 [sshd] enabled = true destemail = <your@email.com> sender = <your@email.com> sendername = Fail2ban mta = sendmail action = %(action_mwl)s
建立此檔案而不是直接在 `jail.conf` 中進行配置是首選,因為 fail2ban 更新會覆蓋您的配置。現在,當 IP 地址在 5 次失敗的登入嘗試後被禁止或 fail2ban 被停止/啟動時,您將收到電子郵件通知。
重新啟動 fail2ban 服務:sudo systemctl restart fail2ban
如果您想接收有關被禁止 IP 的更多資訊,可以安裝 `whoami.x86_64` 軟體包。
您可以透過以下方式檢查 sshd 監禁狀態:sudo fail2ban status sshd
雖然這聽起來可能很明顯,但仍然至關重要的是在您的伺服器上維護強大且唯一的密碼。我建議使用 KeePass 來跟蹤它們,因為它還允許您自動生成非常強大的密碼。
保護 Tomcat 與保護您的 Web 伺服器一樣重要,因為這是您與外部世界的聯絡點。我從以下網站收集了下面列出的安全措施 [1] [2] [3] [4]
這是為了確保即使攻擊者能夠控制 Web 伺服器,她所能造成的損害也是最小的。首先,永遠不要以 root 使用者身份執行您的 Web 伺服器,建立一個名為 `tomcat` 的新使用者,該使用者具有執行伺服器的最低必要許可權。
將資料夾 `tomcat` 及其所有內容的所有者設定為使用者 tomcat 和組 tomcat
chown -R tomcat:tomcat /usr/local/tomcat
(沒有 -R 標誌,您只會更改資料夾的所有權,而不是內容)
授予資料夾所有者讀取、寫入和執行許可權
chmod -R 700 /usr/local/tomcat
(關於使用 chmod 的指南:https://www.lifewire.com/uses-of-command-chmod-2201064) 注意:要能夠開啟資料夾,您需要對它具有執行許可權。我也有過慘痛的教訓。
從配置資料夾中刪除寫入和執行許可權。這可以防止攻擊者修改 Tomcat 的配置檔案
chmod -R u-wx /usr/local/tomcat/conf
但是,Tomcat 需要能夠開啟資料夾,因此僅向資料夾新增執行許可權(=不帶 -R 標誌)
chmod u+x /usr/local/tomcat/conf
從 openclinica.config 和 openclinica-ws.config(如果已安裝)資料夾中刪除讀取許可權
chmod -R u-w openclinica*.config
從 logs 資料夾中刪除讀取許可權
chmod -R u-r /usr/local/tomcat/logs
刪除 oldwebapps 資料夾的所有許可權,因為在部署過程中 Tomcat 不需要處理這些檔案。
chmod -R u-rwx /usr/local/tomcat/oldwebapps
將 `datainfo.properties` 檔案設定為只讀(如果安裝了 OpenClinica-ws,也對它執行同樣的操作)。
chmod 400 /usr/local/tomcat/webapps/OpenClinica/WEB-INF/classes/datainfo.properties
至此,Tomcat 的訪問控制方面已完成。
還可以做的一件事是將您的使用者新增到 tomcat 組,並授予該組對 usr/local/tomcat 資料夾的讀寫執行許可權。這樣,您仍然可以方便地編輯所有內容,而無需使用 root/sudo。我對它的安全方面確實不確定,請自行承擔風險使用。並且不要忘記在所有配置完成後,將自己從組中移除並刪除許可權。
HTTPS
如上所述,Tomcat 的 SSL 設定指南應該是您首先要做的步驟(https://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html)。您必須確保本指南中列出的所有步驟都使用 `tomcat` 使用者執行,因為如果以其他使用者身份執行,則 .keystore 檔案將建立在該使用者的 home 目錄下,Tomcat 將無法找到並讀取它。理論上,您也可以註釋掉 HTTP 聯結器,因為強制使用 HTTPS 訪問 OC 是最佳實踐。埠轉發將在防火牆級別啟用,因此理論上 Tomcat 永遠不會收到對埠 8080 的請求,但我還沒有實際測試過。
配置完成後,您應該能夠使用 HTTPS 與您的 Web 伺服器通訊(在 https://:8443/OpenClinica 上)。如果您使用的是自簽名證書,您的瀏覽器會發出警告,但您仍然可以訪問該站點。您可以在 Tomcat 中強制使用 HTTPS,方法是在 `tomcat/conf` 下的 web.xml 檔案末尾新增以下內容(在 `` 標記之前)
<security-constraint>
<web-resource-collection>
<web-resource-name>Protected Context</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
Cookie、自定義錯誤頁面、停用列表等
這些是良好的實踐,但不是必須的。這些包括隱藏錯誤頁面中的伺服器版本或停用檔案系統列表,以更好地保護您免受 DDoS 攻擊。
以下所有內容都需要新增到 `web.xml` 檔案中。
安全且僅限 HTTP 的 Cookie,以防止 XSS 攻擊
(貼上到 `` 標記之前)
<cookie-config> <http-only>true</http-only> <secure>true</secure> </cookie-config>
自定義錯誤頁面
(貼上到 `` 標記之前)(由於 Tomcat 無法找到錯誤頁面檔案,因此不會顯示任何錯誤頁面,但它確實透過隱藏版本號完成了工作。如果這對您來說是個問題,請跳過此步驟。)
<error-page> <error-code>404</error-code> <location>/error.jsp</location> </error-page> <error-page> <error-code>403</error-code> <location>/error.jsp</location> </error-page> <error-page> <error-code>500</error-code> <location>/error.jsp</location> </error-page> <error-page> <exception-type>java.lang.Exception</exception-type> <location>/error.jsp</location> </error-page> <error-page> <exception-type>java.lang.Throwable</exception-type> <location>/error.jsp</location> </error-page>
只讀資源和無列表
(貼上到檔案中的 `DefaultServlet` 部分)
<init-param> <param-name>readonly</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>listings</param-name> <param-value>false</param-value> </init-param>
server.xml
移除伺服器標語
如果在聯結器的引數列表中新增 `Server=" "` 引數,則會隱藏 HTTP 標頭中的版本號。它應該看起來像這樣
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol" SSLEnabled="true" maxThreads="150" scheme="https" secure="true" Server =" " address="<webserver IP address or localhost>" clientAuth="false" sslProtocol="TLS" keystoreFile="${user.home}/.keystore" keystorePass="<your keystore pass>" />
更改關閉命令
為了防止攻擊者能夠關閉您的伺服器,您應該考慮更改關閉埠以及關閉命令。您可以在 `server.xml` 檔案開頭,`` 標記內執行此操作。
AJP 聯結器
如果 OC 是唯一將部署到 Tomcat 中的 Web 應用程式,您可以安全地註釋掉 AJP 聯結器行,因為 OC 沒有使用此聯結器。
可能良好的實踐,但對我造成了問題
停用自動部署
為了防止有人在您的 Tomcat 例項中自動部署他們自己的惡意 Web 應用程式,您可以在 `server.xml` 檔案中關閉自動部署,方法是在 `` 標記內將以下引數設定為 false。
autoDeploy="false" deployOnStartup="false" deployXML="false"
這樣,如果重新啟動伺服器,則必須手動部署 OC,您需要弄清楚如何操作。
安全容器
使用 Tomcat,您可以選擇在一個容器中啟動您的例項,這確保了即使在最壞的情況下有人入侵伺服器,他們也只能訪問此容器內的資源和檔案。但是,您需要花費時間才能使它在 OC 上工作,因為它已知會(並且對我來說)破壞安裝。如果您有時間和知識使其工作,那麼這可能是值得的。
否則,用法非常簡單,在啟動 Web 伺服器時新增 `-secure` 標誌
/usr/local/tomcat/bin/startup.sh -secure
Tomcat 部分到此結束。
PostgreSQL
在安全性方面,您可以為 PostgreSQL 配置的內容不多,但也可以進行一些訪問控制。
更改 pgsql 資料夾的所有權
sudo chown -R postgres:postgres /usr/local/pgsql
更改許可權
sudo chmod -R 700 /usr/local/pgsql
您還應該仔細配置 `/usr/local/pgsql/data/` 中的 `pg_hba.conf` 檔案。此檔案控制對資料庫的不同訪問許可權。您需要為本地連線的 clinica 使用者授予對 openclinica 資料庫的訪問許可權,但阻止所有其他連線嘗試。身份驗證方法應設定為 `md5`,切勿使用 `password`,因為它會以明文形式傳送密碼。如果要從遠端機器直接訪問資料庫,則需要在此處新增相應的行。
# TYPE DATABASE USER CIDR-ADDRESS METHOD # allow user clinica to connect to openclinica locally, using encrypted password based authentication (needed to automate backups) local openclinica clinica md5 # IPv4 local connections: host openclinica clinica 127.0.0.1/32 md5 # "local" is for Unix domain socket connections only local all all reject # IPv6 local connections: host all all ::1/128 reject
此配置對於下面將描述的自動備份也很重要。
防火牆
為任何 Web 伺服器設定防火牆都是必須的。這允許您限制和監控伺服器與外部世界之間發生的所有流量。此處的主要目標是僅開啟 Web 應用程式正常執行所需的埠。在本例中,這意味著
- 埠 80/tcp,預期接收傳入的 HTTP 流量,
- 埠 443/tcp,預期接收傳入的 HTTPS 流量,
- 埠 22/tcp,SSH 流量正在進行。
您可能需要進行一些嘗試和錯誤,以檢視關閉某個埠是否會中斷任何內容,但對我來說,僅允許這 3 個埠即可。
如果您已經熟悉使用FirewallD,可以跳到下一節(**設定FirewallD**)。
CentOS預裝了FirewallD,這是一個強大的工具,用於管理這些連線。網上有很多資源可以幫助您瞭解更多資訊,例如這個。
(更新:本文中描述的一種現象已過時。無法由其分配的區域處理的資料包不會“向上踢”到下一個區域(“區域漂移”的概念)。它被認為是不安全的,將在未來版本的FirewallD中移除。如果您確實希望擁有此行為,可以在FirewallD的配置檔案中啟用區域漂移)
首先確保firewalld已安裝並在您的系統上啟用。啟用的預設區域是`Public`,出於我們的目的,您可以保持這種方式。您可以檢查此區域中預設啟用了哪些服務
sudo firewall-cmd --zone=public --list-all
服務不是一些特殊的實體,它們僅僅代表給定服務能夠正常執行所需的開放埠。這些在`/usr/lib/firewalld/services`下定義為不言自明的xml檔案。如果您想定義自己的服務,可以透過將這些xml檔案之一複製到`/etc/firewalld/services`並根據自己的需要自定義它來實現。您可以透過以下方式將任何服務新增到防火牆區域
sudo firewall-cmd --zone=public --add-service=<您的服務> --permanent
您可以透過以下方式刪除任何不必要的服務
sudo firewall-cmd --zone=public --remove-service=<不必要的服務> --permanent
您還可以直接新增/刪除所需的埠
firewall-cmd --zone=public --add-port=<您的自定義埠號>/tcp --permanent
如果沒有`permanent`標誌,一旦FirewallD重新載入或重啟,更改將被重置。您可以在沒有標誌的情況下試驗規則,一旦您發現適合您的規則,就可以透過新增`--permanent`標誌來最終確定這些規則。
以下配置假設您使用ssh訪問遠端伺服器,但是,如果不是這種情況,您可以跳過設定內部區域。
防火牆將設定三個區域:public、internal和trusted。public應處理來自任何請求IP地址的所有http/s請求。internal區域應新增一個源,其中包含您的IP或MAC地址,因此(理論上)只有當您的機器與伺服器通訊時,此區域才會處理資料傳輸。這也是啟用了ssh服務的區域(=開啟埠22)。
在開始配置FirewallD之前,您應該確保iptables已停用並阻止其透過遮蔽它而啟動。否則它可能會干擾FirewallD並導致一些奇怪的行為。
systemctl mask iptables
systemctl disable iptables
首先從public和internal區域刪除任何不必要的服務。使用`--list-all`標誌檢視當前允許的內容。您應該只保留(或新增,如果需要)http/https。在internal區域中,還要新增ssh服務。
您應該將面向外部的網路介面分配到public區域(因此來自外部的所有請求都將由此區域處理)。您可以透過以下方式列出所有可用的介面
ip link show
您可以使用`--add-interface=<介面>`標誌新增介面。
不幸的是,這些介面的命名並不簡單(至少對我來說,我的叫`ens192`),因此您可能需要做一些研究才能瞭解情況。
您還應該將自己的IP/MAC新增到internal區域的源中,以便只有來自此IP/MAC地址的請求才會由此區域處理,例如
sudo firewall-cmd --zone=internal --permanent --add-source=154.112.12.18
如果您希望從某個特定的VPN使用ssh,也可以使此IP更通用
sudo firewall-cmd --zone=internal --permanent --add-source=154.112.0.0/16
這將允許154.112.0.0-154.112.255.255中的任何人使用ssh。(請注意,只有當至少分配了一個介面或源時,區域才會處於活動狀態!)
public區域的目標應設定為DROP,這在請求到達無效埠時不會返回任何訊息,而不是傳輸拒絕訊息。這被認為更安全。
sudo firewall-cmd --permanent --zone=public --set-target=DROP
接下來,建立埠轉發規則以限制與https的通訊,並適應Tomcat的埠約定(它使用8080而不是80,使用8443而不是443)
sudo firewall-cmd --zone=public --permanent --add-forward-port=port=443:proto=tcp:toport=8443 sudo firewall-cmd --zone=public --permanent --add-forward-port=port=80:proto=tcp:toport=8443 sudo firewall-cmd --zone=internal --permanent --add-forward-port=port=443:proto=tcp:toport=8443 sudo firewall-cmd --zone=internal --permanent --add-forward-port=port=80:proto=tcp:toport=8443
要使埠轉發工作,您還需要啟用偽裝(https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/security_guide/sec-port_forwarding)
sudo firewall-cmd --zone=public --add-masquerade --permanent
sudo firewall-cmd --zone=internal --add-masquerade --permanent
現在這一步我比較不確定,因為我找不到太多關於它的資訊。我將lo(環回)介面分配到trusted區域。這是從同一臺機器(localhost,127.0.0.1)與您的Web伺服器通訊的介面。理想情況下,這是外部世界無法訪問的,因此我假設trusted區域適合它,但同樣,我在這裡可能錯了。
如果您需要ping工作,請執行此命令(將區域替換為您需要ping工作的區域)
sudo firewall-cmd --permanent --zone=<您的ping區域> --add-rich-rule='rule protocol value="icmp" accept'
您必須重新載入firewalld才能使更改生效
sudo firewall-cmd --reload
現在您已將FirewallD配置為僅允許與外部世界的http/s通訊,但仍允許從您的個人計算機/您的VPN網路建立ssh連線。
您可以使用nmap軟體包測試您的防火牆,以檢視哪些埠已開啟。
您已經完成了大部分使OC安全的工作,但您仍然可以在OC本身中做一些事情。如果您以root身份登入Web介面,導航到`任務/管理/使用者/配置密碼要求`,將有一些選項可以開啟/關閉並調整以滿足您的需求。您還應該在嘗試x次後啟用使用者鎖定(`任務/管理/使用者/鎖定`)。作為root,如果使用者帳戶被鎖定,您可以在Web介面上解鎖這些帳戶。我自己採取的另一項措施,但不確定是否必要:要求我的OpenClinica例項的使用者將他們的密碼挑戰問題設定為一個長(不可猜測)的字串。我這樣做是因為我不確定OC如何傳送密碼重置電子郵件,以及此電子郵件是否可能被潛在攻擊者劫持。一個更安全(儘管承認更不方便,如果您有太多使用者甚至不切實際)的解決方案是以root身份從Web介面重置使用者的密碼並自行傳送給他們。
這確實也應該是必須的。我在這裡分享的解決方案只是一種方法,如果您有更好的方法,請隨時按照自己的方式操作。
這裡有一份指南是關於如何在OC中實施備份的指南。基本上,您希望定期儲存您的OC配置檔案、您的研究目錄($TOMCAT_ROOT/openclinica.data)和您的PostgreSQL資料庫。
我附加了一個指令碼,如果執行該指令碼,它應該備份所有這些內容,將它們打包成一個tarball檔案並將其儲存到`/usr/local/OpenClinica_backups`。您可以(也應該)透過編輯指令碼中的BCKP_path變數來更改備份位置以使其位於伺服器外部。此外,您還需要建立一個.pgpass檔案才能使其工作,更多詳細資訊如下。
我對上述連結指南的補充是使這些備份自動發生,例如每天一次。為此,我使用了`cron`服務,該服務在CentOS 8上預裝。
要使您的指令碼每天執行,請將其放在`/etc/cron.daily/`下。通常,要能夠獲取pg_dump,您需要openclinica資料庫的密碼。要允許自動更新,您需要在`/var/lib/pgsql/`下建立.pgpass檔案。其內容應如下所示
localhost:5432:openclinica:clinica:<您的資料庫密碼>
為了使Postgres能夠使用此檔案,它必須由postgres擁有
sudo chown postgres:postgres .pgpass
並且其許可權必須設定為0600
sudo chmod 0600 .pgpass
如果您在身份驗證方面遇到任何問題,請參閱pgpass的文件[5]。
為了能夠建立pg_dump,postgres需要能夠寫入您的備份資料夾。將資料夾的組更改為postgres並授予組rwx許可權
sudo chown root:postgres <您的備份資料夾>
sudo chmod g+rwx <您的備份資料夾>
您應該練習恢復資料庫以瞭解它是如何實際完成的。上面提到的指南可以幫助您完成此操作。
有一個優秀的GitHub倉庫,它允許您執行每日掃描以檢測各種惡意軟體,包括特洛伊木馬、病毒或rootkit。如果您將克隆儲存庫中的指令碼放在/etc/cron.daily下。它將與自動備份指令碼一起每天執行。
為了清楚起見,最好停用tomcat、clinica和postgres使用者的登入
usermode -L tomcat usermode -L clinica usermode -L postgres
幹得好,您剛剛使您的 OpenClinica 安裝更加安全!不幸的是,您必須記住,我們一直在加固的軟體是過時的軟體(非常過時),因此您只能做這麼多並希望一切順利。我所能給出的最佳建議是,如果可能,不要包含受試者的資訊,這些資訊可以識別他們。這樣,即使一切失敗,至少您的受試者也不必擔心個人身份盜竊。
#!
BCKP_path='/usr/local/OpenClinica_backups'
DATE=`date +"%Y-%m-%d"`
cd $BCKP_path
# create a database dump with pg_dump
sudo -u postgres /usr/local/pgsql/bin/pg_dump -U clinica openclinica -w > pg_dump
# backup the data directory of OC with CRF, XML, etc.. data
sudo tar -cf oc_data.tar /usr/local/tomcat/openclinica.data
# backup OC configuration
sudo cp /usr/local/tomcat/openclinica.config/datainfo.properties datainfo.properties
# tar all the above created files and assign a date
sudo tar -czf ${DATE}_openclinica_backup.tar.gz datainfo.properties oc_data.tar pg_dump
# remove created temporary files
sudo rm datainfo.properties
sudo rm oc_data.tar
sudo rm pg_dump
# add a bit of security
sudo chmod 400 *.tar.gz