GHB Security

From KB

การทำ Pentest ของระบบที่เป็น Springboot ที่การทดสอบอย่างไร เพื่อป้องกันช่องโหว่ของ API

การทำ Pentest (Penetration Testing) ของระบบที่ใช้ Spring Boot เพื่อป้องกันช่องโหว่ของ API ควรมีขั้นตอนดังนี้:

  1. การเตรียมพร้อม:
    • ทำความเข้าใจกับระบบ: รวบรวมข้อมูลเกี่ยวกับแอปพลิเคชัน, API, และส่วนประกอบที่เกี่ยวข้อง เช่น URL, endpoint, วิธีการ authentication, และ authorization
    • กำหนดขอบเขตการทดสอบ: ระบุขอบเขตที่แน่นอนของการทดสอบ เช่น ส่วนไหนที่สามารถทดสอบได้ และส่วนไหนที่ห้ามทดสอบ
    • รับอนุญาต: ตรวจสอบให้แน่ใจว่าได้รับอนุญาตจากผู้ดูแลระบบหรือเจ้าของระบบก่อนทำการทดสอบ
  2. การทดสอบช่องโหว่ทั่วไปของ API:
    • การตรวจสอบการ authentication และ authorization: ตรวจสอบว่า API มีการป้องกันที่เหมาะสมในการตรวจสอบตัวตน (authentication) และสิทธิ์การเข้าถึง (authorization)
    • การทดสอบ SQL Injection: ตรวจสอบว่า API มีการป้องกันการโจมตีด้วย SQL Injection หรือไม่ โดยการป้อนข้อมูลที่เป็นอันตรายเข้าไปใน parameter ที่คาดว่าน่าจะมีการ query ข้อมูลใน database
    • การทดสอบ XSS (Cross-Site Scripting): ตรวจสอบว่า API มีการป้องกันการโจมตีด้วย XSS หรือไม่ โดยการป้อนข้อมูลที่เป็นอันตรายเข้าไปใน parameter ที่จะถูกแสดงผลบนหน้าเว็บ
    • การทดสอบ CSRF (Cross-Site Request Forgery): ตรวจสอบว่า API มีการป้องกันการโจมตีด้วย CSRF หรือไม่ โดยการส่ง request ที่เป็นอันตรายไปยัง API
  3. การทดสอบช่องโหว่เฉพาะใน Spring Boot:
    • การตรวจสอบการตั้งค่าความปลอดภัยของ Spring Security: ตรวจสอบว่ามีการตั้งค่า Spring Security อย่างถูกต้องเพื่อป้องกันช่องโหว่ เช่น การใช้ JWT token หรือ OAuth2
    • การทดสอบการจัดการ session: ตรวจสอบว่า session ที่ใช้งานใน Spring Boot มีความปลอดภัย เช่น การป้องกัน session fixation
    • การทดสอบการจัดการ exception: ตรวจสอบว่าแอปพลิเคชันมีการจัดการ exception อย่างเหมาะสม เพื่อไม่ให้ข้อมูลที่เป็นอันตรายหรือข้อมูลที่เป็นความลับถูกเปิดเผย
  4. การใช้เครื่องมือทดสอบ:
    • ใช้เครื่องมือเช่น OWASP ZAP หรือ Burp Suite: เครื่องมือเหล่านี้สามารถช่วยในการตรวจหาช่องโหว่ของ API โดยอัตโนมัติ
    • ใช้เครื่องมือ fuzzing: เพื่อส่งข้อมูลที่หลากหลายและสุ่มไปยัง API เพื่อหาช่องโหว่
  5. การวิเคราะห์ผลการทดสอบ:
    • ตรวจสอบผลลัพธ์จากการทดสอบ: วิเคราะห์ผลการทดสอบจากเครื่องมือและตรวจสอบว่าช่องโหว่ที่พบมีผลกระทบอย่างไรบ้าง
    • จัดลำดับความสำคัญ: จัดลำดับความสำคัญในการแก้ไขช่องโหว่ตามระดับความเสี่ยง
  6. การแก้ไขและปรับปรุง:
    • การแก้ไขช่องโหว่: ทำการแก้ไขช่องโหว่ที่พบในการทดสอบ
    • การทดสอบซ้ำ: หลังจากแก้ไขแล้ว ควรทำการทดสอบซ้ำเพื่อยืนยันว่าช่องโหว่ถูกแก้ไขเรียบร้อยแล้ว
    • การปรับปรุงการตั้งค่าและการพัฒนา: ปรับปรุงการตั้งค่าและแนวทางการพัฒนาเพื่อป้องกันไม่ให้เกิดช่องโหว่ในอนาคต

