---
# System prepended metadata

title: 網路安全（network security）
tags: [Server管理]

---

# 網路安全（network security）
[TOC]
## 定義
### <a href = "https://www.ieee.org/">IEEE</a> (Institute of Electrical and Electronics Engineers) 的 paper
一種廣泛的模式，利用不同技術與設備去設定一系列的規則，以確保資料的機密性（Condfidentiality）、完整性（Integrity）、可存取性（Accessibility）。
- Condfidentiality
    - 確保資料不能被未授權的攻擊者存取。
    - ex. 你的情書不能被其他人想看就看
- Integrity
    - 確保資料沒有被攻擊者竄改
    - ex. 你的情書不能被改成是喜歡別人
- Accessibility
    - 資料是否可以被正常存取
    - ex. 你的情書不能因為被別人撕掉就沒辦法正常看
### 抽象
- 對大眾來說，較常見的有網路安全問題的例子有以下
    - 帳號被盜用
    - 隱私檔案被竊取
- 最近遇到的例子
    - 成大工資管的書審上傳系統
        - ![image](https://hackmd.io/_uploads/rJh_Nfwpp.png)

## 常見攻擊手法 
### 暴力破解（Brute-force attack）
窮舉出所有可能的帳號密碼的字元組合，以找出正確的帳密，通常會利用大量的計算資源以加速計算過程。
通常會用字典檔來更有效率地破解（字典攻擊）
- 字典檔
    - 包含一些常見的密碼組合，也可以利用工具（ex. crunch）針對特定的系統製作特定的字典檔
    - 常見的字典檔
        - rockyou.txt
            - kali linux 內建提供，一間做社交軟體的 rockyou 公司因 SQL 漏洞而被駭入而外流的真實用戶的密碼檔
                - kali linux：駭客常用的 linux，內含許多攻擊的工具
            - 從此密碼檔發現最受使用者青睞的五大懶人密碼依序是 123456, 12345, 12345689, password, iloveyou。統計之後發現，有近 50% 的使用者選用名字、字典中的單字或鍵盤上鄰近的字母作為密碼。
                - https://www.ithome.com.tw/node/59281
            - https://github.com/brannondorsey/naive-hashcat/releases/download/data/rockyou.txt
- 實作：使用 Metasploit
    - Metasploit
        - https://www.metasploit.com
        - 一個開源的框架，提供多種工具以用來尋找系統漏洞、滲透測試
        - 安裝
            - `curl https://raw.githubusercontent.com/rapid7/metasploit-omnibus/master/config/templates/metasploit-framework-wrappers/msfupdate.erb > msfinstall && chmod 755 msfinstall && ./msfinstall`
        - 執行
            - `msfconsole`
        - ssh brute force
            - 先來用 nmap 看看要攻擊的目標主機（192.168.67.185）的 ssh 開在哪一個 port
                - nmap
                    - 可以掃描一台主機有哪些 port 是對外開放的
                    - 安裝
                        - `sudo apt install nmap`
                    - 預設掃描的 port : 1-1023 
                    - 常用參數
                        - -p : 指定掃的 port
                            - 單個 : `nmap -p 80 192.168.1.1`
                            - 範圍 : `nmap -p 80-200 192.168.1.1`
                        - -A : 作業系統與各種服務的版本
                    - reference
                        - https://blog.gtwang.org/linux/nmap-command-examples-tutorials/
                - 掃描結果
                    - ![image](https://hackmd.io/_uploads/BJFgMEyAa.png)
                    - 可以知道 ssh 可能在其中一個 port

            - 選擇 ssh brute force 要用的模組：`use auxiliary/scanner/ssh/ssh_login`
            - 查看有哪些必要或非必要的參數要設定：`show options`
                - `set stop_on_success true`
                - `set verbose true`
                - `set user_file /home/s109213059/ssh_burst/user.txt`
                - `set pass_file /home/s109213059/ssh_burst/pwd.txt`
                - `set rhosts 192.168.67.185`
                - `set rport 21042`
            - 設定完之後就可以攻擊：`exploit`
                - ![image](https://hackmd.io/_uploads/HyTHgEk06.png)
### 零時差攻擊（Zero-Day Vulnerability）
利用系統未修補漏洞（vulnerability）的期間，針對漏洞進行攻擊（exploit），可能是因漏洞的補丁（patch）未發行，或是系統管理員沒有及時將系統更新到沒有漏洞的版本。
- 漏洞查詢
    - CVE (Common Vulnerabilities and Exposures)
        - 由美國非營利組織 MITRE 所屬的 National Cybersecurity FFRDC 所營運維護的資料庫，收集各種資安弱點及造成的漏洞並給予編號以便於搜尋
        - 查詢漏洞的 CVE detail : https://www.cvedetails.com
    - exploit-db
        - 此資料庫中有許多漏洞的實際的攻擊腳本
        - https://www.exploit-db.com
- 漏洞種類
    - RCE (Remote code Execution)
        - 攻擊者在遠端利用系統漏洞執行指令
        - ex. 寫入一個 Web Shell 到網頁上
        - 小實驗：https://www.exploit-db.com/exploits/50580
    - XSS (Cross-Site-Scripting)
        - reflected：受害人點擊 url，網頁直接執行 url get 的 query string
        - storaged：將 js script 存到 serrver，每個 user 點開 site 就會執行
            - 在前後端用套件過濾 user 的輸入
                - ex. DOMPurify
            - 避免用 innerHTML : 雖然 innerHTML 不會去執行內容的 <script> tag，但可用 button, img 等方式執行 script。但有時候要幫內容加 tag 還是要用 innerHTML
                - sol : 用 textContent 過濾再放入使用者內容，再用 innerHTML 加上 html tag
        - 實際範例的教學：https://xss-game.appspot.com/level1
    - SQL injection
        - user 輸入惡意 sql 指令
            - 後端寫法：`'select * from users where uid =' + user_id + ' and password =' + user_pwd + ';' `
            - user 輸入：`;drop table users;--`
                - 直接把 users 這張 table 刪掉
        - sol
            - 後端執行 sql 時帶入參數用 placeholders
            - 限制輸入格式
                - regex
            - 使用 ORM (Object Relational Mapping) 取代 raw sql
                - ORM : 用框架定義好的物件去存取資料庫
    - CSRF (Cross-Site Request Forgery)
        - 利用社交工程，讓受害者點惡意網站，惡意網站裡面去抓受害者的 cookie，再發 request(可以用 ajax、axios 就不會跳轉，讓受害者無法發現) 到那個 cookie 對應的網站做一些有了受害者權限才能做的事
            ![](https://i.imgur.com/EtnD0WO.png)
            - ref : https://dotblogs.com.tw/joysdw12/2013/09/16/asp-net-cross-site-request-forgery
        - ex. 某個網站的 form 用 get
            - https://example.com/delete?id=3
        - 防範方法
            - 一般使用者
                - 不要點奇怪的網站
                - 盡量不要保持登入，登入完就登出（清除 cookie）
            - server 端
                - server 端 check request referer，若不是相同來源就 drop 掉 request
                    - ![](https://hackmd.io/_uploads/BktHUIIGT.png)
                - cors
                    - 限定 request 的 origin 需是授權的
                    - 只在 browser 有用，因是 browser 去做判斷是否符合 policy，所以用 postman 之類的直接發送 request 就沒用
                    - simple request
                        - method = get, post, head
                        - 不合 policy，browser 會送出 request 但不把 response data 給 js（但還是會在 server 端執行，所以只用 cors 不夠，還要搭配上面的才安全）
                    - preflight request
                        - 觸發條件
                            - ![](https://hackmd.io/_uploads/SymCsL8M6.png)
                                - https://vii120.coderbridge.io/2020/11/16/preflight-request/
                            - method = put, delete

                        - browser 會先問 server request 是否符合 policy, 符合才送
                        - 所以會有 2 個 request
                            - ![](https://hackmd.io/_uploads/BJeKs88zT.png)
                - csrf token
                    - 每個 form 每次新的頁面都會有一組 token，後端會先驗證此 token 是否一致
### 社交工程（Social Engineering）
- 利用人性弱點，應用簡單的溝通和欺騙技倆
- ex.
    - 給我帳號密碼，我幫你儲值
    - 恭喜你中獎了，點擊這個網站來領獎
- 防範方式
    - 多查證，不要輕易地給別人帳號密碼
    - 不要亂點網站、檔案

## 得到資源後的用途
當未授權的攻擊者可以隨意存取資料或主機，可以有許多用途

### 勒索
使用對稱式加密加密資料後勒索受害人，須支付一定贖金才能將資料解密
- 預防方式
    - 重要資料要備份於其他網路下的裝置
### 挖擴
在受害者的 Server 上植入挖擴軟體，以利用 Server 的資源挖擴賺錢
                                  
分享系上主機被植入挖礦病毒：Multios.Coinminer.Miner
- 如何發現
    - 系網載入的速度過慢，以及 Server 執行指令速度也很慢
        - 利用 `top` 看到某個 process 的 cpu 使用率很高
    - 看一下連線狀況（包含開放的連線和<b>對外</b>的連線）：`sudo nestat -anpt`
        - ![](https://hackmd.io/_uploads/B16jcN0gp.jpg)
            - 持續挖擴（因到某個荷蘭知名的挖擴 ip 的 443 port）
            - 查看挖礦的惡意程式 process
                - `cd /proc/{pid}` : 查看 process 內容
                - `sudo ls -l exe` : 查看執行檔真正位置
                    - ![](https://hackmd.io/_uploads/SkiAaVReT.png) 
- 如何解決
    - 利用 `ps` 發現被 temp 執行 3 隻 program
        - ![](https://hackmd.io/_uploads/BkJ-jEAlT.png)
        - ![](https://hackmd.io/_uploads/rJ5-o4RxT.png)
        - ![](https://hackmd.io/_uploads/H1Qms4Rx6.png)
        - 都先砍掉 `sudo kill -9 {pid}`
        - hacker 使用 temp 這個 user
            - ![](https://hackmd.io/_uploads/B17KsEAga.png)
                - 檔案皆為隱藏檔 `.`，要 `ls -a`
                - 且被植入後門金鑰
                    - ![](https://hackmd.io/_uploads/r13i2NRxT.png)
                    - 先砍掉
        - crontab 也有執行惡意腳本排程
            ```=
            5 6 * * 0 /home/temp/.configrc5/a/upd>/dev/null 2>&1
            @reboot /home/temp/.configrc5/a/upd>/dev/null 2>&1
            5 8 * * 0 /home/temp/.configrc5/b/sync>/dev/null 2>&1
            @reboot /home/temp/.configrc5/b/sync>/dev/null 2>&1
            0 0 */3 * * /tmp/.X291-unix/.rsync/c/aptitude>/dev/null 2>&1
            ```
            - 先砍掉 : `sudo crontab -e -u temp`
        - sol
            - 這個病毒滿多人是因為 ssh 破解
                - 更新 `temp` 使用者的密碼
                - 設定 sshd 的 fail2ban
                    - 5 次就 ban ip
        - ref
            - https://askubuntu.com/questions/1224927/cpu-100-with-kswapd0-process-although-no-swap-is-needed

### Mail Server 跳板機
利用受害者的主機和網路資源，大量發送包含惡意網站的連結或是其他垃圾內容的信件。也會造成受害的 Server 的 domain 被列為黑名單，導致正常發送的信件無法正常被接收，以及造成 Server 上的其他正常服務可能無法正常存取

又來分享系上主機遇到的事情：
- 如何發現
    - 系網因為 Server 都把資源用在大量寄送郵件而直接無法正常存取，系辦姐姐狂 call（所以我後來自己寫了監控腳本）
    - `sudo netstat -anpt` : 有奇怪的 port 有大量流量一直到奇怪的 ip 的 25 port(SMTP)
- 如何解決
    - 暫時方法
        - `sudo ps aux | grep program_name` : 找到送 mail 的惡意 process，然後 `kill` 掉。
            - 但是有其他的 process 監控，所以會馬上自己重建起來繼續送 mail
        - 因為資源幾乎全用在傳送大量郵件，導致連下正常指令都須跑很久，所以先用防火牆 drop 掉一些往特定網段的流量
    - 根本方法
        - 依據 process 找出漏洞

### 網站植入惡意連結
藉由在正常的網站中植入惡意網站的連結，或是會導向惡意網站

分享系網（使用 Wordpress）遇到的事情：
- 如何發現
    - 計中通報
    ![image](https://hackmd.io/_uploads/ryzz-tqp6.png)
    - 而且後來發現除了系網以外，其他網站（ex. 系學會網站）也被植入
    - 所以我後來有寫一隻腳本檢查有沒有惡意的檔案，因為 Wordpress 中大多是在 `wp-content/uploads` 內被植入
- 如何解決
    - 查看 wordpress 使用的套件之中是否有套件的版本在 CVE 當中是有嚴重漏洞的（ex. RCE）
    - 都找不到有漏洞的套件，也不太確定是由 Server 中哪個網站的漏洞所造成，所以先將惡意檔案移除後，用 container 將各個網站隔離開來
    - 將各個網站隔離開來後，發現只有系網仍會被植入，且在 wordpress 中新安裝的防火牆顯示有被來自奇怪 ip 登入帳號的狀況
    - 最後我將 wordpress 設定限制登入失敗的次數，到現在都是正常的

## 攻擊防範方式
### 限制存取
就像上面提到，若沒有限制存取失敗的次數，攻擊者可以藉由暴力破解來找到真正的帳號密碼。且有些服務是不能讓未授權的人存取。
- fail2ban
通過監視系統日誌中的活動以辨識不符合規則的行為，並且將不合規則的 ip 和對應的處理方式寫入防火牆
    - 安裝：`sudo apt install fail2ban`
    - 啟動：`sudo systemctl start fail2ban`
        - 預設保護 sshd
    - 開機啟動 : `sudo systemctl enable fail2ban`
    - 設定檔 : 
    - 預設路徑 : `/etc/fail2ban/jail.conf`
    - 先複製設定檔成 `jail.local`，因為如果更新 fail2ban，`jail.conf` 的內容會被更新，而且 `jail.local` 會覆蓋 `jail.conf`，所以以後的設定檔就直接去改 `jail.local` 就可以: 
        - `sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local`
    - [DEFAULT] 是所有服務共用的設定，如果是針對特定的服務如 [sshd]，若有重疊的部分會直接覆蓋 [DEFAULT] 的。但若要啟用特定服務，要把 enabled = true。
        - ex. sshd
        ```conf=
        [DEFAULT]
        ignoreip = 127.0.0.1/8 999.999.999.0/24 888.888.888.0/24

        [sshd]
        enabled  = true
        port     = ssh # 如果 ssh 開在別的 port 這邊要改成改的 port
        filter   = sshd
        logpath  = /var/log/auth.log
        maxretry = 5
        findtime = 600
        bantime  = 1200
        ```
    - 限制設定 : 
        - ex. 預設 : 在 10 分鐘內(findtime) 登入失敗次數超過 5 次(maxretry)，就 ban 10 分鐘(bantime)
        ![](https://i.imgur.com/1Ba2iAn.png)
        - 沒寫單位是秒，分鐘是 m，小時是 h，天是 d
    - 白名單 : 有多個就用空白隔開
        ```config=
        ignoreip = 192.168.56.1 192.168.56.2
        ```
        ![](https://i.imgur.com/64OLEQk.png)
    - filter 
        - 路徑 : /etc/fail2ban/filter.d
        - 用途 : 用來過濾哪一些是此服務失敗的條件(failregex)，fail2ban 預設會有各種服務(ex. ssh、nginx)的 filter 檔
        - ex. ssh 的過濾條件
            - ![](https://i.imgur.com/rbVjhFJ.png)
            - ![](https://i.imgur.com/Jccu8Nm.png)
        - filter 檔的 regex 語法
            - 基本語法
                -  ^ : 比對字串的開始位置
                -  $ : 比對字串的結束位置
                -  ? : 問號前的字元可以出現 0 次或一次。
                    -  ex. colou?r = colour、color
            - 教學 : 
                - https://docs.python.org/3/library/re.html
                - https://www.cyut.edu.tw/~ckhung/b/re/
                - http://it-life.puckwang.com/2016/03/regular-expression.html

    - action 
        - 用途 : 用來決定超過 maxretry 後要採取的行為，預設是只有封鎖 ip
            - 寄信 : 
                - 兩種不同寄信內容
                    - action_mw : 封鎖後寄信通知
                    - action_mwl : 信還會含有whois資訊
                - 更改 action : `sudo vi /etc/fail2ban/jail.local`
                    - ![](https://i.imgur.com/J4lzoLR.png)
                - 更改寄達信箱 : `sudo vi /etc/fail2ban/jail.local`
                    - ![](https://i.imgur.com/6RSkz72.png)
                - 結果
                    - ![](https://i.imgur.com/m99WK2i.png)


    - 查看 fail2ban 管理的項目
        `sudo fail2ban-client status`
        ex. 目前有 ssh 被管理
        ![](https://i.imgur.com/VaXU5CX.png)
        - 查看被管理的項目的狀況(包括哪些 ip 被鎖)
            - `sudo fail2ban-client status sshd`
            ![](https://i.imgur.com/cYe61dv.png)
            - 可以去 /var/log/auth.log 看被登入的狀況(成功和失敗都會記錄)

    - 查看被鎖的 ip 和時間(起始到結束) : `sudo fail2ban-client get sshd banip --with-time`

    - 手動解鎖 ip : 
        - 單一 : `sudo fail2ban-client set sshd unbanip x.x.x.x`
        - 全部 : `sudo fail2ban-client set sshd unbanip --all`
    - 手動增加要封鎖的 ip :
        - `sudo fail2ban-client set sshd banip a.a.a.a x.x.x.x`

    - 手動調整白名單 : 
        - 新增 : `sudo fail2ban-client set sshd addignoreip x.x.x.x`
        - 刪除 : `sudo fail2ban-client set sshd delignoreip x.x.x.x`

    - reference
        - [fail2ban-基本設定及安裝筆記 - 鴉哥手札](https://web.archive.org/web/20211231192318/https://crowsnest1217.com/%e5%ad%b8%e7%bf%92%e8%88%87%e5%88%86%e4%ba%ab/fail2ban-setting.html)
        - https://newtoypia.blogspot.com/2016/04/fail2ban.html
        - https://net.nthu.edu.tw/2009/security:fail2ban

- portSentry
    - 介紹
        - 因為攻擊者可以用 nmap 之類的軟體掃主機的 port，會暴露主機的一些資訊，ex. 某些 port 可以被掃出來是哪些服務、主機的資訊(ex. os)
        所以要對主機是否被掃描做監控，就可以利用這個工具。
    - 安裝
        - `sudo apt install portsentry`
    - 啟動
        - `sudo systemctl start portsentry`
        - `sudo portsentry -atcp`
            - -a : 會檢查主機是否有正在用要檢查的 port，若有就不要監聽該 port
    - 設定檔
        - path : `/etc/portsentry/portsentry.conf`
        - 針對 tcp、udp 的掃描進行動作。
            - ![](https://i.imgur.com/rvsvbSk.png)
            - 0 : 不要限制掃描 
            - 1 : 限制掃描(通常是用這個)
            - 2 : 用自己寫的腳本對掃描進行處置
        - 要監聽的 port
            - 有在用的 port 不要監聽。ex. 22 80 443
            - 基本上用下面這個推薦的就夠了，因為掃描通常是掃描一個範圍，而不是特定 port
                - ![](https://i.imgur.com/eJQ1oBB.png)
        - 對於攻擊者如何處理
            - 直接用防火牆把該 ip 的封包都 drop掉
               ![](https://i.imgur.com/qsxqxi2.png)
                - 結果
                    - 受害者
                        - ![](https://i.imgur.com/4hOXPfG.png)

            - 把攻擊 ip 加入 /etc/hosts.deny
                - ![](https://i.imgur.com/lfIU0dB.png)
                    - 結果
                        - 受害者
                            - ![](https://i.imgur.com/kRsyJtu.png)
            - 攻擊者
                - ![](https://i.imgur.com/eBKt7Yu.png)

    - ignore 檔
        - path : `/etc/portsentry/portsentry.ignore.static`
        - 因為 `/etc/portsentry/portsentry.ignore` 會因 restart 而刷新，然後會依 static 檔建一個新的
        - 新增白名單 ip
            - ![](https://i.imgur.com/8rTlgMX.png)
    - log
        - path
            - `/var/lib/portsentry/`
        - portsentry.blocked.tcp
            - 現在 block 的紀錄(會因 restart 而刷新)
            -  ![](https://i.imgur.com/JF5RGr9.png)
        - portsentry.blocked.udp
            - 現在 block 的紀錄(會因 restart 而刷新)
        - portsentry.history
            - 過去到目前 block 的紀錄
            - ![](https://i.imgur.com/6yd4ZZz.png)
    - refernence
        - https://hackmd.io/@ncnu-opensource/B17djyQs8#PortSentry    

- ssh
因為 ssh 非常常被使用，所以攻擊非常普遍，因此需要對 ssh 重點防護，畢竟若被攻擊者成功用 ssh login，即使該 user 沒有 root 權限，仍有非常大的機會對 Server 造成嚴重的危害（例如使用 Server 資源挖礦、利用其他方式提升 user 的權限）。
    - 更改 ssh port
        - 理由 
            - 預設的 22 port 容易被駭客用暴力破解一直攻擊，雖然有些還是會逐 port 找，但相對較安全
            - ex. 一個有對外 ip 的主機開個幾個小時
                - ssh port 在 22，基本上都是中國的 ip
                    ![](https://i.imgur.com/IzEIXFh.jpg)
                - ssh port 在其他 port
                    ![](https://i.imgur.com/5keCLZa.png)

        - 更改方式
            - 決定要換的 port 
                - 因為有些掃描主機的工具(ex. nmap)預設是掃描 1~1023 比較常用的 port，所以推薦改成 1024~65535。
                - 先找找看要換的 port 是不是有在用了
                    - ex. 要換用 21042 : `sudo netstat -tupln | grep 21042`
            - 改成要換的 port
                - `sudo vi /etc/ssh/sshd_config`
                    - OpenSSH server 預設啟動會去讀 `/etc/ssh/sshd_config` 的參數
                - ![](https://i.imgur.com/unwWECj.png)

            - 開防火牆 port，我是用 ufw
                - 如果還沒開 : `sudo ufw enable`
                    - 記得加一些會用的 port，ex. 443, 80
                - 看一下 : `sudo ufw status`
                - 加入新的 ssh 的 port : `sudo ufw allow 21042/tcp`
                - `sudo ufw reload`
            - `sudo service sshd restart`

        - reference
            - https://www.cyberciti.biz/faq/howto-change-ssh-port-on-linux-or-unix-server/
            - https://xenby.com/b/258-%E6%95%99%E5%AD%B8-ufw-%E9%98%B2%E7%81%AB%E7%89%86%E8%A8%AD%E5%AE%9A%E8%BB%9F%E9%AB%94%E6%93%8D%E4%BD%9C%E6%8C%87%E5%8D%97

    - 限制 ssh 登入 ip（黑/白名單）
        - 一般規則
            - 語法
                - sshd(其他服務也可):(ip/netmask)
            - /etc/hosts.allow : 可通過的 ip
                ```config=
                sshd:163.22.32.0/255.255.255.0 163.22.17.179
                ```
            - /etc/hosts.deny : 要擋掉的 ip
                ```config=
                sshd:ALL
                ```
        - 另一種寫法，都寫在一起
            - `sudo vi /etc/hosts.allow`
                - 語法
                    - sshd:(ip/netmask):(allow||deny)
                - ex. 
                    - ![](https://i.imgur.com/2BKMjUf.png)

        - reference
            - https://hackmd.io/@ncnu-opensource/B17djyQs8#%E7%99%BC%E7%8F%BE%E5%95%8F%E9%A1%8C%E5%88%86%E6%9E%90-log-

    - ssh 取消密碼登入，只能用金鑰 
        - 理由
            - 開著 port 讓別人連總是有風險
        - 在本地產生 ssh 金鑰 : `ssh-keygen -t rsa`
            - 私鑰(自己留) : `.ssh/id_rsa`
            - 公鑰(給別人) : `.ssh/id_rsa.pub`

        - 伺服器端加入本地的公鑰 : 
            - 複製本地的公鑰 : `sudo vi ~/.ssh/id_rsa.pub`
            - 貼到伺服器端 :`sudo vi ~/.ssh/authorized_keys`

        - 拒絕用密碼登入
            - `sudo vi /etc/ssh/sshd_config`
                - `PasswordAuthentication no`
                - ![](https://i.imgur.com/tjjJ52j.png)
            - `sudo service ssh restart`

        - 結果
            - ![](https://i.imgur.com/OJZcTSG.png)

        - reference 
            - https://hackmd.io/@ncnu-opensource/book/https%3A%2F%2Fhackmd.io%2F7kiV5QwqT3y7L46EZF8DQQ#%E4%BD%BF%E7%94%A8%E6%86%91%E8%AD%89%E4%BE%86%E9%81%A0%E7%AB%AF%E9%80%A3%E7%B7%9A
                  
### 檢查是否存在惡意程式
藉由即時檢查 Server 中是否有惡意程式、rootkit 在執行，可以降低惡意程式所帶來的損害
- rootkit : 藉由機器上某些服務的漏洞來取得 root 權限的程式，可能藉由改某些程式(ex. `ps`)來隱藏自己
    - 如何隱藏
        - 如果取得 root 權限，可以藉由載入惡意模組(可以過濾掉特定 pid)，重新編譯核心，然後再呼叫惡意模組，輸入要過濾掉的 pid
        - reference
            - https://github.com/DanielNiv/Process-Hiding-Rootkit
    - 若中了的解決方法 : 因 rootkit 善於隱藏，所以最好備份後重灌系統

- rkhunter
    - 找 rootkit 方式
        - 利用檔案獨有的指紋資料(md5 編碼)，rkhunter 一開始會有各種服務的原始的指紋資料，只要檔案有被更動，就會和原本的編碼不一樣。
            - md5 : 雜湊，相同內容會得到同一組編碼，不相同內容很大機率不會得到同組編碼
            - ![](https://i.imgur.com/CD6pBfs.png)
            - reference
                - https://ithelp.ithome.com.tw/articles/10193762
        - 檢查重要二進位檔案的權限 : 
            - 因為系統實際在執行的是編譯後的二進位檔案，這些通常會是 755 的權限，不能被其他人更改。但 rootkit 為了要方便控制系統，所以可能直接改這些二進位的檔案的權限成 777
        - 檢查隱藏檔案(.xxx) 
            - ![](https://i.imgur.com/Mol61iZ.png)
        - 檢查有沒有被奇怪的程式占用的 port
        - 檢查有沒有特定惡意程式的檔名或目錄

    - 安裝
        - `sudo apt install rkhunter`

    - 執行
        - `sudo rkhunter`
        - 常用參數
            - `--checkall (-c)` : 全系統全部項目都檢測
            - `-cronjob` : 用 crontab 自動跑
                - ex. 每天 8 點 30 分執行一次
                    - `30 8 * * * rkhunter --checkall --cronjob`
            - `--report-warnings-only` : 只報出有問題的，正常的不顯示
            - `--skip-keypress` : 自動執行，不用一部分檢查完再按 enter 才能檢查下一部分
            - `--versioncheck` : 用最新版的 rkhunter
    - reference
        - https://linux.vbird.org/linux_server/others/0420rkhunter.php#whatisrk
                  
### 防火牆
管理主機的網路流量，包含：過濾掉不符合規則的封包、轉送封包到指定的主機
#### iptables
- 介紹
    - Linux 上常見的防火牆套件
- 架構
    - 由 table、chain、rule 組成
    - table 裡有不同 chain，chain 裡有不同 rule，每條 rule 都有一個 target
- table
總共有 5 種 table
    - filter : 預設使用的表，用於過濾封包(常用)
    - nat : 用於 IP 或 port 轉換(常用)
    - mangle : 用於修改封包內容(ex : 改封包 header)
    - raw : 用於停止追蹤封包
    - security : 用於設定 SELinux 對單個封包或整個連線的處理
- chain
    總共有 5 種 chain，不同 chain 代表封包抵達 Server 後的不同時間點
    * PREROUTING : 進行路由前 (封包決定要往哪邊走之前)
    * INPUT : 要進入主機的封包（封包的目的地 ip 是本地的 Server）
    * FORWARD : 轉送的封包
    * OUTPUT : 從主機送出的封包
    * POSTROUTING : 進行路由後 (封包決定要往哪邊走之後)
    ![](https://i.imgur.com/zIHqiY8.png)
        - filter
            - 過濾封包
            - chain : input, output, forward（封包不會進到本機，會馬上被轉送出去）
        - nat (network address translation)
             - 來源與目的之 IP 或 port 的轉換
             - chain : output, prerouting, postrouting

            ![](https://i.imgur.com/AGAcKFX.png)
            * 外網 IP 的位址數量不夠用 -> 使用內網 IP
            * 外網 IP 無法連線內網 IP (找不到) -> NAT 來轉換
            * 主要的 NAT 種類有 SNAT、DNAT、MASQUERADE
            - SNAT
                > Source NAT
                > 在路由後（POSTROUTING）將來源 IP 從內網 IP 位址修改為 NAT 主機的外網 IP 位址
                ##### 情境 : 內網主機(192.168.1.100)要連線到外網(域名 tw.yahoo.com)
                ![](https://i.imgur.com/BbOi9ph.png)
                1. 來源 192.168.1.100 傳遞封包給NAT主機
                2. NAT 發現目的地不是內網，透過路由轉到外網網卡
                3. 因為內網和外網不能互通，所以在 POSTROUTING 透過 NAT 把來源 IP 從內網 IP 換成外網 IP ，另外 conntrack 會在 NAT translation table 把這兩個（內網主機和 NAT）來源 IP、port 的對應關係記錄起來，之後回應封包傳回來時就能知道要傳給內網的哪台主機
                ##### 情境 : 外網(域名tw.yahoo.com)回傳封包給內網主機(192.168.1.100)
                ![](https://i.imgur.com/yZAnOim.png)
                4. 來源外網傳遞封包給 NAT 主機
                5. NAT 主機收到外網的回應封包後，會分析封包的序號，並比對前面存到 NAT translation table 的資料，就會發現這個封包是內網主機(192.168.1.100)之前傳送出去的，就會透過 PREROUTING 把目的 IP 從外網 IP 改成內網主機的 IP 192.168.1.100
                6. 封包會傳送到 192.168.1.2 這個內網網卡，然後再傳送到目的地192.168.1.100 的內網主機(完成連線！)
            - MASQUERADE
                > 動態 SNAT
                * SNAT  是靜態的，必須在 rule 手動設定外網 IP
                * 如果網卡的外網 IP 變動，SNAT 就需要手動去修改(很麻煩)
                * MASQUERADE 會自己去找對應網卡的 IP 位址，它的外網 IP 是多少來當作 SNAT 的來源 IP 
                - 缺點是因每次傳送封包都需去找網卡對應的 IP，故速度較慢
            - DNAT
                > Destination NAT
                > 在路由前（PREROUTING）將來自外網訪問的目的 IP 位址從外網 IP 位址修改為內網主機的IP位址，就能讓外網連線到內網的主機
                ##### 情境 : 外網主機(61.xx.xx.xx)發送請求給 NAT 主機的80 port (對應到內網主機(192.168.1.210) 的 80 port 上的 WWW 服務)
                ![](https://i.imgur.com/Yfu3Dja.png)
                1. 外部主機要連到WWW服務，需要先連到NAT主機上
                2. NAT 主機已經有設定要分析 80 port 的封包，所以當它接收到封包後，會用 PREROUTING 將目的 IP 從外網 IP 改成內網 IP，也就變成連線到 192.168.1.210 的 80 port，同時紀錄封包資訊
                3. 封包會傳送到 192.168.1.2 這個內網網卡，然後再傳送到目的地192.168.1.210 的 80 port (連線到 WWW 服務！)
                4. 之後在回傳封包給外網主機時，會比對前面儲存的封包資訊，把來源 IP 從內網 IP 換成外網 IP，就可以傳送回去了
- 封包在抵達本機後經過的流程
    - ![image](https://hackmd.io/_uploads/Bkmgv5ap6.png)
- rule
    * 若符合該 rule 就會執行相應的行為，有順序性
    ![](https://i.imgur.com/GpE5clw.png =300x)
        > 若符合排在前面的 rule ，就會去執行相應的 action ，通常不會再往下去執行(類似 if , else if)
    - 查看 rule
        ```
        sudo ipatables [-t table] -L [-nv --line-numbers]
        ```
        * `-t` : 選擇 table，預設是 filter
        * `-L` : 列出 rule
        * `-n` : 不把 IP 位址解析成域名，所以速度較快
        * `-v` : 列出更多資訊
        * `--line-numbers` : 顯示編號
        ![](https://i.imgur.com/IUq1qWD.png)
            * target : 進行的動作
            * prot : 針對的封包使用的協定
            * opt : 額外選項說明
            * source : 針對的來源 IP
            * destination : 針對的目的 IP
    - 新增 rule
        ```
        sudo iptables [-t table] [-A or -I] <INPUT, OUTPUT,FORWARD...>\
        -j <ACCEPT, DROP, REJECT> [-i -o -p -s -d...]
        ```
        * `-t` : 選擇 table，後面接 table 名稱
        * 新增
            * `-A` : append，規則加在最後面，後面接 chain 名稱
            * `-I` : insert，規則加在最前面，後面接 chain 名稱
        * target
            * `-j` : jump target，後面接 target
                - target
                    *  ACCEPT : 允許
                    *  REJECT : 拒絕，會告知發送者封包被拒絕
                    *  DROP : 丟掉，發送者不會知道
                    *  SNAT : 修改封包來源 IP
                    *  DNAT : 修改封包目的 IP
                    *  MASQUERADE : 動態 SNAT
                    *  LOG : 紀錄連線到 log
        * 網卡
            * `-i` : in interface，封包從哪個網卡進來
            * `-o` : out interface，封包從哪個網卡出去
        * IP位址
            * `-s` : source address，封包來源IP位址
            * `-d` : destination address，封包目的IP位址
            * `!` : 可用在 -s 和 -d 之後，表示非該 IP
        * 協定
            * `-p` : protocol，當封包使用什麼協定(tcp、udp、ICMP...)
        * port：當 `-p` 要指定 tcp 或 udp 時才可以使用
            * `--sport` : source port，封包來源 port
            * `--dport` : destination port，封包目標 port
        * 模組
            * `-m` : 呼叫系統模組提供其他功能
                - ex: conntrack 模組
                    * 此模組會記錄連線資訊，所以我們可以依此針對不同種類的連線狀態設定不同規則
                        * NEW : 新建立的連線
                        * ESTABLISHED : 已建立的連線(雙向都得到回應)
                        * RELATED : 新的連線，但與已建立的連線相關
                            - ex. ftp 21 port 先建立連線，20 port 傳送資料
                        * INVALID : 無法辨認或惡意的連線
                        * UNTRACKED : 在 raw 表已被關閉追蹤
        - policy
            * 封包預設處理方式，如果 chain 都沒有符合的 rule 就會執行 policy 的 rule
            - 更改 policy
                ```
                sudo iptables [-t table] -P <INPUT, OUTPUT, FORWARD...> <ACCEPT, DROP, ...>
                ```
            * `-t` : 選擇 table
            * `-P` : policy ， 後面接 [chain] [target]
            * 把 filter table 的 INPUT policy 更改為 DROP
            ![](https://i.imgur.com/wHxwio8.png)
            ![](https://i.imgur.com/Xk1Lsak.png)
        * 範例 1：
            ![](https://i.imgur.com/wi1hXY0.png =300x)
            * iptables 在 http server 主機上，對外網卡是 eth1
            * 讓 Good user 可以連線到 http server 
            ```
            sudo iptables -A INPUT -i eth1 -s 192.168.0.101 -j ACCEPT
            ```
            * 讓 Bad user 無法連線到 http server
            ```
            sudo iptables -A INPUT -i eth1 -s 192.168.0.102 -j DROP
            ```
        - 範例 2：
            自己的 Server 一直幫特定網段（163.22.17.0, netmask = 255.255.255.0）的 Server 挖礦，所以想要先丟棄到該網段的封包
            `sudo iptables -I OUTPUT -d 163.22.17.0/24 -j DROP`
        - 範例 3：
            將連線到 NAT 主機 80 port 的封包的目的地，改成內網主機中 Web Server 的 8080 port
            `sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to {Web Server IP}:8080`
    - 刪除 rule
        * `-D` : Delete，刪除 chain 裡對應編號的 rule
        ```
        sudo iptables [-t table] -D <INPUT,OUTPUT,FORWAED...> <rule 編號>
        ```
        * `-F` : Flush，清除 chain 裡全部的 rule
        ```
        sudo iptables [-t table] -F <INPUT,OUTPUT,FORWARD...>
        ```

- 儲存 iptables 設定
    * iptables 的設定關機就會消失，不會自動保存和載入
    * 把設定 save 到檔案裡再 restore 回去
        * `iptables-save` 可以輸出 iptables 目前的設定
        * `iptables-save > iptables.conf` 把輸出的結果寫入 iptables.conf
        * `iptables-restore < iptables.conf` 把  iptables.conf 的內容載入到 iptables

- DMZ
    > Demilitarized Zone (非軍事區)
    >將內網中要開放的伺服器與沒有要開放的主機分隔開來
    >讓外網有限制地存取內網資源
    >當 DMZ 被攻擊時，不開放的內網主機是安全的

    ![image](https://hackmd.io/_uploads/BJlSJo6Tp.png)

    * 要讓內外網都可以存取服務的主機放在 DMZ，而不對外開放的主機放在 LAN
    * 外網、內網可以直接連線到 DMZ，但 DMZ 不能直接連線內網
    * 所以當 DMZ 被攻擊時，因為 DMZ 不能直接連線到 LAN ，所以 LAN 還會是安全的
    
    - 練習：firewall 主機的 iptables 設定
        共有 firewall、DMZ、LAN 的三台主機
        - 外網進來的封包
            * 可以連 DMZ
                * 將外網連到 Firewall 80 port 的封包，轉送到 Web Server 80 port
                    ```=1
                    sudo iptables -t nat -A PREROUTING \
                    -i {外網網卡} -p tcp --dport 80 \
                    -j DNAT --to {Web Server IP}:80
                    ```
                * 同意該封包轉送
                    ```=1
                    sudo iptables -A FORWARD \
                    -i {外網網卡} -d {Web Server IP} \
                    -p tcp --dport 80 -j ACCEPT
                    ```
            * 不能連 LAN
                * 後面統一設定
        - DMZ 發出的封包
            * 可以連外網
                ```=1
                sudo iptables -I FORWARD -i {DMZ 網卡} -o {外網網卡} -j ACCEPT
                sudo iptables -t nat -I POSTROUTING -o {外網網卡} -j MASQUERADE
                ```
            * 不能連 LAN
                * 後面統一設定
        - LAN 發出的封包
            * 可以連外網
                ```bash=1
                sudo iptables -I FORWARD -i {LAN 網卡} -o {外網網卡} -j ACCEPT
                # 出去的封包做 MASQUERADE 在前面已經設過，所以這裡就不用再設定
                ```
            * 可以連 DMZ
                * 不限制只能連到 80 port，也允許 ssh 進去等其他功能
                ```=1
                sudo iptables -I FORWARD -i {LAN 網卡} -o {DMZ 網卡} -j ACCEPT
                ```
        - 其他
            * 允許轉送已建立或相關的連線
                ```bash=1
                sudo iptables -I FORWARD \
                -m conntrack --ctstate "ESTABLISHED,RELATED" \
                -j ACCEPT
                ```
            * 拒絕其他進來 Firewall 主機的連線 
                ```=1
                sudo iptables -A INPUT -j DROP
                ```
            * 拒絕轉送其他連線
                * 要用 `-A` 加在最後面，不然所有轉送的封包都會被 DROP 掉
                ```=1
                sudo iptables -A FORWARD -j DROP
                ```
- ref
    - https://hackmd.io/@ncnu-opensource/book/https%3A%2F%2Fhackmd.io%2FGEFEQU2GQTq36U5Bs6xVfw#iptables
                            
#### ufw
- 介紹
    - Uncomplicated Firewall (簡化版 iptables)
    - 相比 iptables 在操作上更直覺、簡單，因 ufw 會再幫我們設定 iptables 的規則
- 安裝
    - `sudo apt install ufw`
    * 查看狀態 : `sudo ufw status`
    * 詳細狀態 : `sudo ufw status verbose`
    * 啟用 ufw : `sudo ufw enable`
    * 關閉 ufw : `sudo ufw disable`
    * 重設 ufw : `sudo ufw reset`
- 查看規則
    * 顯示目前規則&顯示規則編號（有順序性） : `sudo ufw status numbered`
- 刪除規則
    * 刪除第 3 條規則 : `sudo ufw delete 3`
- 預設規則
    * 預設允許 : `sudo ufw default allow`
    * 預設拒絕 : `sudo ufw default deny`
- 新增規則
    * 允許 ssh port : `sudo ufw allow ssh`
    * 拒絕 22 port : `sudo ufw deny 22`
    * 允許 TCP 6000~6007 port : `sudo ufw allow 6000:6007/tcp`
    * 允許 192.168.11.10 的所有連線 : `sudo ufw allow from 192.168.11.10`
    * 拒絕 192.168.11.1 ~ 192.168.11.255 的所有連線 : `sudo ufw deny from 192.168.11.0/24`
    * 拒絕某 IP 連到某 port : `sudo ufw deny from 192.168.11.7 to any port 22`

- reference
    * https://noob.tw/ufw/
    * https://zh.wikipedia.org/zh-tw/Uncomplicated_Firewall