Siam Thanat Hack Co., Ltd.

OWASP Mobile Top 10:2024

คู่มือ 10 หมวดความเสี่ยงใน OWASP Mobile Top 10:2024 ฉบับปัจจุบัน สำหรับ Android, iOS และบริการที่แอปพึ่งพา

ฉบับ 2024. ใช้ชื่อหมวดความเสี่ยงตามเอกสาร OWASP ทางการ

M1

Improper Credential Usage

Improper Credential Usage คือแอปมือถือฝัง, เก็บ, ส่ง หรือใช้ password, API key, token หรือ session อย่างไม่ปลอดภัย เช่น hardcode secret ใน binary หรือเก็บรหัสผ่านในพื้นที่ทั่วไปของเครื่อง เมื่อแอปถูก reverse engineer หรือโทรศัพท์สูญหาย ผู้โจมตีอาจนำข้อมูลยืนยันตัวตนไปใช้กับ backend ได้.

สรุปความเสี่ยงแบบย่อ
สิ่งที่อาจผิดพลาดSecret, Token, API Key หรือรหัสผ่าน ถูกฝังในโค้ด นำกลับมาใช้ซ้ำ เปิดเผยสู่ภายนอก หรือจัดการโดยไม่มีวงจรชีวิตความปลอดภัยที่เหมาะสม
ผลกระทบต่อธุรกิจแพ็กเกจแอปพลิเคชันที่ถูกวิเคราะห์ย้อนกลับ หรือ Token ที่รั่วไหล อาจทำให้ผู้โจมตีเข้าถึงระบบ Backend หรือฟังก์ชันที่ได้รับการปกป้องได้อย่างต่อเนื่อง
จุดควบคุมแรกที่ควรตรวจไม่เก็บ Secret ระยะยาวไว้ในอุปกรณ์ฝั่ง Client
M1 attack path against a victim application and its mitigating control

ภาพเปรียบเทียบเส้นทางที่ไม่ปลอดภัยกับจุดควบคุมที่ตัดเส้นทางนั้น กดภาพเพื่อดูขนาดเต็ม.

ผลกระทบที่ควรพิจารณา

แพ็กเกจแอปพลิเคชันที่ถูกวิเคราะห์ย้อนกลับ หรือ Token ที่รั่วไหล อาจทำให้ผู้โจมตีเข้าถึงระบบ Backend หรือฟังก์ชันที่ได้รับการปกป้องได้อย่างต่อเนื่อง

แนวทางลดความเสี่ยง

  • ไม่เก็บ Secret ระยะยาวไว้ในอุปกรณ์ฝั่ง Client
  • ใช้ข้อมูลยืนยันตัวตนที่จำกัดขอบเขต สามารถเพิกถอนและหมุนเวียนเปลี่ยนรหัสได้
  • ปกป้องจุดกรอกข้อมูลและช่องทางส่งข้อมูลยืนยันตัวตน
ตัวอย่าง Android ด้วย Kotlin

ตัวอย่างที่มีช่องโหว่

import android.content.Intent
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity

class RedirectActivity : AppCompatActivity() {
    fun openRedirect(intent: Intent) {
        val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
        startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(rawTarget)))
    }
}

ตัวอย่างที่แก้ไขแล้ว

import android.content.Intent
import android.net.Uri
import androidx.browser.customtabs.CustomTabsIntent
import androidx.appcompat.app.AppCompatActivity

class RedirectActivity : AppCompatActivity() {
    private val allowedHosts = setOf("app.example.com")

    fun openRedirect(intent: Intent) {
        val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
        val target = Uri.parse(rawTarget)
        if (target.scheme != "https" || target.host !in allowedHosts) return
        CustomTabsIntent.Builder().build().launchUrl(this, target)
    }
}
ตัวอย่าง iOS ด้วย Swift

ตัวอย่างที่มีช่องโหว่

import UIKit

final class RedirectViewController: UIViewController {
    func openRedirect(rawTarget: String) {
        guard let target = URL(string: rawTarget) else { return }
        UIApplication.shared.open(target)
    }
}

ตัวอย่างที่แก้ไขแล้ว

import SafariServices
import UIKit

final class RedirectViewController: UIViewController {
    private let allowedHosts: Set<String> = ["app.example.com"]

    func openRedirect(rawTarget: String) {
        guard let target = URL(string: rawTarget),
              target.scheme == "https",
              let host = target.host,
              allowedHosts.contains(host) else { return }

        let browser = SFSafariViewController(url: target)
        present(browser, animated: true)
    }
}

M2

Inadequate Supply Chain Security

Inadequate Supply Chain Security คือแอป, SDK, dependency, ระบบ build หรือการเซ็น package ไม่ได้รับการควบคุมแหล่งที่มาและความถูกต้องเพียงพอ SDK ภายนอกที่ถูกเปลี่ยน, pipeline ที่ถูกยึด หรือ signing key รั่ว อาจทำให้แอปที่ติดตั้งบนเครื่องผู้ใช้ทำสิ่งที่ทีมไม่ได้ตั้งใจ.

