guest@websec ~ % man 19-misconfiguration-and-errors
19 · การตั้งค่าผิดพลาดและการจัดการ error
การตั้งค่าผิดตอนนี้อยู่อันดับ 2 ของ OWASP และ "จัดการ error ผิด" เป็นหมวดใหม่ ทั้งสองเกี่ยวกับสิ่งรอบโค้ด: อะไรเปิดทิ้งไว้ อะไรถูกเปิดเผย และเกิดอะไรขึ้นเมื่อมีปัญหา
19.1 การตั้งค่าความปลอดภัยผิดพลาด
สิ่งที่ผู้ตรวจมักเจอ:
- โหมด debug ใน production แสดง stack trace ให้ทุกคนเห็น
- แดชบอร์ด (คิวงาน, feature flag, เครื่องมือฐานข้อมูล) ที่ไม่ต้องล็อกอิน
- ข้อมูลล็อกอินเริ่มต้นหรือที่ใช้ร่วมกันบนฐานข้อมูล หน้า admin และเครื่องมือของบุคคลที่สาม
- ไฟล์ที่ไม่ควรเป็นสาธารณะ:
/.git/,.env, ไฟล์ backup (db.sql.gz), ไฟล์ swap ของ editor, source map ที่มี secret - bucket ของ cloud storage ที่ทุกคนอ่าน (หรือเขียน) ได้
exposure:
ค่าเริ่มต้น production ของ Rails ดี: ไม่มีหน้า debug ไม่มี web console ช่องโหว่ที่พบบ่อยเป็นของเรา: mount Sidekiq, Mission Control หรือ Flipper โดยไม่มีการล็อกอิน หรือรันโหมด development บนเซิร์ฟเวอร์สาธารณะ
# config/routes.rb: every dashboard behind an admin constraint authenticate_admin = ->(req) { Session.find_by(id: req.cookie_jar.signed[:session_id])&.user&.admin? } constraints(authenticate_admin) do mount Sidekiq::Web => "/sidekiq" mount MissionControl::Jobs::Engine => "/jobs" mount Flipper::UI.app(Flipper) => "/flipper" end # config/environments/production.rb (verify these) config.consider_all_requests_local = false # generic error pages config.force_ssl = true config.hosts = ["app.example.com"] config.log_level = :info # :debug can log SQL with values
19.2 การจัดการสถานการณ์ผิดปกติที่ไม่ดี
เรื่องนี้ว่าด้วยสิ่งที่เกิดเมื่อมีปัญหา มีสามรูปแบบที่สร้างความเสียหายมากที่สุด:
Fail open
ถ้าการตรวจความปลอดภัย error ให้ ปฏิเสธ บั๊กคลาสสิก: บริการตรวจสิทธิ์ timeout, rescue กว้างๆ กลืน error ไป แล้วโค้ดทำต่อเหมือนได้รับอนุญาต
error handling:
การทำงานที่เสร็จครึ่งๆ กลางๆ
ถ้าพังกลางทาง เงินอาจถูกหักแต่ไม่ถูกโอนเข้า ให้ห่อการเขียนที่เกี่ยวข้องไว้ใน transaction
การจัดการ error ที่รั่วหรือไม่มี
- แสดง ข้อความง่ายๆ พร้อมรหัสอ้างอิง ให้ผู้ใช้ เก็บรายละเอียดไว้ใน log
- ตั้ง ขีดจำกัด ให้ทุกอย่างที่โตได้: ไฟล์อัปโหลด ขนาดหน้า timeout
rescue => eเปล่าๆ รอบโค้ดความปลอดภัยคือธงแดง
transaction rollback เมื่อ error และ
Rails.error.report ส่ง error ไปยัง tracker ส่วนการ fail closed และ timeout ของการเรียกออกไปข้างนอก (ค่าเริ่มต้น 60 วินาที!) เป็นหน้าที่เราdef destroy
customer = Customer.find(params[:id])
return head :forbidden unless allowed_to_delete?(customer)
customer.destroy!
end
private
def allowed_to_delete?(customer)
PermissionService.allowed?(Current.user, :delete, customer)
rescue PermissionService::Timeout => e
Rails.error.report(e, context: { customer_id: customer.id })
false # fail CLOSED
end
rescue StandardError then true # fail OPEN: any error grants access
# all-or-nothing writes
ActiveRecord::Base.transaction do
from.lock!.update!(balance: from.balance - amount)
to.lock!.update!(balance: to.balance + amount)
end
Net::HTTP.start(host, 443, use_ssl: true, open_timeout: 2, read_timeout: 5) { … }