บทนำ (Overview)
“Private Activities” คือ “Activities” ที่ไม่สามารถเรียกใช้งานจาก “Application” อื่น ๆ ภายในเครื่อง “Android” เดียวกัน ดังนั้นจะเป็นใช้งาน “Activities” ที่มีความปลอดภัยสูงสุด
ระดับของความเสี่ยงและมาตรการป้องกันของการใช้งาน “Activities” ให้ปลอดภัยนั้น ขึ้นอยู่กับการนำไปใช้งาน ซึ่งเราสามารถที่จะจำแนกได้เป็น 4 ประเภทดังต่อไปนี้
เงื่อนไข | ประเภท | อธิบาย |
---|---|---|
สำหรับทุก “Application” | Public Activity | เป็น “Activity” ที่สามารถถูกเรียกใช้งานจาก Application ที่ติดตั้งอยู่ในเครื่องเดียวกัน |
เฉพาะ “Application” อนุญาต | Partner Activity | เป็น “Activity” ที่สามารถเรียกใช้งานเฉพาะ “Application” อนุญาตเท่านั้น |
เฉพาะ “Application” ภายใน | In-house Activity | เป็น “Activity” ที่สามารถใช้งานเฉพาะ Application ที่พัฒนาเฉพาะองค์กรเดียวกันเท่านั้น |
ไม่อนุญาต “Application” อื่น | Private Activity | เป็น “Activity” ที่ไม่สามารถเรียกใช้งานจาก “Application” อื่น ๆ ที่ติดตั้งอยู่ในเครื่องกัน ซึ่งเป็น “Activity” ที่มีความปลอดภัยสูงสุด |
ความเสี่ยง (Risks)
ถึงแม้ว่าจะไม่สามารถเรียกใช้งานจาก “Application” อื่น ๆ ได้ แต่ก็ยังมีความเสี่ยงของการอ่าน “Intent” ที่ถูกเรียกใช้งานภายใน “Application” เดียวกัน ดังนั้นจำเป็นที่เราจะต้องตรวจสอบให้แน่ใจว่า ข้อมูลสำคัญ (Sensitive Information) ที่อยู่ใน “Intent” จะต้องไม่ถูกอ่านโดย “Application” ประสงค์ร้าย
การควบคุมความปลอดภัย (Control Activities)
ลำดับ | การควบคุม | สาเหตุ |
---|---|---|
ขั้นตอนการสร้าง “Activity” | ||
1 | ไม่ระบุใช้งาน “taskAffinity” | ตรวจสอบให้แน่ใจว่า “android:taskAffinity” จะต้องไม่มีอยู่ใน “AndroidManifest.xml” ไฟล์ หรือให้ตั้งค่าเป็นค่าตั้งต้น (Default) เพื่อเรียกใช้งาน “Package Name” เป็น “Root tasks” เพื่อป้องกันการอ่านข้อมูลสำคัญ (Sensitive information) ที่อยู่ ใน “Intent” จาก “Application” ประสงค์ร้าย |
2 | ไม่ระบุใช้งาน “launchMode” | ตรวจสอบให้แน่ใจว่า ค่า “launchMode” จะต้องไม่มีอยู่ใน “AndroidManifest.xml” ไฟล์ หรือให้ตั้งค่าเป็นค่าตั้งต้น (Default) ซึ่งก็คือ “Standard” เพื่อป้องกันการอ่านข้อมูลสำคัญ (Sensitive information) ที่อยู่ ใน “Intent” จาก “Application” ประสงค์ร้าย |
3 | ตั้งค่า “Export” ของ “Activity” สำคัญ เป็น “False” | ตรวจสอบให้แน่ใจว่า ค่า “Export” จะต้องไม่มีอยู่ใน “AndroidManifest.xml” ไฟล์ หรือให้ตั้งค่าเป็น “False” เพื่อป้องกันการเรียกใช้งาน Activity จากจาก “Application” ประสงค์ร้าย |
4 | จัดการข้อมูลนำเข้าอย่างปลอดภัย (Input validation) |
ตรวจสอบให้แน่ใจว่า ข้อมูลนำเข้ามีการตรวจสอบ (Input validation) อย่างปลอดภัยดังนี้
|
ขั้นตอนการใช้งาน “Activity” | ||
5 | จะต้องไม่ตั้งค่า “FLAG_ACTIVITY_NEW_TASK” สำหรับ Intent ที่เรียกใช้งาน “Activity” | ตรวจสอบให้แน่ใจว่า “FLAG_ACTIVITY_NEW_TASK” ไม่ได้ถูกตั้งค่าใน “setFlags()” หรือ “addFlags()” ตอนสร้าง “Intent” ซึ่งก็คือ startActivity() หรือ startActivityForResult() เพื่อป้องกันการเปลี่ยนแปลง “launch mode” ของ “Activity” ที่กำหนดอยู่ใน “AndroidManifest.xml” นำไปสู่อ่านข้อมูลสำคัญ (Sensitive information) ที่อยู่ ใน “Intent” จาก “Application” ประสงค์ร้าย |
6 | ใช้ “Explicit Intent” โดยระบุ “Classes” ไว้ เพื่อเรียกใช้งาน “Activity” ภายใน “Application” เดียวกัน |
ตรวจสอบให้แน่ใจว่า มีการใช้งาน “Explicit Intent” โดยระบุ “Class” ที่จะเรียกใช้ “Activity” เพื่อป้องกันการอ่านข้อมูลสำคัญ (Sensitive information) ที่อยู่ ใน “Intent” จาก “Application” ประสงค์ร้าย ตัวอย่างเช่น new Intent(this, PrivateActivity.class); |
การสอบทานโปรแกรม (Source code review)
ขั้นตอนที่ 1 การตั้งค่าใน AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.itselectlab.android.activity.privateactivity" > <application android:allowBackup="false" android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <!-- สำหรับ Private Activity --> <!-- Control Activity 1: android:taskAffinity จะต้องไม่มีอยู่ใน AndroidManifest.xml ไฟล์ --> <!-- Control Activity 2: android:taskAffinity จะต้องไม่มีอยู่ใน AndroidManifest.xml ไฟล์ หรือถ้ามีจะต้องตั้งเป็น android:launchMode="standard"--> <!-- Control Activity 3: ค่า Export จะต้องไม่มีอยู่ใน AndroidManifest.xml ไฟล์ หรือให้ตั้งค่าเป็น False จากตัวอย่างตั้งค่าเป็น False --> <activity android:name=".PrivateActivity" android:label="@string/app_name" android:exported="false" /> <!-- ส่วนของ Public Activity --> <activity android:name=".PrivateUserActivity" android:label="@string/app_name" android:exported="true" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
ขั้นตอนที่ 2 การเรียกใช้ “Private Activity” จาก “Private User Activity”
public class PrivateUserActivity extends Activity { private static final int REQUEST_CODE = 1; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.user_activity); } public void onUseActivityClick(View view) { // Control Activity 5: จะต้องไม่มีตั้งค่า FLAG_ACTIVITY_NEW_TASK flag // เช่น // Intent i = new Intent(context, ActivityName.class); // i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // context.startActivity(i); // Control Activity 6: มีการใช้งาน Explicit Intent โดยระบุ Class ที่จะเรียกใช้ Activity // จากตัวอย่างข้างล่างมีการกำหนด Class ที่จะเรียก คือ PrivateActivity.class Intent intent = new Intent(this, PrivateActivity.class); // Sensitive information สามารถส่งได้ผ่าน putExtra เนื่อง Activity ปลายทางอยู่ใน Application เดียวกัน intent.putExtra("PARAM", "Sensitive Information"); startActivityForResult(intent, REQUEST_CODE); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode != RESULT_OK) return; switch (requestCode) { case REQUEST_CODE: String result = data.getStringExtra("RESULT"); // Control Activity 4: ข้อมูลนำเข้ามีการตรวจสอบ (Input validation) อย่างปลอดภัย // จากตัวอย่างข้างล่าง // - ข้อมูลนำเข้าจะต้องถูกรูปแบบ (Valid Format) = กำหนดเป็น String // - ขนาดข้อมูลนำเข้า (Value range) Toast.makeText(this, String.format("Received result: ", result), Toast.LENGTH_LONG).show(); break; } } }
ขั้นตอนที่ 3 การใช้งาน “Private Activity”
public class PrivateActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.private_activity); // Control Activity 4: ข้อมูลนำเข้ามีการตรวจสอบ (Input validation) อย่างปลอดภัย // จากตัวอย่างข้างล่าง // - ข้อมูลนำเข้าจะต้องถูกรูปแบบ (Valid Format) = กำหนดเป็น String // - ขนาดข้อมูลนำเข้า (Value range) String param = getIntent().getStringExtra("PARAM"); Toast.makeText(this, String.format("Received param: ", param), Toast.LENGTH_LONG).show(); } public void onReturnResultClick(View view) { // Sensitive information สามารถส่งได้ผ่าน putExtra เนื่อง Activity ปลายทางอยู่ใน Application เดียวกัน Intent intent = new Intent(); intent.putExtra("RESULT", "Sensitive Information"); setResult(RESULT_OK, intent); finish(); } }
เอกสารอ้างอิง (Referrences)
- Android Application Secure Design/Secure CodingGuidebook, February 1st, 2016 Edition, Japan Smartphone Security Association (JSSEC)
- https://developer.android.com/guide/topics/manifest/activity-element.html