สรุปความเสี่ยงแบบย่อ
สิ่งที่อาจผิดพลาดSDK มือถือ, Build Plugin, ระบบลงนามดิจิทัล และ Dependency ภายนอก ขาดการกำกับดูแลและความปลอดภัยในห่วงโซ่อุปทานที่เพียงพอ
ผลกระทบต่อธุรกิจSDK หรือ Release Pipeline ที่ถูกโจมตีอาจฝังระบบติดตาม แอบส่งออกข้อมูลสำคัญ หรือเปลี่ยนแปลงพฤติกรรมการทำงานของแอปพลิเคชัน
จุดควบคุมแรกที่ควรตรวจจัดทำบัญชี SDK ภายนอกและตรวจสอบเส้นทางการรับส่งข้อมูล
M2 attack path against a victim application and its mitigating control

ภาพเปรียบเทียบเส้นทางที่ไม่ปลอดภัยกับจุดควบคุมที่ตัดเส้นทางนั้น กดภาพเพื่อดูขนาดเต็ม.

ผลกระทบที่ควรพิจารณา

SDK หรือ Release Pipeline ที่ถูกโจมตีอาจฝังระบบติดตาม แอบส่งออกข้อมูลสำคัญ หรือเปลี่ยนแปลงพฤติกรรมการทำงานของแอปพลิเคชัน

แนวทางลดความเสี่ยง

  • จัดทำบัญชี SDK ภายนอกและตรวจสอบเส้นทางการรับส่งข้อมูล
  • จำกัดและตรวจสอบสิทธิ์ในการลงนามดิจิทัลและการ Release แอปพลิเคชัน
  • ตรวจสอบที่มา ความถูกต้องสมบูรณ์ และประกาศอัปเดตของแพ็กเกจ
ตัวอย่าง Android ด้วย Kotlin

ตัวอย่างที่มีช่องโหว่

import android.content.Intent
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity

class RedirectActivity : AppCompatActivity() {
    fun openRedirect(intent: Intent) {
        val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
        startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(rawTarget)))
    }
}

ตัวอย่างที่แก้ไขแล้ว

import android.content.Intent
import android.net.Uri
import androidx.browser.customtabs.CustomTabsIntent
import androidx.appcompat.app.AppCompatActivity

class RedirectActivity : AppCompatActivity() {
    private val allowedHosts = setOf("app.example.com")

    fun openRedirect(intent: Intent) {
        val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
        val target = Uri.parse(rawTarget)
        if (target.scheme != "https" || target.host !in allowedHosts) return
        CustomTabsIntent.Builder().build().launchUrl(this, target)
    }
}
ตัวอย่าง iOS ด้วย Swift

ตัวอย่างที่มีช่องโหว่

import UIKit

final class RedirectViewController: UIViewController {
    func openRedirect(rawTarget: String) {
        guard let target = URL(string: rawTarget) else { return }
        UIApplication.shared.open(target)
    }
}

ตัวอย่างที่แก้ไขแล้ว

import SafariServices
import UIKit

final class RedirectViewController: UIViewController {
    private let allowedHosts: Set<String> = ["app.example.com"]

    func openRedirect(rawTarget: String) {
        guard let target = URL(string: rawTarget),
              target.scheme == "https",
              let host = target.host,
              allowedHosts.contains(host) else { return }

        let browser = SFSafariViewController(url: target)
        present(browser, animated: true)
    }
}

M3

Insecure Authentication and Authorization

Insecure Authentication and Authorization คือแอปยืนยันว่าใครเป็นผู้ใช้หรืออนุญาตให้ทำอะไรไม่ถูกต้อง เช่น ไม่ตรวจ token ให้ครบ, เชื่อ role ที่ส่งจาก client, หรือปล่อย session ใช้ต่อหลัง logout ผู้โจมตีอาจยึดบัญชี ใช้ข้อมูลของผู้อื่น หรือเรียกฟังก์ชันที่ควรจำกัดเฉพาะบทบาทได้.

สรุปความเสี่ยงแบบย่อ
สิ่งที่อาจผิดพลาดแอปพลิเคชันหรือระบบ Backend ยอมรับกระบวนการยืนยันตัวตน การจัดการ Session หรือการกำหนดสิทธิ์ที่มีช่องโหว่
ผลกระทบต่อธุรกิจผู้ใช้บนอุปกรณ์หรือผู้โจมตีจากระยะไกลอาจเข้าถึงบัญชี ฟีเจอร์ หรือชุดข้อมูลของผู้อื่นโดยมิชอบ
จุดควบคุมแรกที่ควรตรวจตรวจสอบสิทธิ์คำขอบนระบบ Backend เสมอ ไม่พึ่งพาการตรวจฝั่งแอปเพียงอย่างเดียว
M3 attack path against a victim application and its mitigating control

ภาพเปรียบเทียบเส้นทางที่ไม่ปลอดภัยกับจุดควบคุมที่ตัดเส้นทางนั้น กดภาพเพื่อดูขนาดเต็ม.

ผลกระทบที่ควรพิจารณา

ผู้ใช้บนอุปกรณ์หรือผู้โจมตีจากระยะไกลอาจเข้าถึงบัญชี ฟีเจอร์ หรือชุดข้อมูลของผู้อื่นโดยมิชอบ