การทำ Pentest เป็นกระบวนการที่ต่อเนื่องและควรทำอย่างสม่ำเสมอเพื่อให้แน่ใจว่าระบบของคุณมีความปลอดภัยจากช่องโหว่ต่าง ๆ อยู่เสมอ

ใน Java Spring-boot มีวิธีรัน Command เพื่อสรุป Route API ทั้งหมดได้หรือไม่

ใน Java Spring Boot คุณสามารถใช้คำสั่งเพื่อสรุป Route API ทั้งหมดในแอปพลิเคชันได้โดยการใช้งาน Spring Boot Actuator หรือเขียนโค้ดเฉพาะเพื่อดึงข้อมูลจาก RequestMappingHandlerMapping ใน Spring MVC

วิธีที่ 1: ใช้ Spring Boot Actuator

  1. เพิ่ม Dependency ใน pom.xml:
  2. เปิดใช้งาน Actuator Endpoint ใน application.properties:
  3. เรียกดู API Endpoint:
    • รันแอปพลิเคชัน Spring Boot
    • เปิดเบราว์เซอร์หรือใช้เครื่องมืออย่าง curl เพื่อเรียกดูที่ URL: http://localhost:8080/actuator/mappings ตัวอย่าง:

วิธีที่ 2: เขียนโค้ดเฉพาะเพื่อดึง Route API

  1. สร้าง Bean ที่จะดึงข้อมูลจาก RequestMappingHandlerMapping:
  2. รันแอปพลิเคชัน Spring Boot: เมื่อแอปพลิเคชันรัน, Bean ที่สร้างขึ้นจะพิมพ์รายการของ API Endpoints ใน console

การใช้โค้ดเหล่านี้จะช่วยให้คุณสามารถดึงข้อมูลและสรุป Route API ทั้งหมดในแอปพลิเคชัน Spring Boot ได้ง่าย ๆ

จากภาพที่แสดง HTTP Status 401 - Unauthorized หมายความว่าคุณต้องทำการ authentication (การยืนยันตัวตน) เพื่อเข้าถึง endpoint ของ Spring Boot Actuator นี่คือวิธีการแก้ไข:

วิธีการเปิดใช้งานการ authentication สำหรับ Actuator

  1. เพิ่ม dependency สำหรับ Spring Security ใน pom.xml:
  2. เพิ่มการตั้งค่าการรักษาความปลอดภัยใน application.properties:
  3. สร้าง Security Configuration Class: สร้างไฟล์ใหม่ เช่น SecurityConfig.java ใน package ของคุณ และกำหนดค่า Spring Security:
  4. รันแอปพลิเคชัน: เมื่อรันแอปพลิเคชันใหม่ คุณสามารถเข้าถึง actuator endpoint โดยใช้ข้อมูลการเข้าสู่ระบบที่กำหนดใน application.properties (ในตัวอย่างคือ admin และ admin123)
  5. ลองเข้าถึง URL:
    • เปิดเบราว์เซอร์อีกครั้ง และเข้าไปที่ http://localhost:8081/actuator/mappings
    • ใช้ข้อมูลการเข้าสู่ระบบที่ตั้งไว้ (admin และ admin123) เพื่อเข้าถึงข้อมูล

เพียงเท่านี้คุณก็จะสามารถดู Route API ทั้งหมดของแอปพลิเคชันได้แล้ว

