guest@websec: ~/websec/19-misconfiguration-and-errors/th — zsh — 100×40 เขียนโดย SaKKo ENTH โค้ด:

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 ที่ทุกคนอ่าน (หรือเขียน) ได้
sim: ตรวจการตั้งค่า productionแก้สิ่งที่พบ แล้วดูการเปิดเผยลดลง
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 ไป แล้วโค้ดทำต่อเหมือนได้รับอนุญาต

sim: บริการตรวจสิทธิ์ล่มfail open เทียบกับ fail closed
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) { … }