บทความก่อนหน้า The Rubyist's Guide To Environment Variables แสดงว่าระบบ environment variables ทำงานยังไง และ debunk myths แต่ reader ชี้ให้เห็นว่าเราพูดน้อยเกินไปเรื่อง security
ตอนนี้ใช้ env vars เก็บ secret API keys และข้อมูลสำคัญมาก เข้าใจ security implications สำคัญ มาดู:
Worst Case Scenario
โจรกลางเข้าถึง server เป็น root หรือ user ที่ own web apps ในกรณีนี้ environment variables ถูก compromise พร้อมกับทุกอย่างที่ไม่ได้ encrypted แรง
แก้คือกันคนไม่ให้ได้ root access servers :)
The Trojan Horse
คนแปลกหน้าในซอยข้างท่าเรือให้ imagemagick พิเศษ ว่าจะเร็วกว่า stock 2 เท่า
...คุณทำตามปกติ ติดตั้ง production ปัญหาคือมันออกแบบมาเพื่อขโมย environment variables
รัน "malicious" mogrify command จาก Ruby ด้วย back-ticks syntax Mogrify ขโมย env variables พิมพ์ข้อความท้าทาย
Environment variables ถูก copy จาก parent process (irb) ไป child process (mogrify)
นี่ไม่ใช่ "hack" แค่การทำงานของ env variables ถูก copy จาก parent ไป child ถ้ารัน malware มันจะ inherit env variables เหมือน app อื่นๆ
2 ทางที่เกิดได้:
ใครหลอกให้ติดตั้ง malicious software ใน toolchain
"Benign" toolchain piece มี vulnerability ถูก exploit เปิดเผย env variables
แก้จริงคือ proactive ป้องกันทั้ง 2 แต่มี precautionary step จำกัด damage ถ้า ENV stealing bandit เข้ามาใน toolchain
Sanitizing the Environment
เวลา shell out จาก Ruby รัน imagemagick หรือโปรแกรมอื่น มัน inherit copy ของ app ENV ถ้ามี secrets ใน ENV มันได้ไปด้วย เว้นแต่ strip ออก
Override specific environment variables ตอนสร้าง process ใหม่ โดยส่ง hash ไป system method:
วิธีส่ง custom environment variables เข้า Ruby's system method
อยากหยุดส่ง environment variables ทั้งหมดตอน shell out อาจทำแบบนี้ สร้าง hash mirror ENV แต่ values ทั้งหมดเป็น nil ไม่สวยแต่วิธีเดียวที่ผมหาเจอ remove all env vars ตอน execute shell command
วิธีหยุดส่ง environment variables ตอนรัน shell command จาก Ruby
Don't throw the baby out with the bathwater
Inheritance เป็น feature มีประโยชน์ที่สุดของ ENV variables
สมมติรัน command เขียน S3 Environment variable inheritance แปลว่า command share API keys จาก Ruby app ได้ seamless จะเสียความสามารถนี้ถ้าไม่ allow inheritance
Persistence
ทุก process มี env variables ตัวเอง ตายพร้อม process ตาย ตั้ง env variables ใน Ruby app ได้แต่มันหายตอน app quit
ต้องการ env variable อยู่หลัง reboot ต้องเก็บไว้ที่ไหนที่หนึ่ง ที่นั่นมักเป็น filesystem
Don't use your app's git repo
คน github ขอให้ซื่อสัตย์เท่าเรา แต่อยากให้ทุกคน access source code ได้ API keys รัน AWS bill $10,000 ไหม?
Avoid using .bashrc or .bash-profile for secrets
เก็บ secrets ใน .bashrc ส่งเป็น env variables ไปทุก program ที่รันเป็น user ใหญ่ส่วนใหญ่ไม่ต้องรู้ secrets ทำไมให้พวกมัน?
Only reveal your secrets to the processes that need them
ถ้า Rails app process เดียวที่ต้องรู้ HONEYBADGER_API_KEY ควรทำให้ available เฉพาะ process นั้น
มี gems ให้เพิ่ม env variables ใน file ที่ load ตอน Rails เริ่ม env vars เหล่านี้ available เฉพาะ Rails process และ child processes มี section เรื่อง figaro และ dotenv gems ท้าย The Rubyist's Guide To Environment Variables
Secure your configuration files
ถ้า load environment จาก config file อยากให้ permissions ตั้งให้ readable เฉพาะ user รัน web app
ทำ config files readable เฉพาะ user ที่ต้องอ่าน
เพราะไม่ check เข้า github ต้อง SSH เข้า server edit manual หรือใช้ tool เช่น Chef manage ให้
Build "firewalls" where possible
สิ่งดีของ AWS คือสร้าง access control policies ได้ super granular Service providers เยอะมี feature แบบนี้
หมายถึงอะไร? สร้าง API keys ชุดหนึ่ง allow upload ได้แค่ single bucket S3 ควรสร้าง keypairs แยกกิจกรรม ชุด upload images ชุด database backup ฯลฯ
Operate แบบนี้ limit damage ของ security breach ใดๆ หนึ่ง