แนวทางลดความเสี่ยง

  • ตรวจสอบสิทธิ์คำขอบนระบบ Backend เสมอ ไม่พึ่งพาการตรวจฝั่งแอปเพียงอย่างเดียว
  • ใช้ Session ที่ปลอดภัยและระบบ MFA ตามระดับความเสี่ยง
  • ทดสอบการเข้าถึงจาก Deep Link, Component ของแอป และออบเจ็กต์บน Backend
ตัวอย่าง Android ด้วย Kotlin

ตัวอย่างที่มีช่องโหว่

import android.content.Intent
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity

class RedirectActivity : AppCompatActivity() {
    fun openRedirect(intent: Intent) {
        val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
        startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(rawTarget)))
    }
}

ตัวอย่างที่แก้ไขแล้ว

import android.content.Intent
import android.net.Uri
import androidx.browser.customtabs.CustomTabsIntent
import androidx.appcompat.app.AppCompatActivity

class RedirectActivity : AppCompatActivity() {
    private val allowedHosts = setOf("app.example.com")

    fun openRedirect(intent: Intent) {
        val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
        val target = Uri.parse(rawTarget)
        if (target.scheme != "https" || target.host !in allowedHosts) return
        CustomTabsIntent.Builder().build().launchUrl(this, target)
    }
}
ตัวอย่าง iOS ด้วย Swift

ตัวอย่างที่มีช่องโหว่

import UIKit

final class RedirectViewController: UIViewController {
    func openRedirect(rawTarget: String) {
        guard let target = URL(string: rawTarget) else { return }
        UIApplication.shared.open(target)
    }
}

ตัวอย่างที่แก้ไขแล้ว

import SafariServices
import UIKit

final class RedirectViewController: UIViewController {
    private let allowedHosts: Set<String> = ["app.example.com"]

    func openRedirect(rawTarget: String) {
        guard let target = URL(string: rawTarget),
              target.scheme == "https",
              let host = target.host,
              allowedHosts.contains(host) else { return }

        let browser = SFSafariViewController(url: target)
        present(browser, animated: true)
    }
}

M4

Insufficient Input/Output Validation

Insufficient Input/Output Validation คือแอปเชื่อ deep link, QR, intent, file, response จาก server หรือข้อมูลที่แสดงผลโดยไม่ตรวจรูปแบบ แหล่งที่มา และขอบเขตก่อนใช้งาน ข้อมูลที่ดัดแปลงจึงอาจพาแอปเปิดปลายทางที่ไม่ปลอดภัย, ทำงานผิด flow หรือส่งข้อมูลกลับออกไปผิดที่.

สรุปความเสี่ยงแบบย่อ
สิ่งที่อาจผิดพลาดข้อมูลที่ส่งข้ามระหว่างแอปพลิเคชัน อุปกรณ์ ระบบ Backend เบราว์เซอร์ หรือบริการภายนอก ถูกเชื่อถือโดยไม่มีการตรวจสอบรูปแบบและความถูกต้องอย่างเพียงพอ
ผลกระทบต่อธุรกิจเนื้อหาที่เป็นอันตรายอาจเปลี่ยนแปลงขั้นตอนการทำงานของแอป แสดงผลอย่างไม่ปลอดภัย หรือทำให้ระบบ Backend ดำเนินการที่ไม่ปลอดภัย
จุดควบคุมแรกที่ควรตรวจตรวจสอบข้อมูลภายนอกทั้งหมด ณ ทุกจุดเชื่อมต่อความเชื่อถือ
M4 attack path against a victim application and its mitigating control

ภาพเปรียบเทียบเส้นทางที่ไม่ปลอดภัยกับจุดควบคุมที่ตัดเส้นทางนั้น กดภาพเพื่อดูขนาดเต็ม.

ผลกระทบที่ควรพิจารณา

เนื้อหาที่เป็นอันตรายอาจเปลี่ยนแปลงขั้นตอนการทำงานของแอป แสดงผลอย่างไม่ปลอดภัย หรือทำให้ระบบ Backend ดำเนินการที่ไม่ปลอดภัย

แนวทางลดความเสี่ยง

  • ตรวจสอบข้อมูลภายนอกทั้งหมด ณ ทุกจุดเชื่อมต่อความเชื่อถือ
  • Encode ข้อมูลออกให้เหมาะสมกับบริบทของการแสดงผล
  • ใช้ Schema ชนิดข้อมูลที่ชัดเจนและปฏิเสธ Field ที่ไม่คาดคิด
ตัวอย่าง Android ด้วย Kotlin

ตัวอย่างที่มีช่องโหว่

import android.content.Intent
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity

class RedirectActivity : AppCompatActivity() {
    fun openRedirect(intent: Intent) {
        val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
        startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(rawTarget)))
    }
}

ตัวอย่างที่แก้ไขแล้ว

import android.content.Intent
import android.net.Uri
import androidx.browser.customtabs.CustomTabsIntent
import androidx.appcompat.app.AppCompatActivity

class RedirectActivity : AppCompatActivity() {
    private val allowedHosts = setOf("app.example.com")

