Broadcast Receiver ที่ไม่ปลอดภัย
จัดทุกอย่างให้เป็นระเบียบอยู่เสมอด้วยคอลเล็กชัน
บันทึกและจัดหมวดหมู่เนื้อหาตามค่ากำหนดของคุณ
หมวดหมู่ OWASP: MASVS-PLATFORM: การโต้ตอบกับแพลตฟอร์ม
ภาพรวม
การติดตั้งใช้งานตัวรับการออกอากาศอย่างไม่ถูกต้องอาจทำให้ผู้โจมตีส่งความตั้งใจที่เป็นอันตรายเพื่อทำให้แอปพลิเคชันที่มีช่องโหว่ดำเนินการซึ่งไม่ได้มีไว้สำหรับผู้เรียกภายนอก
โดยทั่วไปแล้วช่องโหว่หมายถึงกรณีที่มีการส่งออกตัวรับการออกอากาศโดยไม่ตั้งใจ โดยการตั้งค่า android:exported="true"
ใน AndroidManifest หรือสร้างตัวรับการออกอากาศแบบเป็นโปรแกรม ซึ่งทำให้ตัวรับเป็นแบบสาธารณะโดยค่าเริ่มต้น หากตัวรับไม่มีตัวกรอง Intent ค่าเริ่มต้นจะเป็น "false"
แต่หากตัวรับมีตัวกรอง Intent อย่างน้อย 1 รายการ ค่าเริ่มต้นของ android:exported จะเป็น "true"
ผู้รับสัญญาณออกอากาศที่ส่งออกโดยเจตนาโดยไม่มีการควบคุมการเข้าถึงที่เหมาะสมอาจถูกละเมิดได้หากนักพัฒนาแอปไม่ได้ตั้งใจให้แอปพลิเคชันทั้งหมดเรียกใช้
ผลกระทบ
ผู้โจมตีอาจใช้ตัวรับการออกอากาศที่ติดตั้งใช้งานอย่างไม่ปลอดภัยเพื่อรับสิทธิ์เข้าถึงที่ไม่ได้รับอนุญาตเพื่อดําเนินการในแอปพลิเคชันซึ่งนักพัฒนาแอปไม่ได้ตั้งใจที่จะเปิดเผยต่อบุคคลที่สาม
การลดปัญหา
หลีกเลี่ยงปัญหาโดยสิ้นเชิง
หากต้องการแก้ไขปัญหานี้อย่างสมบูรณ์ ให้ตั้งค่า exported
เป็น false
โดยทำดังนี้
<receiver android:name=".MyReceiver" android:exported="false">
<intent-filter>
<action android:name="com.example.myapp.MY_ACTION" />
</intent-filter>
</receiver>
ใช้การเรียกและการรับสายกลับ
ในกรณีที่คุณใช้ Broadcast Receiver เพื่อวัตถุประสงค์ภายในแอป (เช่น การแจ้งเตือนเมื่อเหตุการณ์เสร็จสมบูรณ์) คุณสามารถจัดโครงสร้างโค้ดใหม่เพื่อส่งการเรียกกลับที่จะทริกเกอร์หลังจากเหตุการณ์เสร็จสมบูรณ์แทน
Listener เหตุการณ์เสร็จสมบูรณ์
Kotlin
interface EventCompletionListener {
fun onEventComplete(data: String)
}
Java
public interface EventCompletionListener {
public void onEventComplete(String data);
}
งานที่มีความปลอดภัย
Kotlin
class SecureTask(private val listener: EventCompletionListener?) {
fun executeTask() {
// Do some work...
// Notify that the event is complete
listener?.onEventComplete("Some secure data")
}
}
Java
public class SecureTask {
final private EventCompletionListener listener;
public SecureTask(EventCompletionListener listener) {
this.listener = listener;
}
public void executeTask() {
// Do some work...
// Notify that the event is complete
if (listener != null) {
listener.onEventComplete("Some secure data");
}
}
}
กิจกรรมหลัก
Kotlin
class MainActivity : AppCompatActivity(), EventCompletionListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val secureTask = SecureTask(this)
secureTask.executeTask()
}
override fun onEventComplete(data: String) {
// Handle event completion securely
// ...
}
}
Java
public class MainActivity extends AppCompatActivity implements EventCompletionListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SecureTask secureTask = new SecureTask(this);
secureTask.executeTask();
}
@Override
public void onEventComplete(String data) {
// Handle event completion securely
// ...
}
}
รักษาความปลอดภัยให้กับ Broadcast Receiver ด้วยสิทธิ์
ลงทะเบียนผู้รับแบบไดนามิกสําหรับการออกอากาศที่ได้รับการคุ้มครองเท่านั้น (การออกอากาศที่มีเพียงแอปพลิเคชันระดับระบบเท่านั้นที่ส่งได้) หรือมีสิทธิ์ระดับลายเซ็นที่ประกาศด้วยตนเอง
แหล่งข้อมูล
ตัวอย่างเนื้อหาและโค้ดในหน้าเว็บนี้ขึ้นอยู่กับใบอนุญาตที่อธิบายไว้ในใบอนุญาตการใช้เนื้อหา Java และ OpenJDK เป็นเครื่องหมายการค้าหรือเครื่องหมายการค้าจดทะเบียนของ Oracle และ/หรือบริษัทในเครือ
อัปเดตล่าสุด 2025-07-26 UTC
[[["เข้าใจง่าย","easyToUnderstand","thumb-up"],["แก้ปัญหาของฉันได้","solvedMyProblem","thumb-up"],["อื่นๆ","otherUp","thumb-up"]],[["ไม่มีข้อมูลที่ฉันต้องการ","missingTheInformationINeed","thumb-down"],["ซับซ้อนเกินไป/มีหลายขั้นตอนมากเกินไป","tooComplicatedTooManySteps","thumb-down"],["ล้าสมัย","outOfDate","thumb-down"],["ปัญหาเกี่ยวกับการแปล","translationIssue","thumb-down"],["ตัวอย่าง/ปัญหาเกี่ยวกับโค้ด","samplesCodeIssue","thumb-down"],["อื่นๆ","otherDown","thumb-down"]],["อัปเดตล่าสุด 2025-07-26 UTC"],[],[],null,["# Insecure broadcast receivers\n\n\u003cbr /\u003e\n\n**OWASP category:** [MASVS-PLATFORM: Platform Interaction](https://mas.owasp.org/MASVS/09-MASVS-PLATFORM)\n\nOverview\n--------\n\nImproperly implemented broadcast receivers can allow an attacker to send a\nmalicious intent to make the vulnerable application perform actions which are\nnot intended for external callers.\n\nThe vulnerability generally refers to instances where the broadcast receiver is\nunintentionally exported, either by setting [`android:exported=\"true\"`](/guide/topics/manifest/receiver-element#exported) in\nthe AndroidManifest or by creating a broadcast receiver programmatically which\nmakes the receiver public by default. If the receiver doesn't contain any intent\nfilters the default value is `\"false\"` but if the receiver contains at least one\nintent filter the default value of android:exported is `\"true\"`.\n\nIntentionally exported broadcast receivers without proper access control can be\nabused if the developer did not intend for it to be called by all applications.\n\nImpact\n------\n\nInsecurely implemented broadcast receivers can be abused by an attacker to gain\nunauthorized access to execute behavior in the application that the developer\ndid not mean to expose to third parties.\n\nMitigations\n-----------\n\n### Avoid the problem entirely\n\nTo resolve the dilemma entirely, set `exported` to `false`: \n\n \u003creceiver android:name=\".MyReceiver\" android:exported=\"false\"\u003e\n \u003cintent-filter\u003e\n \u003caction android:name=\"com.example.myapp.MY_ACTION\" /\u003e\n \u003c/intent-filter\u003e\n \u003c/receiver\u003e\n\n### Use calls and callbacks\n\nIn the case you used broadcast receivers for internal app purposes (ie. event\ncompletion notification), you can restructure your code to pass a callback that\nwould fire after event completion instead.\n\n###### Event completion listener\n\n### Kotlin\n\n interface EventCompletionListener {\n fun onEventComplete(data: String)\n }\n\n### Java\n\n public interface EventCompletionListener {\n public void onEventComplete(String data);\n }\n\n###### Secure task\n\n### Kotlin\n\n class SecureTask(private val listener: EventCompletionListener?) {\n fun executeTask() {\n // Do some work...\n\n // Notify that the event is complete\n listener?.onEventComplete(\"Some secure data\")\n }\n }\n\n### Java\n\n public class SecureTask {\n\n final private EventCompletionListener listener;\n\n public SecureTask(EventCompletionListener listener) {\n this.listener = listener;\n }\n\n public void executeTask() {\n // Do some work...\n\n // Notify that the event is complete\n if (listener != null) {\n listener.onEventComplete(\"Some secure data\");\n }\n }\n }\n\n###### Main activity\n\n### Kotlin\n\n class MainActivity : AppCompatActivity(), EventCompletionListener {\n override fun onCreate(savedInstanceState: Bundle?) {\n super.onCreate(savedInstanceState)\n setContentView(R.layout.activity_main)\n\n val secureTask = SecureTask(this)\n secureTask.executeTask()\n }\n\n override fun onEventComplete(data: String) {\n // Handle event completion securely\n // ...\n }\n }\n\n### Java\n\n public class MainActivity extends AppCompatActivity implements EventCompletionListener {\n\n @Override\n protected void onCreate(Bundle savedInstanceState) {\n super.onCreate(savedInstanceState);\n setContentView(R.layout.activity_main);\n\n SecureTask secureTask = new SecureTask(this);\n secureTask.executeTask();\n }\n\n @Override\n public void onEventComplete(String data) {\n // Handle event completion securely\n // ...\n }\n }\n\n### Secure broadcast receivers with permissions\n\nOnly register dynamic receivers for [protected broadcasts](/about/versions/12/reference/broadcast-intents-31) (broadcasts that\nonly system level applications can send) or with [self-declared signature level\npermissions](/guide/topics/manifest/permission-element#plevel).\n\nResources\n---------\n\n- [Exported Receiver Elements](/guide/topics/manifest/receiver-element#exported)\n- [Broadcast Receiver Permissions documentation](/guide/components/broadcasts#receiving-broadcasts-permissions)\n- [Protected Broadcast Intents](/about/versions/12/reference/broadcast-intents-31)"]]