คำตอบสั้น ๆ: เมื่อสิทธิ์แบบ owner-group-other ไม่พอ ใช้ ACL กำหนดสิทธิ์รายผู้ใช้และรายกลุ่มบนไฟล์เดียวกัน พร้อมสิทธิ์ที่สืบทอดให้ไฟล์ใหม่
คู่มือนี้อธิบาย setfacl ทีละขั้นตอน พร้อมคำสั่งที่ใช้ได้จริงและปัญหาที่พบบ่อย
สิทธิ์ไฟล์แบบดั้งเดิมบน Linux มีเพียงสามกลุ่มคือเจ้าของ กลุ่ม และคนอื่น ซึ่งพอสำหรับงานทั่วไป แต่ไม่พอเมื่อต้องการให้ "ผู้ใช้ A เขียนได้ ผู้ใช้ B อ่านได้อย่างเดียว และเว็บเซิร์ฟเวอร์อ่านได้" บนโฟลเดอร์เดียวกัน
ทางแก้ที่หลายคนใช้คือ chmod 777 ซึ่งเปิดให้ทุกคนในเครื่องเขียนได้และเป็นช่องโหว่ที่ถูกใช้โจมตีบ่อย ACL คือทางแก้ที่ถูกต้อง คู่มือนี้ใช้กรณีจริงของเว็บเซิร์ฟเวอร์เป็นตัวอย่าง
สิ่งที่ต้องเตรียม
- Linux Server และสิทธิ์
sudo - ระบบไฟล์ที่รองรับ ACL ซึ่ง ext4 และ xfs รองรับอยู่แล้วโดยค่าเริ่มต้น
# Ubuntu / Debian
sudo apt install -y acl
# AlmaLinux / Rocky Linux
sudo dnf install -y acl
ตรวจว่าระบบไฟล์เปิด ACL อยู่
mount | grep ' / '
sudo tune2fs -l /dev/sda1 | grep 'Default mount options'
ถ้าเห็นคำว่า acl แปลว่าใช้ได้เลย เกือบทุกดิสทริบิวชันสมัยใหม่เปิดไว้ให้แล้ว
ขั้นตอนที่ 1: ดูสิทธิ์ที่มีอยู่
ls -l /var/www/example.com
getfacl /var/www/example.com
ผลของ getfacl จะแสดงบรรทัด user::, group:: และ other:: ซึ่งตรงกับสิทธิ์แบบเดิม หากมี ACL เพิ่มเติมจะเห็นบรรทัดที่ระบุชื่อผู้ใช้ เช่น user:deploy:rwx
สังเกตจาก ls -l ได้เช่นกัน ถ้ามีเครื่องหมาย + ต่อท้ายสิทธิ์ แปลว่าไฟล์นั้นมี ACL อยู่
ขั้นตอนที่ 2: กรณีใช้งานจริง — เว็บเซิร์ฟเวอร์กับผู้ใช้ Deploy
สถานการณ์ที่พบบ่อยที่สุด ไฟล์เว็บอยู่ที่ /var/www/example.com โดยมีเงื่อนไข
- ผู้ใช้
deployต้องอัปโหลดและแก้ไฟล์ได้ - ผู้ใช้
www-data(Nginx/PHP-FPM) ต้องอ่านได้ และเขียนได้เฉพาะโฟลเดอร์อัปโหลด - ผู้ใช้อื่นในเครื่องไม่ควรเห็นอะไรเลย
เริ่มจากตั้งสิทธิ์พื้นฐานให้แน่นก่อน
sudo chown -R deploy:deploy /var/www/example.com
sudo chmod -R 750 /var/www/example.com
sudo find /var/www/example.com -type f -exec chmod 640 {} \;
ตอนนี้ www-data ยังเข้าไม่ได้ ให้สิทธิ์อ่านด้วย ACL
sudo setfacl -R -m u:www-data:rX /var/www/example.com
ตัว X ตัวใหญ่สำคัญมาก มันให้สิทธิ์เข้าโฟลเดอร์ (execute) เฉพาะกับไดเรกทอรีและไฟล์ที่มีสิทธิ์ execute อยู่แล้ว ต่างจาก x ตัวเล็กที่จะทำให้ไฟล์ทุกไฟล์กลายเป็นไฟล์รันได้ ซึ่งไม่ควรเกิดกับไฟล์เว็บ
ขั้นตอนที่ 3: ให้สิทธิ์เขียนเฉพาะโฟลเดอร์ที่จำเป็น
sudo setfacl -R -m u:www-data:rwX /var/www/example.com/storage
sudo setfacl -R -m u:www-data:rwX /var/www/example.com/public/uploads
หลักการคือให้สิทธิ์เขียนแคบที่สุดเท่าที่แอปต้องการ เว็บที่ถูกแฮกส่วนใหญ่เริ่มจากการที่โฟลเดอร์อัปโหลดเขียนได้และรันสคริปต์ได้พร้อมกัน
ขั้นตอนที่ 4: ตั้ง Default ACL ให้ไฟล์ใหม่สืบทอดสิทธิ์
นี่คือจุดที่ ACL มีค่าที่สุด ไฟล์ที่สร้างใหม่ในอนาคตจะได้สิทธิ์ตามที่กำหนดไว้โดยอัตโนมัติ ไม่ต้องมาไล่ตั้งใหม่ทุกครั้งที่ Deploy
sudo setfacl -R -d -m u:www-data:rX /var/www/example.com
sudo setfacl -R -d -m u:deploy:rwX /var/www/example.com
sudo setfacl -R -d -m u:www-data:rwX /var/www/example.com/storage
ตัวเลือก -d คือ default ซึ่งมีผลกับไดเรกทอรีเท่านั้นและใช้กับไฟล์ที่สร้างขึ้นใหม่ภายในเท่านั้น ไฟล์ที่มีอยู่แล้วไม่เปลี่ยน จึงต้องสั่งทั้งสองแบบคู่กันเสมอ
ตรวจผล
getfacl /var/www/example.com
บรรทัดที่ขึ้นต้นด้วย default: คือสิทธิ์ที่จะสืบทอด ทดสอบด้วยการสร้างไฟล์ใหม่
sudo -u deploy touch /var/www/example.com/test.txt
getfacl /var/www/example.com/test.txt
sudo rm /var/www/example.com/test.txt