返回文章列表

網站管理指令碼安全實踐

本文探討網站管理中常用的 Shell 指令碼,包含檢查外部連結、管理 Apache 密碼和使用 SFTP 同步檔案,並深入剖析程式碼邏輯、安全考量以及實務應用。從檢查連結的 checkexternal 指令碼開始,逐步解析其運作原理,接著介紹 Apache 密碼管理指令碼

網站管理 資安

網站可靠性與安全性息息相關,仰賴穩固的管理機制。本文介紹三種 Shell 指令碼,分別用於檢查外部連結、Apache 密碼管理和 SFTP 檔案同步,強化網站的日常維運。首先,checkexternal 指令碼能有效檢測外部連結的可用性,從 checklinks 指令碼產生的 rejects 檔案中讀取 URL 列表,並利用 curl 命令驗證每個連結的狀態,及時發現失效連結。接著,apm 指令碼提供網頁介面,簡化 Apache .htpasswd 檔案的管理,讓管理員能輕鬆新增、更新和刪除使用者帳戶,提升管理效率。最後,sftpsync 指令碼則專注於檔案同步,利用時間戳記檔案追蹤本地與遠端伺服器之間的檔案差異,僅上傳新檔案或修改過的檔案,並透過 SFTP 確保檔案傳輸的安全性。

網站與網際網路管理:檢查外部連結的指令碼

在前一篇文章中,我們討論了一個用於檢查網站內部連結的指令碼(checklinks)。現在,我們將進一步探討如何檢查外部連結,以確保它們的有效性。

檢查外部連結的指令碼(checkexternal)

這個指令碼(checkexternal)旨在檢查一個網站或其子目錄中的所有外部連結,以找出可能失效或損壞的連結。為了簡化流程,它假設前一個指令碼(checklinks)已經執行過,因此可以直接使用其產生的 *.rejects 檔案中的URL列表。

指令碼的工作原理

checkexternal 指令碼透過以下步驟來檢查外部連結:

  1. 讀取外部連結列表:從 *.rejects 檔案中讀取外部連結的列表。
  2. 檢查每個連結的有效性:使用 curl 命令測試每個外部連結的有效性。
  3. 報告結果:根據測試結果,報告每個連結的狀態(成功或失敗)。

程式碼解析

#!/bin/bash
# checkexternal--測試一個網站上的所有URL,以建立外部參考列表,
# 然後檢查每個參考,以確定哪些可能已經失效或損壞。
listall=0; errors=0; checked=0
if [ "$1" = "-a" ] ; then
  listall=1; shift
fi
if [ -z "$1" ] ; then
  echo "用法:$(basename $0) [-a] URL" >&2
  exit 1
fi

trap "$(which rm) -f traverse*.errors reject*.dat traverse*.dat" 0
outfile="$(echo "$1" | cut -d/ -f3).errors.ext"
URLlist="$(echo $1 | cut -d/ -f3 | sed 's/www\.//').rejects"
rm -f $outfile # 為新的輸出做好準備
if [ ! -e "$URLlist" ] ; then
  echo "找不到檔案 $URLlist。請先執行 checklinks。" >&2
  exit 1
fi
if [ ! -s "$URLlist" ] ; then
  echo "似乎沒有外部連結($URLlist 為空)。" >&2
  exit 1
fi

#### 現在,終於可以開始了...
for URL in $(cat $URLlist | sort | uniq)
do
  curl -s "$URL" > /dev/null 2>&1; return=$?
  if [ $return -eq 0 ] ; then
    if [ $listall -eq 1 ] ; then
      echo "$URL 是正常的。"
    fi
  else
    echo "$URL 失敗,錯誤程式碼為 $return"
    errors=$(( $errors + 1 ))
  fi
  checked=$(( $checked + 1 ))
done
echo ""
echo "完成。已檢查 $checked 個URL,發現 $errors 個錯誤。"
exit 0

內容解密:

  1. listallerrorschecked 變數:用於控制指令碼的行為和跟蹤錯誤數量及已檢查的URL數量。
  2. curl 命令的使用-s 選項使 curl 以靜默模式執行,> /dev/null 2>&1 將輸出重定向到 /dev/null,丟棄所有輸出,而 $? 取得 curl 命令的傳回碼,用於判斷URL是否有效。
  3. trap 命令:在指令碼離開時自動刪除臨時檔案。
  4. for 迴圈:遍歷外部連結列表,對每個URL進行檢查。