    fun openRedirect(intent: Intent) {
        val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
        val target = Uri.parse(rawTarget)
        if (target.scheme != "https" || target.host !in allowedHosts) return
        CustomTabsIntent.Builder().build().launchUrl(this, target)
    }
}
ตัวอย่าง iOS ด้วย Swift

ตัวอย่างที่มีช่องโหว่

import UIKit

final class RedirectViewController: UIViewController {
    func openRedirect(rawTarget: String) {
        guard let target = URL(string: rawTarget) else { return }
        UIApplication.shared.open(target)
    }
}

ตัวอย่างที่แก้ไขแล้ว

import SafariServices
import UIKit

final class RedirectViewController: UIViewController {
    private let allowedHosts: Set<String> = ["app.example.com"]

    func openRedirect(rawTarget: String) {
        guard let target = URL(string: rawTarget),
              target.scheme == "https",
              let host = target.host,
              allowedHosts.contains(host) else { return }

        let browser = SFSafariViewController(url: target)
        present(browser, animated: true)
    }
}

M5

Insecure Communication

Insecure Communication คือข้อมูลระหว่างแอปกับบริการไม่ได้รับการปกป้องจากการดักฟังหรือแก้ไขอย่างพอเพียง เช่น ยอมรับ certificate ที่ไม่น่าเชื่อถือ, ใช้ HTTP, ตรวจ TLS ไม่ครบ หรือส่งข้อมูลลับผ่านช่องทางอื่นที่ไม่ปลอดภัย ผู้โจมตีบนเครือข่ายเดียวกันจึงอาจอ่านข้อความหรือแทรกข้อมูลได้.

สรุปความเสี่ยงแบบย่อ
สิ่งที่อาจผิดพลาดการรับส่งข้อมูลผ่านเครือข่าย การตรวจสอบใบรับรอง หรือการเลือกใช้ช่องทางสื่อสาร ไม่ได้ปกป้องข้อมูลระหว่างการรับส่งอย่างปลอดภัย
ผลกระทบต่อธุรกิจผู้โจมตีบนเครือข่ายที่ไม่ปลอดภัยอาจดักดู แก้ไข หรือเปลี่ยนทิศทางการรับส่งข้อมูลสำคัญได้
จุดควบคุมแรกที่ควรตรวจบังคับใช้โปรโตคอล TLS เวอร์ชันปัจจุบันสำหรับการเชื่อมต่อสำคัญ
M5 attack path against a victim application and its mitigating control

ภาพเปรียบเทียบเส้นทางที่ไม่ปลอดภัยกับจุดควบคุมที่ตัดเส้นทางนั้น กดภาพเพื่อดูขนาดเต็ม.

ผลกระทบที่ควรพิจารณา

ผู้โจมตีบนเครือข่ายที่ไม่ปลอดภัยอาจดักดู แก้ไข หรือเปลี่ยนทิศทางการรับส่งข้อมูลสำคัญได้

แนวทางลดความเสี่ยง

  • บังคับใช้โปรโตคอล TLS เวอร์ชันปัจจุบันสำหรับการเชื่อมต่อสำคัญ
  • ตรวจสอบใบรับรองดิจิทัลและหลีกเลี่ยงพฤติกรรมที่ยอมรับทุกใบรับรอง
  • ลดการส่งข้อมูลสำคัญในคำขอและข้อมูลวินิจฉัย
ตัวอย่าง Android ด้วย Kotlin

ตัวอย่างที่มีช่องโหว่

import android.content.Intent
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity

class RedirectActivity : AppCompatActivity() {
    fun openRedirect(intent: Intent) {
        val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
        startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(rawTarget)))
    }
}

ตัวอย่างที่แก้ไขแล้ว

import android.content.Intent
import android.net.Uri
import androidx.browser.customtabs.CustomTabsIntent
import androidx.appcompat.app.AppCompatActivity

class RedirectActivity : AppCompatActivity() {
    private val allowedHosts = setOf("app.example.com")

    fun openRedirect(intent: Intent) {
        val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
        val target = Uri.parse(rawTarget)
        if (target.scheme != "https" || target.host !in allowedHosts) return
        CustomTabsIntent.Builder().build().launchUrl(this, target)
    }
}
ตัวอย่าง iOS ด้วย Swift

ตัวอย่างที่มีช่องโหว่

import UIKit

final class RedirectViewController: UIViewController {
    func openRedirect(rawTarget: String) {
        guard let target = URL(string: rawTarget) else { return }
        UIApplication.shared.open(target)
    }
}

ตัวอย่างที่แก้ไขแล้ว

import SafariServices
import UIKit

final class RedirectViewController: UIViewController {
    private let allowedHosts: Set<String> = ["app.example.com"]

    func openRedirect(rawTarget: String) {
        guard let target = URL(string: rawTarget),
              target.scheme == "https",
              let host = target.host,
              allowedHosts.contains(host) else { return }

        let browser = SFSafariViewController(url: target)
        present(browser, animated: true)
    }
}

M6

Inadequate Privacy Controls