กรณี Login ผ่าน Return Token { "response_code": "200", "message": "Valid user", "username": "SCMS001", "staffName": "ฟร้อง", "userId": 219, "userIdReference": null, "pinCode": null, "token": "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJTQ01TMDAxIiwicm9sZSI6bnVsbCwiY3JlYXRlZCI6MTcyMTk2OTI4MzMwOCwic3RhZmZuYW1lIjoi4Lif4Lij4LmJ4Lit4LiHIiwiaWQiOjIxOSwiZXhwIjoxNzIyMDA1MjgzfQ.dlZuFaPA6tfgBh2x8X9p7vX6xlhZ8wIybxFzGJ1vB0mnaOeOmv0mpGWNMESK_elCnW2qqdgdI9EKeo1hEsg5rg", "org_id": null, "org_br_id": null, "dept_id": null, "cust_corp_id": null, "cust_corp_br_id": null, "cust_corp_dept_id": null, "online_status": "online", "branch_name_th": null, "branch_id": null } กรณี Login ไม่ผ่าน Return { "response_code": "400", "message": "User not found", "username": null, "staffName": null, "userId": null, "userIdReference": null, "pinCode": null, "token": null, "org_id": null, "org_br_id": null, "dept_id": null, "cust_corp_id": null, "cust_corp_br_id": null, "cust_corp_dept_id": null, "online_status": null, "branch_name_th": null, "branch_id": null } แบบนี้มีช่องโหว่หรือไม่

จากข้อมูลที่ให้มา เกี่ยวกับการ Login และการส่งคืน Token เมื่อผู้ใช้ล็อกอินสำเร็จ หรือการตอบกลับเมื่อผู้ใช้ไม่สามารถล็อกอินได้ สิ่งสำคัญในการพิจารณาว่ามีช่องโหว่หรือไม่คือการตรวจสอบขั้นตอนการจัดการข้อมูลต่างๆ ดังนี้:

การตรวจสอบความปลอดภัยของการ Login และการจัดการ Token

  1. การใช้ HTTPS:
    • ตรวจสอบว่า API ใช้ HTTPS ในการรับส่งข้อมูล เพื่อป้องกันการดักจับข้อมูลระหว่างการรับส่ง
  2. การจัดการ Token:
    • ตรวจสอบว่า Token ที่สร้างขึ้นมีความปลอดภัย (เช่น ใช้ JWT ที่เข้ารหัสด้วย secret key ที่ปลอดภัย)
    • Token ควรมีเวลาในการหมดอายุ (expiration time) เพื่อป้องกันการใช้งานที่ไม่ถูกต้อง
  3. การป้องกัน Brute Force Attack:
    • ควรมีการจำกัดจำนวนครั้งในการพยายามเข้าสู่ระบบ เพื่อป้องกันการโจมตีด้วยการลองรหัสผ่านหลายๆ ครั้ง
    • อาจเพิ่มการตรวจสอบ Captcha หลังจากความพยายามเข้าสู่ระบบหลายครั้งไม่สำเร็จ
  4. การเก็บข้อมูลที่จำเป็น:
    • ตรวจสอบว่าข้อมูลที่เก็บใน Token หรือที่ส่งกลับมีเฉพาะข้อมูลที่จำเป็น ไม่เก็บข้อมูลที่เป็นความลับหรือไม่จำเป็น
    • การตอบกลับเมื่อผู้ใช้ไม่สามารถล็อกอินได้ ควรให้ข้อมูลที่ไม่เป็นอันตราย เช่น "User not found" โดยไม่บอกรายละเอียดเพิ่มเติม
  5. การป้องกัน CSRF:
    • ใช้การตรวจสอบ CSRF เพื่อป้องกันการโจมตีจากการเรียกใช้ API โดยไม่ตั้งใจจากเว็บอื่น
  6. การจัดการ Error Response:
    • ตรวจสอบว่าข้อความ error ที่ส่งกลับไม่ให้ข้อมูลที่เป็นอันตราย เช่น การเปิดเผยโครงสร้างของฐานข้อมูล หรือรายละเอียดอื่นๆ ที่อาจใช้ในการโจมตี

