ASP.NET 虛擬主機環境下,System.IO 命名空間提供強大的檔案系統存取能力,若未妥善隔離,惡意使用者可上傳 WebShell 讀寫任意目錄(甚至 C 槽系統目錄),造成嚴重安全風險。本文基於 Windows Server 2003 + IIS 6.0 + SQL Server 2000 環境,提出以「應用程式集區身分隔離 + NTFS 精細權限 + 系統目錄鎖定」為核心的纵深防禦方案。
FileSystemObject (scrrun.dll) 可透過刪除/改名 DLL 阻擋。System.IO 為 managed code,無需註冊,僅需將組件放入 bin 目錄即可使用,傳統阻擋失效。w3wp.exe 以 Network Service 內建帳號運行,該帳號屬於 IIS_WPG 群組,預設擁有廣泛讀取權限(如 C:\Windows、C:\Program Files),導致跨站目錄遍歷。IIS 6.0 採用「工作進程隔離模式」,每個應用程式集區對應一組 w3wp.exe 進程。將每個網站指派給獨立集區,並為集區指定專屬的低權限帳號,配合 NTFS ACL 鎖定目錄存取,實現網站間的硬性隔離。
| 帳號用途 | 帳號名稱 | 密碼 | 加入群組 | 移出群組 |
|---|---|---|---|---|
| 應用程式集區身分 | app_test_user | appuser | IIS_WPG | Users, Guests 等 |
| 匿名存取身分 (IUSR) | iis_test_user | iisuser | Guests | Users, IIS_WPG 等 |
帳號屬性:勾選「使用者無法變更密碼」、「密碼永不過期」。


test_pool。app_test_user → 輸入密碼。

test_site,實體路徑 D:\test。test_pool。iis_test_user → 輸入密碼。
| 目錄 | 權限設定原則 | 備註 |
|---|---|---|
| C:\ | 僅 Administrators、SYSTEM 擁有「完全控制」,移除所有其他群組/帳號,不替換子物件。 | 防止任意讀取系統根目錄 |
| C:\Documents and Settings | 繼承父權限,替換子物件。 | |
| C:\Program Files | 繼承父權限,替換子物件。 額外: C:\Program Files\Common Files\Microsoft Shared 移除繼承→複製現有權限→增加 Users「讀取」並替換子物件。 | 支援 ASP/ASP.NET 使用 Access/MDAC 等共用元件 |
| C:\Windows | 移除繼承→複製現有權限→僅保留 Administrators、SYSTEM「完全控制」+ Users「讀取」,替換子物件。 | 系統服務需 Users 讀取;Network Service 屬 Users 成員故間接獲得讀取 |
| 其他資料磁碟 (D:, E:...) | 僅 Administrators、SYSTEM 完全控制,移除其餘,替換子物件。 | |
| 網站目錄 (D:\test) | 繼承現有權限 → 增加 app_test_user、iis_test_user「完全控制」並替換子物件。 | 確保網站讀寫僅限自身目錄 |


因 Network Service 屬 Users 群組,而系統服務需 Users 讀取 C:\Windows,難以完全移除。兩大補強方案:
C:\Windows 改為 C:\WIN2003SRV (≤8 字元,符合 DOS 命名),大幅增加攻擊者猜測路徑難度。IIS_WPG 必須的特定路徑權限:%windir%\help\iishelp\common (讀取)%windir%\IIS Temporary Compressed Files (列出/讀取/寫入)%windir%\system32\inetsrv\ASP Compiled Template (讀取)Inetpub\wwwroot (讀取/執行)建議雙重佈防:方案一為必做,方案二視應用相容性微調。
適用於大量虛擬主機批量建立集區、虛擬目錄、綁定集區:
using System;
using System.DirectoryServices;
namespace IISAdmin {
public class PoolManager {
public static void CreatePool(string name) {
var pools = new DirectoryEntry("IIS://localhost/W3SVC/AppPools");
var pool = pools.Children.Add(name, "IIsApplicationPool");
pool.CommitChanges();
}
public static void SetPoolIdentity(string poolName, string user, string pwd) {
var pool = new DirectoryEntry($"IIS://localhost/W3SVC/AppPools/{poolName}");
pool.Properties["WAMUserName"].Value = user;
pool.Properties["WAMUserPass"].Value = pwd;
pool.CommitChanges();
}
public static void AssignPoolToVdir(string vdirPath, string poolName) {
var vdir = new DirectoryEntry($"IIS://localhost/{vdirPath}");
vdir.Invoke("AppCreate3", new object[] { 0, poolName, true });
}
}
}
第二組範例展示完整網站建立、啟停、查詢邏輯,可整合至主控面板系統。
本方案透過「集區身分隔離 + NTFS 精細 ACL + 系統目錄最小權限」三層防線,從根本阻斷 System.IO 跨站存取。雖實施較繁瑣,但為虛擬主機商必備的安全基線。期待 .NET 2.0+ 版本能在框架層面提供更完善的沙箱機制。