Inadequate Privacy Controls คือแอปเก็บ ใช้ เปิดเผย หรือเก็บรักษาข้อมูลส่วนบุคคลเกินวัตถุประสงค์หรือโดยไม่มีการควบคุมที่เข้าใจได้ เช่น ขอ permission เกินจำเป็น, ส่ง analytics ที่ระบุตัวบุคคลได้ หรือไม่มีทางให้ผู้ใช้จัดการ consent ความเสี่ยงครอบคลุมทั้งผู้ใช้ ความเชื่อมั่น และข้อกำหนดด้านข้อมูลส่วนบุคคล.

สรุปความเสี่ยงแบบย่อ
สิ่งที่อาจผิดพลาดแอปพลิเคชันรวบรวม แบ่งปัน จัดเก็บ หรือเปิดเผยข้อมูลส่วนบุคคลเกินกว่าวัตถุประสงค์ที่ได้แจ้งไว้และเกินความจำเป็น
ผลกระทบต่อธุรกิจผู้ใช้อาจสูญเสียการควบคุมข้อมูลส่วนบุคคลผ่านระบบ Telemetry, Permission, ระบบวิเคราะห์การใช้งาน หรือการแบ่งปันข้อมูลกับบุคคลที่สาม
จุดควบคุมแรกที่ควรตรวจทำแผนที่การจัดเก็บข้อมูลส่วนบุคคลและรายชื่อผู้รับข้อมูล
M6 attack path against a victim application and its mitigating control

ภาพเปรียบเทียบเส้นทางที่ไม่ปลอดภัยกับจุดควบคุมที่ตัดเส้นทางนั้น กดภาพเพื่อดูขนาดเต็ม.

ผลกระทบที่ควรพิจารณา

ผู้ใช้อาจสูญเสียการควบคุมข้อมูลส่วนบุคคลผ่านระบบ Telemetry, Permission, ระบบวิเคราะห์การใช้งาน หรือการแบ่งปันข้อมูลกับบุคคลที่สาม

แนวทางลดความเสี่ยง

  • ทำแผนที่การจัดเก็บข้อมูลส่วนบุคคลและรายชื่อผู้รับข้อมูล
  • ขอ Permission เฉพาะที่จำเป็นและในเวลาที่เหมาะสม
  • ใช้มาตรการควบคุมระยะเวลาจัดเก็บ ความยินยอม และการลบข้อมูล
ตัวอย่าง Android ด้วย Kotlin

ตัวอย่างที่มีช่องโหว่

import android.content.Intent
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity

class RedirectActivity : AppCompatActivity() {
    fun openRedirect(intent: Intent) {
        val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
        startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(rawTarget)))
    }
}

ตัวอย่างที่แก้ไขแล้ว

import android.content.Intent
import android.net.Uri
import androidx.browser.customtabs.CustomTabsIntent
import androidx.appcompat.app.AppCompatActivity

class RedirectActivity : AppCompatActivity() {
    private val allowedHosts = setOf("app.example.com")

    fun openRedirect(intent: Intent) {
        val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
        val target = Uri.parse(rawTarget)
        if (target.scheme != "https" || target.host !in allowedHosts) return
        CustomTabsIntent.Builder().build().launchUrl(this, target)
    }
}
ตัวอย่าง iOS ด้วย Swift

ตัวอย่างที่มีช่องโหว่

import UIKit

final class RedirectViewController: UIViewController {
    func openRedirect(rawTarget: String) {
        guard let target = URL(string: rawTarget) else { return }
        UIApplication.shared.open(target)
    }
}

ตัวอย่างที่แก้ไขแล้ว

import SafariServices
import UIKit

final class RedirectViewController: UIViewController {
    private let allowedHosts: Set<String> = ["app.example.com"]

    func openRedirect(rawTarget: String) {
        guard let target = URL(string: rawTarget),
              target.scheme == "https",
              let host = target.host,
              allowedHosts.contains(host) else { return }

        let browser = SFSafariViewController(url: target)
        present(browser, animated: true)
    }
}

M7

Insufficient Binary Protections

Insufficient Binary Protections คือ binary ของแอปเปิดให้ถูกแกะ วิเคราะห์ ดัดแปลง หรือ repack ได้ง่ายจนกลไกป้องกันที่อยู่ฝั่ง client ถูกข้ามได้ เช่น ไม่มี tamper detection หรือไม่ตรวจว่าแอปทำงานบนเครื่องที่ถูกดัดแปลง การป้องกันนี้ไม่แทน server-side control แต่ช่วยเพิ่มต้นทุนและสัญญาณตรวจจับการโจมตี.

สรุปความเสี่ยงแบบย่อ
สิ่งที่อาจผิดพลาดไฟล์ Binary ของแอปพลิเคชันไม่มีกลไกป้องกันการแกะโค้ด การดัดแปลงแก้ไข หรือการบรรจุใหม่ที่เหมาะสมตาม Threat Model
ผลกระทบต่อธุรกิจแอปพลิเคชันฝั่ง Client ที่ถูกแก้ไขอาจปลดมาตรการความปลอดภัย เปิดเผยตรรกะภายใน หรือปลอมเป็นแอปพลิเคชันจริงเพื่อหลอกลวงผู้ใช้
จุดควบคุมแรกที่ควรตรวจเก็บการตัดสินใจด้านความเชื่อถือและ Secret ไว้บนระบบ Backend
M7 attack path against a victim application and its mitigating control