ตัวอย่างเพิ่มเติมของโค้ดเพื่อเพิ่มความปลอดภัย

  • การตรวจสอบ Token ใน Spring Boot Security:
  • การตั้งค่า Token Expiration:

สรุป

จากข้อมูลที่ให้มา การทำงานของ API ยังมีบางจุดที่ควรตรวจสอบและปรับปรุงเพื่อความปลอดภัย เช่น การใช้ HTTPS, การจัดการ Token, และการป้องกันการโจมตี Brute Force และ CSRF การตรวจสอบเหล่านี้จะช่วยให้ API ของคุณมีความปลอดภัยมากขึ้น

@PostMapping("/auth/genesys/signin") public ResponseEntity<Object> getAuthenticationGenesys(@RequestBody GenesysAuthenticationBean body, HttpServletRequest request) throws AuthenticationException { String email = body.getEmail(); JwtUser userDetails; String headerApikey = request.getHeader("api_key"); if (!apiKey.equals(headerApikey)) { return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Unauthorized"); } try { UserInfoIDSBean userSystem = userRepository.findUserProfileByEmail(email); if (Optional.ofNullable(userSystem).isPresent()) { userDetails = (JwtUser) userDetailsService.loadUserByUsername(userSystem.getUsername()); final String token = jwtTokenUtil.generateToken(userDetails); if (updateTokenExpire(userSystem.getUsername(), token)) { userRepository.lastLoginDatetime(userSystem.getUsername()); return ResponseEntity.ok(code200Response(userSystem.getUsername(), token)); } else { return ResponseEntity.ok(code400Response()); } } else { return ResponseEntity.ok(code400Response()); } } catch (Exception ex) { logger.info("Got an exception. {}", ex.getMessage()); return ResponseEntity.ok(code400Response()); } } --- Bean --- package th.co.scms.allway.api.bean; import lombok.Data; @Data public class GenesysAuthenticationBean { private String email; }

จากโค้ดที่คุณให้มา การทำงานในการตรวจสอบการเข้าสู่ระบบและการจัดการ token นั้นมีหลายจุดที่ควรพิจารณาเพื่อเพิ่มความปลอดภัยและประสิทธิภาพของ API ดังนี้:

จุดที่ควรปรับปรุงเพื่อความปลอดภัย

  1. การตรวจสอบ API Key:
    • ตรวจสอบว่า apiKey มีการตั้งค่าอย่างปลอดภัย และไม่ถูกเปิดเผยในโค้ด
    • API Key ควรได้รับการเก็บในที่ที่ปลอดภัย เช่น environment variables หรือ configuration file ที่เข้ารหัส
  2. การจัดการ Exceptions:
    • ไม่ควรใช้ catch (Exception ex) เพราะจะทำให้การจับข้อผิดพลาดไม่ชัดเจน ควรจับข้อผิดพลาดที่เฉพาะเจาะจง เช่น UsernameNotFoundException, BadCredentialsException เป็นต้น
  3. การจัดการ Token:
    • ควรตรวจสอบว่า token ที่สร้างขึ้นมีการเข้ารหัสที่ปลอดภัย และมีเวลาหมดอายุ (expiration time) ที่เหมาะสม
  4. การป้องกัน Brute Force Attack:
    • ควรมีการจำกัดจำนวนครั้งในการพยายามเข้าสู่ระบบ เช่น ล็อคบัญชีผู้ใช้ชั่วคราวหากพยายามเข้าสู่ระบบหลายครั้งไม่สำเร็จ

ตัวอย่างโค้ดปรับปรุง

สรุป

  • ตรวจสอบการตั้งค่า apiKey ให้ปลอดภัย
  • จัดการ exception ให้เฉพาะเจาะจงและเหมาะสม
  • เพิ่มการจัดการ token ที่มีเวลาหมดอายุ
  • เพิ่มการป้องกัน Brute Force Attack

การปรับปรุงเหล่านี้จะช่วยเพิ่มความปลอดภัยและประสิทธิภาพของระบบการล็อกอินใน Spring Boot API ของคุณ