管理 Apache 密碼的安全實踐

Apache 網頁伺服器提供內建的密碼保護目錄功能,即使在共用公用伺服器上也能實作私密、安全的有限存取資訊。不論是經營付費訂閱服務,還是希望確保家庭照片僅供家人檢視,此功能都非常實用。

設定 .htaccess 檔案

標準設定要求在受密碼保護的目錄中管理名為 .htaccess 的檔案。此檔案指定安全區網域名稱,更重要的是,它指向另一個包含帳戶名稱和密碼配對的資料檔案,用於驗證目錄存取許可權。

$ cat .htaccess
AuthUserFile /usr/lib/cgi-bin/.htpasswd
AuthGroupFile /dev/null
AuthName "Members Only Data Area."
AuthType Basic
<Limit GET>
require valid-user
</Limit>

建立 .htpasswd 檔案

另一個名為 .htpasswd 的檔案儲存所有帳戶和密碼配對。如果此檔案尚未存在,需要建立它。執行 touch .htpasswd 並確保 Apache 使用者 ID(可能是 nobody)可寫入該檔案。

Apache 密碼管理指令碼(apm)

為簡化 .htpasswd 檔案的管理,apm 指令碼提供了一個在瀏覽器中以 CGI 指令碼形式執行的密碼管理工具,方便新增帳戶、修改現有帳戶密碼或刪除帳戶。

apm 程式碼解析

#!/bin/bash
# apm--Apache Password Manager allows the administrator to easily
# add, update, or delete accounts and passwords for a subdirectory
# of a typical Apache configuration (where the config file is called
# .htaccess).

echo "Content-type: text/html"
echo ""
echo "<html><title>Apache Password Manager Utility</title><body>"
basedir=$(pwd)
myname="$(basename $0)"
footer="$basedir/apm-footer.html"
htaccess="$basedir/.htaccess"
htpasswd="$(which htpasswd) -b"

內容解密:

  1. 設定 HTTP 標頭:首先輸出 Content-type: text/html 以指示輸出為 HTML 檔案。
  2. 初始化變數:定義指令碼工作目錄、指令碼名稱、頁尾檔案路徑、.htaccess 路徑以及 htpasswd 命令的路徑。
if [ ! -r "$htaccess" ] ; then
echo "Error: cannot read $htaccess file."
exit 1
fi
passwdfile="$(grep "AuthUserFile" $htaccess | cut -d\ -f2)"

內容解密:

  1. 檢查 .htaccess 可讀性:如果無法讀取 .htaccess,輸出錯誤訊息並離開。
  2. 擷取密碼檔案路徑:從 .htaccess 中擷取 AuthUserFile 的值,即密碼檔案路徑。
action="$(echo $QUERY_STRING | cut -c3)"
user="$(echo $QUERY_STRING|cut -d\& -f2|cut -d= -f2|tr '[:upper:]' '[:lower:]')"
case "$action" in
A ) echo "<h3>Adding New User <u>$user</u></h3>"
if [ ! -z "$(grep -E "^${user}:" $passwdfile)" ] ; then
echo "Error: user <b>$user</b> already appears in the file."
else
pass="$(echo $QUERY_STRING|cut -d\& -f3|cut -d= -f2)"
if [ ! -z "$(echo $pass|tr -d '[[:upper:][:lower:][:digit:]]')" ]; then
echo "Error: passwords can only contain a-z A-Z 0-9 ($pass)"

內容解密:

  1. 解析查詢字串:根據查詢字串判斷操作型別(新增、更新或刪除)及使用者名稱。
  2. 新增使用者邏輯:檢查使用者是否已存在,若不存在則繼續檢查密碼是否符合規範(僅包含字母和數字)。
  3. 錯誤處理:若使用者已存在或密碼不符合規範,輸出對應的錯誤訊息。

安全性和易用性考量

  • 安全性:透過限制只有特定使用者(如 admin)才能存取 apm,可以提高安全性。
  • 易用性:提供根據網頁的介面,讓管理員能夠輕鬆新增、修改或刪除帳戶,提升了管理的便捷性。

Apache 密碼管理指令碼解析與實作

指令碼功能概述