ภาพเปรียบเทียบเส้นทางที่ไม่ปลอดภัยกับจุดควบคุมที่ตัดเส้นทางนั้น กดภาพเพื่อดูขนาดเต็ม.

ผลกระทบที่ควรพิจารณา

แอปพลิเคชันฝั่ง Client ที่ถูกแก้ไขอาจปลดมาตรการความปลอดภัย เปิดเผยตรรกะภายใน หรือปลอมเป็นแอปพลิเคชันจริงเพื่อหลอกลวงผู้ใช้

แนวทางลดความเสี่ยง

  • เก็บการตัดสินใจด้านความเชื่อถือและ Secret ไว้บนระบบ Backend
  • ใช้การลงนามดิจิทัลของแพลตฟอร์มและสัญญาณตรวจเช็กความสมบูรณ์
  • ตรวจจับการแก้ไขแอปพลิเคชันและวางแผนการตอบสนองที่ปลอดภัย
ตัวอย่าง Android ด้วย Kotlin

ตัวอย่างที่มีช่องโหว่

import android.content.Intent
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity

class RedirectActivity : AppCompatActivity() {
    fun openRedirect(intent: Intent) {
        val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
        startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(rawTarget)))
    }
}

ตัวอย่างที่แก้ไขแล้ว

import android.content.Intent
import android.net.Uri
import androidx.browser.customtabs.CustomTabsIntent
import androidx.appcompat.app.AppCompatActivity

class RedirectActivity : AppCompatActivity() {
    private val allowedHosts = setOf("app.example.com")

    fun openRedirect(intent: Intent) {
        val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
        val target = Uri.parse(rawTarget)
        if (target.scheme != "https" || target.host !in allowedHosts) return
        CustomTabsIntent.Builder().build().launchUrl(this, target)
    }
}
ตัวอย่าง iOS ด้วย Swift

ตัวอย่างที่มีช่องโหว่

import UIKit

final class RedirectViewController: UIViewController {
    func openRedirect(rawTarget: String) {
        guard let target = URL(string: rawTarget) else { return }
        UIApplication.shared.open(target)
    }
}

ตัวอย่างที่แก้ไขแล้ว

import SafariServices
import UIKit

final class RedirectViewController: UIViewController {
    private let allowedHosts: Set<String> = ["app.example.com"]

    func openRedirect(rawTarget: String) {
        guard let target = URL(string: rawTarget),
              target.scheme == "https",
              let host = target.host,
              allowedHosts.contains(host) else { return }

        let browser = SFSafariViewController(url: target)
        present(browser, animated: true)
    }
}

M8

Security Misconfiguration

Security Misconfiguration บนมือถือคือการเปิดใช้ capability, component, debug setting, permission หรือ network policy เกินความจำเป็น เช่น exported activity ที่ไม่ควรเปิด, backup ที่นำข้อมูลออกได้ หรือ debug endpoint ที่ยังอยู่ใน release แอปอาจถูกเรียกจากแอปอื่นหรือเปิดข้อมูลในลักษณะที่หน้าจอปกติไม่เคยอนุญาต.

สรุปความเสี่ยงแบบย่อ
สิ่งที่อาจผิดพลาดการกำหนดค่าใน Build Variant, การตั้งค่าแพลตฟอร์ม, Component ที่เปิดเผยภายนอก หรือการตั้งค่า Backend ทำให้เกิดช่องโหว่ที่ไม่ตั้งใจ
ผลกระทบต่อธุรกิจฟีเจอร์สำหรับ Debug, Component ที่เปิดเผยภายนอก, การเปิดให้สำรองข้อมูลได้ หรือการตั้งค่าสื่อสารที่อ่อนแอ อาจถูกเข้าถึงได้ในเวอร์ชันใช้งานจริง
จุดควบคุมแรกที่ควรตรวจทบทวน Manifest ของเวอร์ชัน Release และการตั้งค่าแพลตฟอร์ม
M8 attack path against a victim application and its mitigating control

ภาพเปรียบเทียบเส้นทางที่ไม่ปลอดภัยกับจุดควบคุมที่ตัดเส้นทางนั้น กดภาพเพื่อดูขนาดเต็ม.

ผลกระทบที่ควรพิจารณา

ฟีเจอร์สำหรับ Debug, Component ที่เปิดเผยภายนอก, การเปิดให้สำรองข้อมูลได้ หรือการตั้งค่าสื่อสารที่อ่อนแอ อาจถูกเข้าถึงได้ในเวอร์ชันใช้งานจริง

แนวทางลดความเสี่ยง

  • ทบทวน Manifest ของเวอร์ชัน Release และการตั้งค่าแพลตฟอร์ม
  • แยกการตั้งค่าระหว่าง Debug และ Production อย่างเด็ดขาด
  • ใช้ระบบอัตโนมัติในการตรวจเช็กการกำหนดค่าในขั้นตอน CI/CD
ตัวอย่าง Android ด้วย Kotlin

ตัวอย่างที่มีช่องโหว่

import android.content.Intent
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity

