การทำ certificates pinning กับ alamofire

Wasith T. (Bai-Phai)
กูโค้ด
Published in
2 min readNov 1, 2019

Certificate and Public Key Pinning เป็นหนุ่งใน guideline ของ OWASP ที่แนะนำให้ทำ เพื่อเพิ่มความปลอดภัย หรือถ่วงเวลาในการ reserve engineer ของแอปฯ ต่าง ๆ ได้

ซึ่งถ้าใครใช้ Alamofire ก็จะมีคำแนะนำง่าย ๆ ว่า

let serverTrustPolicies: [String: ServerTrustPolicy] = [
"test.example.com": .pinCertificates(
certificates: ServerTrustPolicy.certificates(),
validateCertificateChain: true,
validateHost: true
),
]
let serverTrustPolicyManager =
ServerTrustPolicyManager(policies: serverTrustPolicies)
let sessionManager = SessionManager(
serverTrustPolicyManager: serverTrustPolicyManager)

แล้วพอเรามีหลาย environments

เช่น dev, test, UAT, production และเราต้องรองรับหลายโดเมนด้วย

เราก็เผลอที่จะใส่ domain ของ dev, test ที่ปกติจะเปิด debug mode เอาไว้ซึ่ง อาจทำให้ผู้ไม่ประสงค์ดีพบ domain ของ dev และ test และสามารถแกะ api ของเราได้ง่ายขึ้น

ตรงนี้เราสามารถใช้ Preprocessor Macros (#if DEBUG) มาช่วยได้

ซึ่งตรงนี้จะไม่ทำให้ domain name หลุดออกไป หรือถ้ามีการระบุ domain name ผ่าน build setting variables แยกตาม environment มาอยู่แล้วก็อาจจะไม่เป็นไร

ไม่ให้ของหลุดออกไป

คำสั่ง ServerTrustPolicy.certificates() จะเป็นการหยิบ certificates จากทั้งหมดใน bundle เข้ามา ซึ่งอาจจะมีของ dev, test, UAT ติดขึ้นไปที่แอปปของ production ด้วยก็ได้

ตรงนี้มีคำแนะนำสองทางซึ่งจะทำทางแรกอย่างเดียว หรือทำทั้งสองทางก็ได้

  1. ตั้ง EXCLUDED_SOURCE_FILE_NAMES ในแต่ละ build configurations โดยเราสามารถใช้ wildcard ได้เช่น *.cer และเรา override ในแต่ละ config ที่ key INCLUED_SOURCE_FILE_NAMES ว่า my-service-test.cer มันจะดึงไฟล์ตามที่ระบุไปใน bundle ด้วย
  2. ระบุชื่อไฟล์ตรง ๆ ว่าอยากได้ไฟล์นี้เช่น แล้วค่อยใส่ใน ServerTrustPolicy.pinCertificates
static func getCharlesCertificate() -> NSData {
let charlesCertName = "charles-ssl-proxying-certificate"
let pathToCert = Bundle.main.path(
forResource: charlsCertName, ofType: "cer")!
return try! NSData(contentsOfFile: pathToCert)
}
let charlesCert = SecCertificateCreateWithData(
nil,
getCharlesCertificate())
ตัวอย่าง excluded และ included source file names

ถ้าใครใช้ Moya ก็สามารถใช้เหมือน ๆ กัน เพราะจริง ๆ แล้ว Moya ก็ใช้ Alamofire อยู่ข้างล่างเหมือนกัน

ต้องการดึง certificate มาไว้ในแอป

สามารถทำได้หลายวิธี แต่จะขอยกตัวอย่างแค่ 1 วิธี คือการดึงจาก Firefox

  1. เข้าไปที่เว็บไซต์นั้น ๆ
  2. กดที่รูปแม่กุญแจที่ address bar หน้า uri ของเว็บนั้น ๆ
  3. กดลูกศรที่หลังคำว่า Conneciton secure
  4. กดที่ More information
  5. กดที่ View Certificate ที่ tab Security
  6. กดที่ tab Details
  7. กดที่ export แล้ว save ไว้ที่ต้องการ
  8. ลากเข้าไปที่ Xcode

แล้วพบกันใหม่

สวัสดีครับ

--

--

Wasith T. (Bai-Phai)
กูโค้ด

ตบมือเป็นกำลังใจให้ผมด้วยนะครับ 😘