此指令碼主要用於透過網頁介面管理 Apache 的 .htpasswd 檔案,實作新增、更新和刪除使用者的功能。指令碼透過 CGI(Common Gateway Interface)與網頁伺服器互動,接收使用者請求並執行相應的操作。

指令碼結構與流程

1. 前置處理

在主邏輯執行前,指令碼會:

  • .htaccess 檔案中提取 htpasswd 檔案的路徑。
  • 檢查指令碼是否具有寫入 .htpasswd 檔案的許可權。
  • 處理可能的錯誤情況,如檔案不可寫或 htpasswd 命令不可用。

2. 主邏輯:case 陳述式

指令碼的核心是一個 case 陳述式,根據從 QUERY_STRING 中提取的操作碼(AUD)執行相應的操作:

  • A(新增使用者):檢查使用者名稱和密碼的有效性,若無誤則使用 htpasswd 命令新增使用者。
  • U(更新使用者密碼):檢查使用者是否存在、密碼是否有效,若無誤則更新使用者密碼。
  • D(刪除使用者):檢查使用者是否存在,若使用者不是 admin 則刪除該使用者。
case "$action" in
A ) # 新增使用者邏輯
    ;;
U ) # 更新使用者密碼邏輯
    ;;
D ) # 刪除使用者邏輯
    ;;
esac

3. 列出當前使用者

無論執行何種操作,指令碼都會在操作完成後列出 .htpasswd 檔案中的所有使用者,並提供刪除連結。

while read acct pw ; do
    echo "<tr><th>$acct</th><td align=center><a href=\"$myname?a=D&u=$acct\">[delete]</a></td></tr>"
done < $passwdfile

4. 輸出 HTML 表尾與操作表單

指令碼會讀取 apm-footer.html 檔案,並替換其中的 --myname----options-- 分別為當前指令碼名稱和使用者列表選項,最後輸出完整的 HTML。

程式碼重點解析

QUERY_STRING 處理

指令碼從 QUERY_STRING 環境變數中提取操作碼、使用者名稱和密碼。

action=$(echo $QUERY_STRING | cut -d\& -f1 | cut -d= -f2)
user=$(echo $QUERY_STRING | cut -d\& -f2 | cut -d= -f2)
pass=$(echo $QUERY_STRING | cut -d\& -f3 | cut -d= -f2)

htpasswd 命令呼叫

使用 htpasswd 命令對密碼進行加密並更新 .htpasswd 檔案。

$htpasswd $passwdfile "$user" "$pass"

實作注意事項

  1. 安全性:確保 .htpasswd 檔案存放在安全的位置,避免直接被網頁伺服器存取。
  2. 許可權控制:指令碼需要適當的執行許可權,以確保能夠讀寫 .htpasswd 檔案。
  3. 錯誤處理:完善的錯誤處理機制對於提升使用者經驗和系統穩定性至關重要。

使用 SFTP 同步檔案:sftpsync 指令碼詳解

在現代網路環境中,檔案傳輸協定(FTP)由於其安全性問題逐漸被更安全的協定如 rsync 和 ssh(安全殼層)所取代。SFTP(SSH 檔案傳輸協定)作為 ssh 的一部分,提供了加密的檔案傳輸功能。本篇文章將介紹如何使用 sftpsync 指令碼透過 SFTP 同步本地與遠端伺服器之間的檔案。

sftpsync 指令碼功能

sftpsync 是一個 Bash 指令碼,用於將本地目錄中的新檔案或已修改檔案上傳至遠端 SFTP 伺服器。該指令碼使用一個名為 .timestamp 的時間戳記檔案來追蹤最後一次同步的時間,從而決定哪些檔案需要被上傳。

程式碼解析

#!/bin/bash
# sftpsync--Given a target directory on an sftp server, makes sure that
# all new or modified files are uploaded to the remote system. Uses
# a timestamp file ingeniously called .timestamp to keep track.

timestamp=".timestamp"
tempfile="/tmp/sftpsync.$$"
count=0
trap "$(which rm) -f $tempfile" 0 1 15 # Zap tempfile on exit