class RedirectActivity : AppCompatActivity() {
    fun openRedirect(intent: Intent) {
        val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
        startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(rawTarget)))
    }
}

ตัวอย่างที่แก้ไขแล้ว

import android.content.Intent
import android.net.Uri
import androidx.browser.customtabs.CustomTabsIntent
import androidx.appcompat.app.AppCompatActivity

class RedirectActivity : AppCompatActivity() {
    private val allowedHosts = setOf("app.example.com")

    fun openRedirect(intent: Intent) {
        val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
        val target = Uri.parse(rawTarget)
        if (target.scheme != "https" || target.host !in allowedHosts) return
        CustomTabsIntent.Builder().build().launchUrl(this, target)
    }
}
ตัวอย่าง iOS ด้วย Swift

ตัวอย่างที่มีช่องโหว่

import UIKit

final class RedirectViewController: UIViewController {
    func openRedirect(rawTarget: String) {
        guard let target = URL(string: rawTarget) else { return }
        UIApplication.shared.open(target)
    }
}

ตัวอย่างที่แก้ไขแล้ว

import SafariServices
import UIKit

final class RedirectViewController: UIViewController {
    private let allowedHosts: Set<String> = ["app.example.com"]

    func openRedirect(rawTarget: String) {
        guard let target = URL(string: rawTarget),
              target.scheme == "https",
              let host = target.host,
              allowedHosts.contains(host) else { return }

        let browser = SFSafariViewController(url: target)
        present(browser, animated: true)
    }
}

M9

Insecure Data Storage

Insecure Data Storage คือแอปบันทึกข้อมูลสำคัญไว้ในเครื่องโดยไม่มีการคุ้มครองที่เหมาะสม เช่น shared preferences, cache, log, screenshot, clipboard หรือไฟล์ backup ที่อ่านได้ ข้อมูลอาจหลุดผ่านเครื่องที่ root/jailbreak, backup, malware หรือผู้ที่เข้าถึงอุปกรณ์ชั่วคราว.

สรุปความเสี่ยงแบบย่อ
สิ่งที่อาจผิดพลาดข้อมูลสำคัญถูกจัดเก็บหรือบันทึก Cache ไว้ในอุปกรณ์ โดยไม่มีการคุ้มครองจนแอปอื่น ผู้ใช้เครื่อง ระบบสำรองข้อมูล หรือกระบวนการตรวจพิสูจน์สามารถเข้าถึงได้
ผลกระทบต่อธุรกิจหากอุปกรณ์สูญหาย ถูก Root หรือ Jailbreak มีผู้ใช้เครื่องร่วมกัน หรือถูกสำรองข้อมูล อาจทำให้ข้อมูลบัญชีผู้ใช้ ข้อมูลธุรกิจ หรือข้อมูลส่วนบุคคลหลุดรอดได้
จุดควบคุมแรกที่ควรตรวจลดการจัดเก็บข้อมูลสำคัญไว้ในอุปกรณ์และลดระยะเวลาของ Cache
M9 attack path against a victim application and its mitigating control

ภาพเปรียบเทียบเส้นทางที่ไม่ปลอดภัยกับจุดควบคุมที่ตัดเส้นทางนั้น กดภาพเพื่อดูขนาดเต็ม.

ผลกระทบที่ควรพิจารณา

หากอุปกรณ์สูญหาย ถูก Root หรือ Jailbreak มีผู้ใช้เครื่องร่วมกัน หรือถูกสำรองข้อมูล อาจทำให้ข้อมูลบัญชีผู้ใช้ ข้อมูลธุรกิจ หรือข้อมูลส่วนบุคคลหลุดรอดได้

แนวทางลดความเสี่ยง

  • ลดการจัดเก็บข้อมูลสำคัญไว้ในอุปกรณ์และลดระยะเวลาของ Cache
  • ใช้ระบบจัดเก็บข้อมูลที่ได้รับการคุ้มครองจากแพลตฟอร์ม (เช่น Key Store / Keychain) สำหรับ Secret
  • ตรวจสอบ Log, Screenshot, ไฟล์สำรองข้อมูล และพื้นที่จัดเก็บข้อมูลร่วม
ตัวอย่าง Android ด้วย Kotlin

ตัวอย่างที่มีช่องโหว่

import android.content.Intent
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity

class RedirectActivity : AppCompatActivity() {
    fun openRedirect(intent: Intent) {
        val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
        startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(rawTarget)))
    }
}

ตัวอย่างที่แก้ไขแล้ว

import android.content.Intent
import android.net.Uri
import androidx.browser.customtabs.CustomTabsIntent
import androidx.appcompat.app.AppCompatActivity

class RedirectActivity : AppCompatActivity() {
    private val allowedHosts = setOf("app.example.com")

    fun openRedirect(intent: Intent) {
        val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
        val target = Uri.parse(rawTarget)
        if (target.scheme != "https" || target.host !in allowedHosts) return
        CustomTabsIntent.Builder().build().launchUrl(this, target)
    }
}
ตัวอย่าง iOS ด้วย Swift

ตัวอย่างที่มีช่องโหว่

import UIKit

