API Security Checklist

Checklist ที่ต้องให้ความสำคัญเมื่อมีการสร้าง API ในช่วงการออกแบบ ทดสอบระบบ และการปล่อยให้คนนอกใช้

Authentication (การพิสูจน์ตัวตน)

  1. ไม่ควรใช้ Basic Auth (การ authen ปกติด้วยusername password) สำหรับการพิสูจน์ตัวตน แต่ให้ใช้รูปแบบมาตรฐานสากลแทน(e.g. JWT, OAuth).
  2. ไม่ต้องเสียเวลาสร้างวิธี Authentication ใหม่ขึ้นมา ให้ใช้ที่มีอยู่ในมาตรฐานไปเลย
  3. ให้มีการจำกัดจำนวนครั้งในการพยายาม authen และสร้างระบบล็อคกรณีพยายามเกินกำหนด
  4. ข้อมูลที่สำคัญควรมีการเข้ารหัสเสมอ


JWT (JSON Web Token)

  1. key ในการ generate token ควรมีความซับซ้อนสูง เพื่อป้องกันการ brute force หาตัวเข้ารหัส
  2. ไม่ควรมีการแกะข้อมูลหรือขั้นตอนการถอดข้อมูลในฝั่ง client. ให้มีเฉพาะในฝั่ง server เท่านั้น โดยอาจใช้วิธีเข้ารหัสด้วย HS256 หรือ RS256 เอา
  3. พยายามให้ token หมดอายุให้ไวที่สุดเท่าที่จะเป็นไปได้ (TTL, RTTL)
  4. ไม่ควรเก็บข้อมูลสำคัญใน payload ของ JWT เพราะอาจถูกแกะได้ ง่าย


OAuth

  1. มีการ validate redirect_uri ในฝั่ง server โดยยอมรับuriเฉพาะที่มีอยู่ในลิสต์ที่เราเชื่อถือเท่านั้น (whitelist)
  2. บังคับให้มีการใช้ response_type เป็น code เสมอ (พยายามเลี่ยง response_type=token)
  3. ตัวแปร state ให้ใช้ random hash เพื่อป้องกัน CSRF (Cross Site Request Forgery) ในช่วง OAuth authentication.
  4. กำหนด scope และมีการ validate scope ตัวแปรสำหรับแต่ละแอป


Access

  1. จำกัดจำนวนสูงสุดของ request เพื่อป้องกัน DDoS / Bruteforce
  2. ใช้ https เพื่อป้องกัน MITM (Man In The Middle Attack).
  3. ใช้ HSTS header กับ SSL เพื่อป้องกัน SSL Strip attack.


Input

  1. ใช้คำสั่ง HTTP ตาม operation ที่ทำ เช่น GET (read)POST (create)PUT/PATCH (replace/update) and DELETE (to delete a record) และตอบกลับด้วย 405 Method Not Allowed ถ้าไม่มีการรองรับ request ด้วย method นั้นในระบบ.
  2. Validate content-type ใน header ขา request (Content Negotiation) โดยยอมให้ส่งมาเฉพาะ format ที่กำหนด (e.g. application/xml, application/json... และอื่นๆ) และตอบกลับด้วย 406 Not Acceptable ถ้า format ที่ส่งมาไม่ถูก.
  3. Validate content-type ของ data ที่รับมาทุกครั้ง(e.g. application/x-www-form-urlencodedmultipart/form-data ,application/json... ).
  4. Validate ข้อมูลที่ user ใส่เข้ามาทุกครั้งเพื่อป้องกันช่องโหว่ที่โดนกันบ่อยๆ (e.g. XSSSQL-InjectionRemote Code Execution ... etc).
  5. ห้ามเอาข้อมูลสำคัญไปใส่ไว้ใน URL (เช่น /servicexxx?creditcardnum=1234) แต่ให้ไปแปะไว้ใน authorization header แทน (credentialsPasswordssecurity tokens, or API keys)
  6. ทำ API Gateway เพื่อให้สามารถทำ caching, Rate Limit, Spike Arrest, และการจัดสรรค์ทรัพยากรสำหรับ API ได้อย่างยืดหยุ่น


Processing

  1. ตรวจดูว่า endpoints ทุกจุดอยู่ภายใต้ authentication เพื่อป้องกันช่องโหว่ที่ทำให้คนอื่นมาเรียกใช้โดยไม่จำเป็นต้องพิสูจน์ตัวตน
  2. ไม่ควรนำ resource ID ของ user ไปใช้ (/user/654321/orders) แต่ให้ไปใช้แบบ /me/orders แทน เพื่อป้องกัน user เปลี่ยนไปใช้ของคนอื่น
  3. เลข ID ของ user ไม่ควรมีการสร้างแบบไล่ลำดับเพิ่มไปเรื่อยๆ แต่ให้สร้าง UUID แทน
  4. ถ้ามีการ parsing ไฟล์ XML, ให้ปิดส่วนของ Entity parsing ไว้เพื่อเลี่ยงที่จะโดนช่องโหว่ต่างๆเช่น (XML external entity attack, Billion Laughs/XML bomb)
  5. ใช้ CDN เมื่อจำเป็นต้องมีการ upload ไฟล์จาก client
  6. หากต้องเผชิญกับข้อมูลขนาดใหญ่ ให้ใช้ Workers กับ คิวในการจัดการเพื่อให้มีการตอบข้อมูลกลับได้อย่างรวดเร็วจะได้ไม่เกิดคอขวดขึ้น
  7. อย่าลืมปิดโหมด DEBUG ใน code หากทำไว้


Output

  1. ตั้ง X-Content-Type-Options: nosniff ใน header.
  2. ตั้ง X-Frame-Options: deny ใน header.
  3. ตั้ง Content-Security-Policy: default-src 'none' ในheader.
  4. เอา fingerprinting headers ออก - X-Powered-ByServerX-AspNet-Version etc.
  5. กำหนด content-type ใน response เช่นถ้าต้องการส่งข้อมูลที่เป็น json กลับไป ก็เซ็ต content-type เป็น application/json ไปเลย
  6. ไม่ต้องส่งข้อมูลส่งข้อมูลสำคัญกลับไปหา client (credentialsPasswordssecurity tokens).
  7. ตอบ status code ที่ตรงกับ operation กลับไป (e.g. 200 OK400 Bad Request401 Unauthorized405 Method Not Allowed ... etc)


CI & CD

  1. ตรวจสอบ design กับ implementation ในขั้น unit/integration test อย่างครอบคลุม
  2. ให้ใช้ code review process ไม่ใช่ว่าตัวเองพอใจก็โอเคแล้ว
  3. มั่นใจว่าทุกอย่างใน service ปลอดไวรัสแล้วก่อนจะนำขึ้น production รวมถึง lib ของพวก vendor กับ dependencies อื่นๆด้วย
  4. ออกแบบวิธี rollback ไว้ด้วยก่อนจะนำขึ้นไป เพราะเวลาเกิดปัญหาจะได้ย้อนกลับมาใช้ version เก่าไปก่อนได้ (อาจพบได้บ่อยตอนพัฒนา feature ใหม่ๆ)
0
685