if [ $# -eq 0 ] ; then
  echo "Usage: $0 user@host { remotedir }" >&2
  exit 1
fi

user="$(echo $1 | cut -d@ -f1)"
server="$(echo $1 | cut -d@ -f2)"

if [ $# -gt 1 ] ; then
  echo "cd $2" >> $tempfile
fi

if [ ! -f $timestamp ] ; then
  # If no timestamp file, upload all files.
  for filename in *
  do
    if [ -f "$filename" ] ; then
      echo "put -P \"$filename\"" >> $tempfile
      count=$(( $count + 1 ))
    fi
  done
else
  for filename in $(find . -newer $timestamp -type f -print)
  do
    echo "put -P \"$filename\"" >> $tempfile
    count=$(( $count + 1 ))
  done
fi

if [ $count -eq 0 ] ; then
  echo "$0: No files require uploading to $server" >&2
  exit 1
fi

echo "quit" >> $tempfile

echo "Synchronizing: Found $count files in local folder to upload."

if ! sftp -b $tempfile "$user@$server" ; then
  echo "Done. All files synchronized up with $server"
  touch $timestamp
fi

exit 0

內容解密:

  1. 初始化變數和暫存檔案:指令碼首先設定了時間戳記檔案 .timestamp 和一個用於儲存 SFTP 命令的暫存檔案。trap 命令確保在指令碼離開時刪除暫存檔案。

  2. 引數檢查:指令碼檢查是否提供了足夠的引數(使用者名稱@主機名和可選的遠端目錄)。如果沒有提供足夠的引數,則顯示用法並離開。

  3. 解析使用者名稱和伺服器位址:從第一個引數中提取使用者名稱和伺服器位址。

  4. 建立 SFTP 命令

    • 如果提供了第二個引數(遠端目錄),則在暫存檔案中新增 cd 命令以切換到該目錄。
    • 如果不存在時間戳記檔案,則上傳所有本地檔案;否則,只上傳比時間戳記檔案新的檔案。
    • put 命令(帶有 -P 選項以保留檔案許可權和時間戳記)新增至暫存檔案中,以上傳選定的檔案。
  5. 執行 SFTP:使用 -b 選項將暫存檔案中的命令餵給 sftp 命令。如果 SFTP 操作成功,則更新時間戳記檔案。

  6. 錯誤處理和輸出:指令碼根據需要輸出同步結果,並在沒有檔案需要上傳時離開。

如何使用 sftpsync

  1. 移動到本地源目錄:確保你位於想要同步的本地目錄中。

  2. 執行 sftpsync:執行 sftpsync 指令碼,並提供你的使用者名稱、伺服器名稱和遠端目錄作為引數。例如:

    sftpsync [email protected] /wicked/scripts
    
  3. 驗證結果:指令碼將顯示正在上傳的檔案,並在完成後報告同步結果。

使用 SFTP 同步檔案的安全考量

在使用 sftpsync 指令碼或任何其他根據 SFTP 的解決方案時,安全性是一個非常重要的考量因素。以下是一些需要特別注意的安全事項:

私鑰與密碼的安全管理

  1. 使用 SSH 金鑰認證:相較於使用密碼,使用 SSH 金鑰進行認證更為安全。確保你的私鑰得到妥善保護,不要將其與他人共用或存放在不安全的地方。

  2. 密碼的安全性:如果你仍然選擇使用密碼,請確保密碼足夠複雜並定期更換。

SFTP 伺服器的組態

  1. 限制 SFTP 使用者的許可權:確保 SFTP 使用者僅擁有必要的許可權,避免過度授權。例如,可以透過 chroot jail 將使用者限制在其主目錄中,防止他們存取系統上的其他檔案。

  2. 更新和修補 SSH/SFTP 軟體:保持你的 SSH/SFTP 軟體(例如 OpenSSH)為最新版本,以確保已修補已知的安全漏洞。

日誌記錄和監控

  1. 啟用日誌記錄:確保你的 SFTP 伺服器組態了適當的日誌記錄級別,以便能夠監控和分析任何可疑活動。

  2. 定期檢查日誌:定期檢查 SFTP 日誌,以及相關的系統日誌,以便及時發現並回應任何潛在的安全威脅。

網路安全

  1. 防火牆組態:使用防火牆限制對 SFTP 伺服器的存取,只允許信任的 IP 位址或網路連線到 SFTP 服務。

  2. 使用 VPN:對於需要從不安全網路連線的情況,考慮透過 VPN 連線來增加額外的一層保護。