final class RedirectViewController: UIViewController {
    func openRedirect(rawTarget: String) {
        guard let target = URL(string: rawTarget) else { return }
        UIApplication.shared.open(target)
    }
}

ตัวอย่างที่แก้ไขแล้ว

import SafariServices
import UIKit

final class RedirectViewController: UIViewController {
    private let allowedHosts: Set<String> = ["app.example.com"]

    func openRedirect(rawTarget: String) {
        guard let target = URL(string: rawTarget),
              target.scheme == "https",
              let host = target.host,
              allowedHosts.contains(host) else { return }

        let browser = SFSafariViewController(url: target)
        present(browser, animated: true)
    }
}

M10

Insufficient Cryptography

Insufficient Cryptography คือแอปเลือกหรือใช้อัลกอริทึม, key, random number หรือ library ผิดวิธี แม้จะมีคำว่า encryption อยู่ในระบบก็ตาม เช่น key เดาง่าย, ใช้โหมดเข้ารหัสไม่เหมาะสม หรือเก็บ key แบบอ่านได้ ผู้โจมตีที่ได้ข้อมูลหรือ key อาจถอดรหัสหรือปลอมข้อมูลได้.

สรุปความเสี่ยงแบบย่อ
สิ่งที่อาจผิดพลาดการเลือกใช้อัลกอริทึมการเข้ารหัส โหมดการทำงาน ค่าสุ่ม กุญแจเข้ารหัส หรือกลไกการเข้ารหัสที่ไม่เหมาะสม ทำให้ไม่สามารถปกป้องข้อมูลในแอปมือถือได้อย่างปลอดภัย
ผลกระทบต่อธุรกิจข้อมูลที่ปกป้องด้วยอัลกอริทึมการเข้ารหัสที่อ่อนแอ หรือใช้กลไกเข้ารหัสที่ไม่ถูกต้อง อาจถูกถอดรหัส กู้คืน หรือแก้ไขดัดแปลงโดยผู้ไม่หวังดีได้
จุดควบคุมแรกที่ควรตรวจใช้ API การเข้ารหัสมาตรฐานของแพลตฟอร์มและผ่านการรับรอง
M10 attack path against a victim application and its mitigating control

ภาพเปรียบเทียบเส้นทางที่ไม่ปลอดภัยกับจุดควบคุมที่ตัดเส้นทางนั้น กดภาพเพื่อดูขนาดเต็ม.

ผลกระทบที่ควรพิจารณา

ข้อมูลที่ปกป้องด้วยอัลกอริทึมการเข้ารหัสที่อ่อนแอ หรือใช้กลไกเข้ารหัสที่ไม่ถูกต้อง อาจถูกถอดรหัส กู้คืน หรือแก้ไขดัดแปลงโดยผู้ไม่หวังดีได้

แนวทางลดความเสี่ยง

  • ใช้ API การเข้ารหัสมาตรฐานของแพลตฟอร์มและผ่านการรับรอง
  • สร้างและจัดเก็บกุญแจเข้ารหัสด้วยกลไกการปกป้องของแพลตฟอร์ม
  • หลีกเลี่ยงการเขียนอัลกอริทึมเข้ารหัสขึ้นเองและอัลกอริทึมที่ล้าสมัย
ตัวอย่าง Android ด้วย Kotlin

ตัวอย่างที่มีช่องโหว่

import android.content.Intent
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity

class RedirectActivity : AppCompatActivity() {
    fun openRedirect(intent: Intent) {
        val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
        startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(rawTarget)))
    }
}

ตัวอย่างที่แก้ไขแล้ว

import android.content.Intent
import android.net.Uri
import androidx.browser.customtabs.CustomTabsIntent
import androidx.appcompat.app.AppCompatActivity

class RedirectActivity : AppCompatActivity() {
    private val allowedHosts = setOf("app.example.com")

    fun openRedirect(intent: Intent) {
        val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
        val target = Uri.parse(rawTarget)
        if (target.scheme != "https" || target.host !in allowedHosts) return
        CustomTabsIntent.Builder().build().launchUrl(this, target)
    }
}
ตัวอย่าง iOS ด้วย Swift

ตัวอย่างที่มีช่องโหว่

import UIKit

final class RedirectViewController: UIViewController {
    func openRedirect(rawTarget: String) {
        guard let target = URL(string: rawTarget) else { return }
        UIApplication.shared.open(target)
    }
}

ตัวอย่างที่แก้ไขแล้ว

import SafariServices
import UIKit

final class RedirectViewController: UIViewController {
    private let allowedHosts: Set<String> = ["app.example.com"]

    func openRedirect(rawTarget: String) {
        guard let target = URL(string: rawTarget),
              target.scheme == "https",
              let host = target.host,
              allowedHosts.contains(host) else { return }

        let browser = SFSafariViewController(url: target)
        present(browser, animated: true)
    }
}

เครื่องมือประเมินความพร้อม

คลิกเลือกรายการที่องค์กรของท่านได้ดำเนินการแล้ว เพื่อคำนวณระดับความพร้อมเบื้องต้น

0%

เอกสารอ้างอิง OWASP

เปิดเอกสาร OWASP ฉบับทางการ