วิธีปฏิบัติที่ดีที่สุดสำหรับการจัดเก็บและปกป้องคีย์ API ส่วนตัวในแอปพลิเคชัน [ปิด]


373

นักพัฒนาแอพส่วนใหญ่จะรวมห้องสมุดบุคคลที่สามเข้ากับแอพของพวกเขา ถ้าเป็นการเข้าถึงบริการเช่น Dropbox หรือ YouTube หรือการบันทึกการขัดข้อง จำนวนไลบรารีและบริการของบุคคลที่สามกำลังส่าย ไลบรารี่และบริการส่วนใหญ่นั้นได้รับการบูรณาการโดยการรับรองความถูกต้องกับบริการส่วนใหญ่แล้วเกิดขึ้นผ่านคีย์ API เพื่อวัตถุประสงค์ด้านความปลอดภัยบริการมักจะสร้างสาธารณะและเอกชนมักจะเรียกว่าเป็นความลับที่สำคัญ น่าเสียดายที่เพื่อเชื่อมต่อกับบริการคีย์ส่วนตัวนี้จะต้องใช้ในการตรวจสอบและด้วยเหตุนี้อาจเป็นส่วนหนึ่งของแอปพลิเคชัน ไม่จำเป็นต้องพูดเลยว่าสิ่งนี้กำลังเผชิญกับปัญหาด้านความปลอดภัยอันยิ่งใหญ่ คีย์ API สาธารณะและส่วนตัวสามารถดึงมาจาก APK ในเวลาไม่กี่นาทีและสามารถเป็นอัตโนมัติได้อย่างง่ายดาย

สมมติว่าฉันมีบางสิ่งที่คล้ายกันนี้ฉันจะป้องกันรหัสลับได้อย่างไร:

public class DropboxService  {

    private final static String APP_KEY = "jk433g34hg3";
    private final static String APP_SECRET = "987dwdqwdqw90";
    private final static AccessType ACCESS_TYPE = AccessType.DROPBOX;

    // SOME MORE CODE HERE

}

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



ฉันเก็บภาพ / png และรับกุญแจผ่าน png ในฐานะ BufferReader
Sumit

ผมคิดว่านี่เป็นความกังวลที่ถูกต้องและโพสต์ปัญหาที่คล้ายกันในหน้า Firebase Android SDK GitHub: github.com/firebase/firebase-android-sdk/issues/1583 มาดูกันว่าเรื่องนี้ได้รับการจัดการไหม
grebulon

คำตอบ:


348
  1. แอปพลิเคชันที่รวบรวมของคุณมีสตริงที่สำคัญ แต่ยังมีชื่อคงที่ APP_KEY และ APP_SECRET การแตกกุญแจจากรหัสการทำเอกสารด้วยตนเองนั้นเป็นเรื่องเล็กน้อยเช่นกับเครื่องมือ Android มาตรฐาน dx

  2. คุณสามารถใช้ ProGuard มันจะปล่อยให้สตริงที่สำคัญแตะต้อง แต่มันจะลบชื่อคงที่ มันจะเปลี่ยนชื่อคลาสและเมธอดด้วยชื่อที่สั้นและไม่มีความหมายซึ่งเป็นไปได้ การแตกคีย์นั้นใช้เวลานานขึ้นในการหาว่าสตริงใดทำหน้าที่ตามวัตถุประสงค์

    โปรดทราบว่าการตั้งค่า ProGuard ไม่ควรยากอย่างที่คุณกลัว ในการเริ่มต้นคุณจะต้องเปิดใช้งาน ProGuard ตามที่ระบุไว้ใน project.properties หากมีปัญหาใด ๆ กับห้องสมุดของบุคคลที่สามคุณอาจต้องระงับคำเตือนและ / หรือป้องกันไม่ให้พวกเขาสับสนใน proguard-project.txt ตัวอย่างเช่น

    -dontwarn com.dropbox.**
    -keep class com.dropbox.** { *; }

    นี่เป็นวิธีการที่ดุร้าย คุณสามารถปรับแต่งการกำหนดค่าดังกล่าวได้เมื่อแอปพลิเคชันที่ประมวลผลทำงาน

  3. คุณสามารถทำให้งงสตริงด้วยตนเองในรหัสของคุณเช่นด้วยการเข้ารหัส Base64 หรือโดยเฉพาะอย่างยิ่งกับสิ่งที่ซับซ้อนมากขึ้น; อาจจะเป็นรหัสพื้นเมือง แฮ็คเกอร์จะต้องย้อนกลับแบบคงที่วิศวกรการเข้ารหัสของคุณหรือขัดขวางการถอดรหัสแบบไดนามิกในสถานที่ที่เหมาะสม

  4. คุณสามารถใช้ Obfuscator เชิงพาณิชย์เช่นพี่น้องเฉพาะ ProGuard ของDexGuard มันสามารถเพิ่มเติมเข้ารหัส / obfuscate สตริงและคลาสสำหรับคุณ การแตกกุญแจจะต้องใช้เวลาและความเชี่ยวชาญมากขึ้น

  5. คุณอาจเรียกใช้บางส่วนของแอปพลิเคชันของคุณบนเซิร์ฟเวอร์ของคุณเอง หากคุณสามารถเก็บกุญแจไว้ที่นั่นก็จะปลอดภัย

ในท้ายที่สุดมันเป็นการแลกเปลี่ยนทางเศรษฐกิจที่คุณต้องทำ: ความสำคัญของคีย์, เวลาหรือซอฟต์แวร์ที่คุณสามารถจ่ายได้เท่าไหร่, แฮ็กเกอร์ที่สนใจกุญแจ, พวกเขาต้องการเวลาเท่าไหร่ ใช้เวลาเท่าไรความล่าช้าก่อนที่คีย์จะถูกแฮ็กข้อมูลแฮ็กเกอร์ที่ประสบความสำเร็จจะกระจายกุญแจ ฯลฯ ในระดับใดข้อมูลขนาดเล็กเช่นคีย์จะป้องกันได้ยากกว่าแอปพลิเคชั่นทั้งหมด โดยพื้นฐานแล้วไม่มีอะไรในฝั่งไคลเอ็นต์ที่ไม่สามารถแตกได้ แต่คุณสามารถยกระดับมาตรฐานได้

(ฉันเป็นผู้พัฒนา ProGuard และ DexGuard)


2
@EricLafortune ไม่ได้สร้างความแตกต่างถ้าเก็บสายอักขระส่วนตัวใน Java class vs ใน XML Resource String?
อลัน

1
@EricLafortune ตอนนี้เป็นไปได้ไหมที่จะใช้ระบบ Android Keystore เพื่อจัดเก็บกุญแจอย่างปลอดภัยหรือไม่? ( developer.android.com/training/articles/keystore.html )
David Thomas

1
@DavidThomas: คุณลองใช้ที่เก็บคีย์หรือไม่ ฉันต้องการทำให้คีย์ API ที่เขียนในคลาส Java ยุ่งเหยิง โปรดตอบกลับ
Sagar Trehan

1
Android KeyStore มีประโยชน์สำหรับสิ่งนี้หรือไม่? ( developer.android.com/training/articles/… )
Weishi Zeng

1
ฉันไม่เข้าใจ # 5 มันไม่ได้มีปัญหาตรงกับปัญหาดั้งเดิมใช่ไหม
pete

80

ในความคิดของฉันมีเพียงแนวคิดแรกเท่านั้นที่รับประกัน:

  1. เก็บความลับของคุณบนเซิร์ฟเวอร์บางอย่างบนอินเทอร์เน็ตและเมื่อจำเป็นเพียงแค่หยิบมันมาใช้ หากผู้ใช้กำลังจะใช้ดรอปบ็อกซ์ไม่มีอะไรจะหยุดคุณจากการร้องขอไปยังเว็บไซต์ของคุณและรับรหัสลับของคุณ

  2. ใส่ความลับของคุณในรหัส jni เพิ่มรหัสตัวแปรบางอย่างเพื่อทำให้ไลบรารีของคุณใหญ่ขึ้นและยากต่อการถอดรหัส คุณอาจแยกสตริงคีย์ในส่วนที่น้อยและเก็บไว้ในที่ต่าง ๆ

  3. ใช้ obfuscator และใส่รหัสลับแฮชและหลังจากนั้นปล่อยเมื่อจำเป็นต้องใช้

  4. ใส่รหัสลับของคุณเป็นพิกเซลสุดท้ายของหนึ่งในภาพของคุณในเนื้อหา จากนั้นเมื่อจำเป็นต้องอ่านมันในรหัสของคุณ การทำให้รหัสของคุณสับสนควรช่วยซ่อนรหัสที่จะอ่าน

หากคุณต้องการดูอย่างรวดเร็วว่าการอ่านโค้ด apk ของคุณนั้นง่ายแค่ไหนให้หยิบ APKAnalyser:

http://developer.sonymobile.com/knowledge-base/tool-guides/analyse-your-apks-with-apkanalyser/


46
หากผู้ใช้สามารถถอดรหัสแอปได้แม้ว่าพวกเขาจะสามารถกำหนดคำขอที่ทำกับเซิร์ฟเวอร์ของคุณและเพียงแค่ดำเนินการเพื่อรับความลับ ไม่มีกระสุนเงินที่นี่ แต่ทำไม่กี่ก้าวและฉันพนันได้เลยว่าคุณจะสบายดี! หากแอปของคุณได้รับความนิยมสูงสุด แต่อาจจะไม่ใช่ .. ความคิดที่ยอดเยี่ยม!
Matt Wolfe

3
ใช่หมายเลข 1 ไม่รับประกัน
marcinj

42
ฉันชอบความคิดในการซ่อนกุญแจไว้ในภาพ +1
อิกอร์Čordaš

1
@ MarcinJędrzejewskiคุณต้องการที่จะอธิบายเพิ่มเติม (พร้อมตัวอย่างหรือรหัสที่ดีกว่า) เกี่ยวกับการแก้ปัญหาที่ออกมา? ขอบคุณ.
Dr.jacky

2
@ Mr.Hyde นี้เรียกว่า Steganography ซึ่งซับซ้อนเกินไปที่จะให้โค้ดตัวอย่างที่นี่คุณสามารถหาตัวอย่างบน google ได้ ฉันได้พบหนึ่งที่นี่: dreamincode.net/forums/topic/27950-steganography ความคิดนั้นดี แต่เนื่องจากรหัส apk สามารถถอดรหัสได้มันทำลายความงามของมัน
marcinj

33

อีกวิธีคือการไม่มีความลับในอุปกรณ์ตั้งแต่แรก! ดูเทคนิคความปลอดภัย API มือถือ (โดยเฉพาะตอนที่ 3)

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

เมื่อลูกค้าของคุณต้องการโทร API ลูกค้าจะขอให้บริการรับรองความถูกต้องของแอปเพื่อตรวจสอบสิทธิ์ (ใช้เทคนิคการยืนยันระยะไกลที่รัดกุม) และรับเวลา จำกัด (โดยทั่วไปคือJWT ) โทเค็นที่ลงชื่อโดยความลับ

โทเค็นจะถูกส่งไปพร้อมกับการเรียก APIแต่ละครั้งที่ปลายทางสามารถตรวจสอบลายเซ็นได้ก่อนดำเนินการตามคำขอ

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

ดังนั้นหากคุณต้องการที่จะปกป้องความลับของคุณการไม่มีมันไว้ในแอพของคุณตั้งแต่แรกเป็นวิธีที่ดีมาก


5
นี่ควรเป็นคำตอบที่ยอมรับได้
ortonomy

3
ปัญหายังคงมีอยู่เมื่อคุณต้องการเข้าถึงบริการการตรวจสอบความถูกต้อง มันจะให้รหัสลูกค้าและความลับของลูกค้า เราจะช่วยพวกเขาได้ที่ไหน
Ashi

ไม่ได้แก้ apis ส่วนตัวที่คุณต้องรับรองความถูกต้องกับ api ของคุณก่อนเพื่อใช้งาน คุณจะได้รับข้อมูลรับรองสำหรับผู้ใช้แอปทั้งหมดได้ที่ไหน
Kibotu

25

วิธีที่ไม่ปลอดภัยเก่า:

ทำตาม 3 ขั้นตอนง่ายๆเพื่อรักษาความปลอดภัยของ API / รหัสลับ ( คำตอบเดิม )

เราสามารถใช้ Gradle เพื่อรักษาความปลอดภัยรหัส API หรือรหัสลับ

1. gradle.properties (คุณสมบัติโครงการ):สร้างตัวแปรด้วยคีย์

GoolgeAPIKey = "Your API/Secret Key"

2. build.gradle (โมดูล: แอพ):ตั้งค่าตัวแปรใน build.gradle เพื่อเข้าถึงมันในกิจกรรมหรือส่วน เพิ่มรหัสด้านล่างเพื่อ buildTypes {}

buildTypes.each {
    it.buildConfigField 'String', 'GoogleSecAPIKEY', GoolgeAPIKey
}

3. เข้าถึงได้ในกิจกรรม / ชิ้นส่วนโดย BuildConfig ของแอป:

BuildConfig.GoogleSecAPIKEY

อัปเดต:

การแก้ปัญหาข้างต้นมีประโยชน์ในโครงการโอเพนซอร์ซที่จะส่งมอบผ่าน Git (ขอบคุณ David Rawson และ riyaz-ali สำหรับความคิดเห็นของคุณ)

ตามความเห็นของ Matthew และ Pablo Cegarra วิธีข้างต้นไม่ปลอดภัยและ Decompiler จะอนุญาตให้บางคนดู BuildConfig ด้วยรหัสลับของเรา

สารละลาย :

เราสามารถใช้ NDK เพื่อรักษาความปลอดภัยคีย์ API เราสามารถจัดเก็บคีย์ในคลาส C / C ++ และเข้าถึงคลาสเหล่านั้นในคลาส Java ของเรา

โปรดติดตามบล็อกนี้เพื่อรักษาความปลอดภัยคีย์ API โดยใช้ NDK

การติดตามวิธีจัดเก็บโทเค็นอย่างปลอดภัยใน Android


4
การจัดเก็บคีย์ในไฟล์ gradle ปลอดภัยหรือไม่?
Google

4
@Google gradle.propertiesไม่ควรเช็คอิน Git ดังนั้นนี่เป็นวิธีในการเก็บความลับจากซอร์สโค้ดที่กำหนดไว้อย่างน้อย
David Rawson

4
สิ่งนี้ไม่ได้ป้องกันคีย์ API จากการรวมเข้ากับผลลัพธ์apk(มันจะถูกเพิ่มลงในBuildConfigไฟล์ที่สร้างขึ้น) แม้ว่าจะเป็นความคิดที่ดีในการจัดการคีย์ API ที่แตกต่างกัน (เช่นในโครงการโอเพ่นซอร์ส)
riyaz-ali

5
การใช้ Java Decompiler จะอนุญาตให้บางคนดูไฟล์ BuildConfig และ "GoogleSecAPIKEY"
Matthew

3
BuildConfig.javaไฟล์ของคุณจะมีคีย์ในรูปแบบข้อความล้วน นี่ไม่ได้ดีไปกว่าสิ่งที่ OP กำลังทำอยู่
iceman

16

รหัสลับของแอปควรเก็บเป็นความลับ - แต่เมื่อมีการปล่อยแอพพวกเขาสามารถย้อนกลับได้โดยบางคน

สำหรับพวกนั้นมันจะไม่ซ่อน, ล็อคProGuardรหัสอย่างใดอย่างหนึ่ง มันเป็น refactor และผู้ obfuscators ที่จ่ายเงินบางส่วนกำลังแทรกตัวดำเนินการระดับบิตสองสามตัวเพื่อกลับคืนjk433g34hg3 สตริงกลับ คุณสามารถแฮ็คได้นาน 5 -15 นาทีหากคุณทำงาน 3 วัน :)

ทางที่ดีควรเก็บไว้ตามที่เป็น

แม้ว่าคุณจะจัดเก็บที่ฝั่งเซิร์ฟเวอร์ (พีซีของคุณ) คีย์สามารถแฮ็กและพิมพ์ออกมาได้ บางทีนี่อาจใช้เวลานานที่สุด? อย่างไรก็ตามมันเป็นเรื่องของไม่กี่นาทีหรือไม่กี่ชั่วโมงในกรณีที่ดีที่สุด

ผู้ใช้ปกติจะไม่ถอดรหัสรหัสของคุณ


1
ดี - ไม่ใช่คำตอบที่ฉันหวังว่าจะได้รับ =) ... ฉันคิดว่าคุณสามารถรักษาความปลอดภัยได้เป็นอย่างดี :(
Coder ขั้นพื้นฐาน

ขออภัยมันไม่ได้เป็นอย่างที่คุณต้องการโซลูชั่นที่สดใสเป็นพิเศษ แต่สำหรับผู้ที่สามารถใช้คอมไพเลอร์ decompiler ก็ไม่มีรหัส Java ที่ปลอดภัย: แม้แต่รหัสดั้งเดิมก็สามารถดูได้ด้วย hexa viewer และ decrtyped อย่างน้อยน่าลอง ...

1
Proguard จะไม่ทำให้คีย์ผิด ๆ สิ่งที่ดีที่สุดที่จะทำคือชุดคำสั่ง encript / decript ง่ายๆที่ obfuscate จะซ่อน
Doomsknight

3
มันคือ "มองเห็น" รูทีนการถอดรหัสเป็นเรื่องง่ายที่จะย้อนกลับและคุณมีสตริงดั้งเดิม

14

ทางออกหนึ่งที่เป็นไปได้คือการเข้ารหัสข้อมูลในแอปของคุณและใช้การถอดรหัสที่รันไทม์ (เมื่อคุณต้องการใช้ข้อมูลนั้น) ฉันยังแนะนำให้ใช้ progaurd เพื่อทำให้อ่านและเข้าใจซอร์สโค้ดที่ถอดรหัสแล้วของแอปของคุณได้ยาก ตัวอย่างเช่นฉันใส่รหัสที่เข้ารหัสในแอพจากนั้นใช้วิธีการถอดรหัสในแอพของฉันเพื่อถอดรหัสคีย์ลับของฉันที่รันไทม์:

// "the real string is: "mypassword" "; 
//encoded 2 times with an algorithm or you can encode with other algorithms too
public String getClientSecret() {
    return Utils.decode(Utils
            .decode("Ylhsd1lYTnpkMjl5WkE9PQ=="));
}

ซอร์สโค้ดที่คอมไพล์แล้วของแอปที่ได้รับการป้องกันคือ:

 public String c()
 {
    return com.myrpoject.mypackage.g.h.a(com.myrpoject.mypackage.g.h.a("Ylhsd1lYTnpkMjl5WkE9PQ=="));
  }

อย่างน้อยมันก็ซับซ้อนพอสำหรับฉัน นี่คือวิธีที่ฉันทำเมื่อฉันไม่มีทางเลือก แต่เก็บค่าไว้ในใบสมัครของฉัน แน่นอนเราทุกคนรู้ว่ามันไม่ได้เป็นวิธีที่ดีที่สุด แต่ก็ใช้งานได้สำหรับฉัน

/**
 * @param input
 * @return decoded string
 */
public static String decode(String input) {
    // Receiving side
    String text = "";
    try {
        byte[] data = Decoder.decode(input);
        text = new String(data, "UTF-8");
        return text;
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    return "Error";
}

เวอร์ชันที่แปลแล้ว:

 public static String a(String paramString)
  {
    try
    {
      str = new String(a.a(paramString), "UTF-8");
      return str;
    }
    catch (UnsupportedEncodingException localUnsupportedEncodingException)
    {
      while (true)
      {
        localUnsupportedEncodingException.printStackTrace();
        String str = "Error";
      }
    }
  }

และคุณสามารถค้นหาคลาสของ Encryptor จำนวนมากด้วยการค้นหาเพียงเล็กน้อยใน Google


13

การเพิ่มโซลูชัน @Manohar Reddy ฐานข้อมูล firebase หรือ firebase RemoteConfig (ที่มีค่าดีฟอลต์ Null) สามารถใช้ได้:

  1. เข้ารหัสคีย์ของคุณ
  2. เก็บไว้ในฐานข้อมูล firebase
  3. รับได้ระหว่างการเริ่มต้นแอพหรือเมื่อใดก็ตามที่จำเป็น
  4. ถอดรหัสคีย์และใช้งาน

อะไรคือสิ่งที่แตกต่างในโซลูชันนี้?

  • ไม่มี creditintials สำหรับ firebase
  • การเข้าถึง firebase ได้รับการคุ้มครองดังนั้นแอปที่มีใบรับรองที่ลงนามแล้วเท่านั้นที่มีสิทธิ์โทร API
  • การเข้ารหัส / ถอดรหัสเพื่อป้องกันการสกัดกั้นชายกลาง อย่างไรก็ตามโทรไปที่ฐาน Fire แล้ว

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

ข้อดีอย่างหนึ่งแม้ว่าด้วยวิธีแก้ปัญหาที่แนะนำเรากำลังเพิ่มความซับซ้อนอีกหนึ่งอย่างต่อหน้าแฮ็กเกอร์
Ashi

11

ตัวอย่างนี้มีแง่มุมต่าง ๆ มากมาย ฉันจะพูดถึงสองประเด็นที่ฉันไม่คิดว่าได้รับการคุ้มครองอย่างชัดเจนที่อื่น

ปกป้องความลับในการขนส่ง

สิ่งแรกที่ควรทราบคือการเข้าถึง Dropbox API โดยใช้กลไกการตรวจสอบสิทธิ์แอพนั้นคุณต้องส่งคีย์และความลับของคุณ การเชื่อมต่อคือ HTTPS ซึ่งหมายความว่าคุณไม่สามารถดักจับทราฟฟิกโดยไม่ทราบว่าใบรับรอง TLS เพื่อป้องกันไม่ให้บุคคลดักจับและอ่านแพ็กเก็ตในการเดินทางจากอุปกรณ์พกพาไปยังเซิร์ฟเวอร์ สำหรับผู้ใช้ทั่วไปเป็นวิธีที่ดีในการรับรองความเป็นส่วนตัวของการรับส่งข้อมูล

สิ่งที่ไม่ดีคือป้องกันผู้ประสงค์ร้ายที่ดาวน์โหลดแอพและตรวจสอบปริมาณการใช้งาน เป็นเรื่องง่ายมากที่จะใช้พร็อกซีแบบแมน - อิน - มิดสำหรับการรับส่งข้อมูลเข้าและออกจากอุปกรณ์พกพา มันจะต้องไม่มีการถอดหรือวิศวกรรมย้อนกลับของรหัสเพื่อแยกคีย์แอปและความลับในกรณีนี้เนื่องจากลักษณะของ Dropbox API

คุณสามารถทำตรึงซึ่งการตรวจสอบว่า TLS ที่คุณได้รับจากเซิร์ฟเวอร์เป็นหนึ่งที่คุณคาดหวัง สิ่งนี้จะเพิ่มการตรวจสอบให้กับลูกค้าและทำให้การสกัดกั้นทราฟฟิกยากขึ้น สิ่งนี้จะทำให้ยากต่อการตรวจสอบการจราจรในเที่ยวบิน แต่การตรวจสอบการตรึงเกิดขึ้นในไคลเอนต์ดังนั้นจึงเป็นไปได้ที่จะปิดการทดสอบการปักหมุด มันทำให้มันยากขึ้น

ปกป้องความลับที่เหลือ

ในขั้นตอนแรกการใช้สิ่งที่คล้ายกับproguardจะช่วยให้ชัดเจนน้อยลงเมื่อมีการเก็บความลับ นอกจากนี้คุณยังสามารถใช้ NDK เพื่อเก็บคีย์และความลับและส่งคำขอโดยตรงซึ่งจะช่วยลดจำนวนคนที่มีทักษะที่เหมาะสมในการดึงข้อมูล การทำให้งงงวยเพิ่มเติมสามารถทำได้โดยไม่เก็บค่าโดยตรงในหน่วยความจำระยะเวลาใด ๆ คุณสามารถเข้ารหัสและถอดรหัสก่อนใช้ตามคำแนะนำอื่น

ตัวเลือกขั้นสูงเพิ่มเติม

หากคุณหวาดระแวงเกี่ยวกับการใส่ความลับไว้ที่ใดก็ได้ในแอปของคุณและคุณมีเวลาและเงินในการลงทุนในโซลูชันที่ครอบคลุมมากขึ้นคุณอาจพิจารณาจัดเก็บข้อมูลประจำตัวบนเซิร์ฟเวอร์ของคุณ (สมมติว่าคุณมี) วิธีนี้จะเพิ่มเวลาแฝงของการโทรไปยัง API เนื่องจากจะต้องสื่อสารผ่านเซิร์ฟเวอร์ของคุณและอาจเพิ่มค่าใช้จ่ายในการเรียกใช้บริการของคุณเนื่องจากปริมาณข้อมูลที่เพิ่มขึ้น

จากนั้นคุณต้องตัดสินใจว่าจะสื่อสารกับเซิร์ฟเวอร์ของคุณอย่างไรเพื่อให้แน่ใจว่าได้รับการปกป้อง นี่เป็นสิ่งสำคัญเพื่อป้องกันปัญหาเดียวกันทั้งหมดที่เกิดขึ้นอีกครั้งด้วย API ภายในของคุณ กฎง่ายๆที่ฉันสามารถให้ได้ก็คืออย่าส่งความลับใด ๆ โดยตรงเนื่องจากการคุกคามจากคนกลาง แต่คุณสามารถลงชื่อเข้าใช้ทราฟฟิกโดยใช้ความลับของคุณและตรวจสอบความถูกต้องของคำขอใด ๆ ที่มายังเซิร์ฟเวอร์ของคุณ วิธีหนึ่งที่เป็นมาตรฐานในการทำเช่นนี้คือการคำนวณ HMAC ของข้อความที่เป็นความลับ ฉันทำงานที่ บริษัท ที่มีผลิตภัณฑ์รักษาความปลอดภัยซึ่งทำงานในสาขานี้ด้วยเหตุนี้สิ่งต่าง ๆ ที่ฉันสนใจ อันที่จริงนี่เป็นบทความบล็อกจากหนึ่งในเพื่อนร่วมงานของฉันที่ทำเรื่องส่วนใหญ่

ฉันควรทำอย่างไร

ด้วยคำแนะนำด้านความปลอดภัยเช่นนี้คุณต้องตัดสินใจเรื่องค่าใช้จ่าย / ผลประโยชน์ว่าคุณต้องการให้ใครบางคนบุกเข้ามาได้ยากเพียงใดถ้าคุณเป็นธนาคารที่ปกป้องลูกค้านับล้านงบประมาณของคุณแตกต่างจากคนที่สนับสนุนแอป เวลาว่าง. แทบเป็นไปไม่ได้ที่จะป้องกันไม่ให้ใครบางคนทำลายระบบรักษาความปลอดภัยของคุณ แต่ในทางปฏิบัติมีเพียงไม่กี่คนที่ต้องการเสียงระฆังและเสียงนกหวีดและด้วยความระมัดระวังขั้นพื้นฐานบางอย่างคุณจึงสามารถเดินทางได้ไกล


1
คุณเพิ่งคัดลอกและวางสิ่งนี้จากที่นี่: hackernoon.com/mobile-api-security-techniques-682a5da4fe10โดยไม่ยอมรับแหล่งที่มา
ortonomy

1
@ortonomy ฉันยอมรับว่าเขาควรจะยกบทความที่คุณเชื่อมโยง แต่เขาอาจลืมเพราะทั้งสองทำงานในสถานที่เดียวกัน ...
23926

2
อีกทั้งบทความของ Skip และการโพสต์บล็อกที่พวกเขาอ้างอิงนั้นออกมาหนึ่งสัปดาห์หลังจากคำตอบของฉัน
ThePragmatist

8

โซลูชันที่ปลอดภัยที่สุดคือการเก็บคีย์ของคุณไว้บนเซิร์ฟเวอร์และกำหนดเส้นทางคำขอทั้งหมดที่ต้องการคีย์นั้นผ่านเซิร์ฟเวอร์ของคุณ ด้วยวิธีนี้คีย์จะไม่ออกจากเซิร์ฟเวอร์ของคุณตราบใดที่เซิร์ฟเวอร์ของคุณปลอดภัยแล้วก็เป็นกุญแจของคุณ แน่นอนว่ามีค่าใช้จ่ายด้านประสิทธิภาพด้วยโซลูชันนี้


32
ปัญหาคือ - เพื่อเข้าถึงเซิร์ฟเวอร์ที่มี secrect ทั้งหมดที่ฉันควรใช้ Secret Key อื่น - ฉันสงสัยว่าฉันจะเก็บไว้ที่ไหน? ;) สิ่งที่ฉันพยายามจะพูดคือ - นี่ไม่ใช่ทางออกที่ดีที่สุด (อย่าคิดว่ามีทางออกที่ดีที่สุดที่นี่)
Mercury

ไม่จริงเลยเซิร์ฟเวอร์ของคุณอยู่ภายใต้การควบคุมของคุณอย่างสมบูรณ์ สิ่งที่ต้องการทั้งหมดขึ้นอยู่กับคุณ
เบอร์นาร์ดอิกิริ

5
คุณช่วยอธิบายได้อย่างไรว่าไคลเอนต์สามารถเข้ารหัสข้อมูลที่เขาต้องการส่งไปยังเซิร์ฟเวอร์ได้อย่างไรในขณะที่คีย์อยู่ฝั่งเซิร์ฟเวอร์ และถ้าคำตอบของคุณคือ - เซิร์ฟเวอร์จะส่งคีย์ไปยังลูกค้า - ดังนั้นต้องมีการรักษาความปลอดภัยเช่นกัน! ดังนั้นอีกครั้งไม่มีทางออกมายากล! ไม่เห็นเหรอ!
ปรอท

2
@BernardIgiri และจากนั้นเรากลับไปที่ Square 1 อีกครั้งสมมติว่าโทรศัพท์สร้างการเข้าสู่ระบบแบบสุ่มและเซิร์ฟเวอร์ยอมรับและส่งพิน (นี่คือเซิร์ฟเวอร์ส่วนตัวที่เรากำลังพูดถึง) จากนั้นคนที่ถอดแอปของคุณจะเห็นว่าการเข้าถึงเซิร์ฟเวอร์ส่วนตัวของคุณนั้นเป็นเพียงแค่การเข้าสู่ระบบแบบสุ่มซึ่งเขาสามารถสร้างขึ้นเองได้ บอกฉันทีว่าจะห้ามไม่ให้เขาสร้างและเข้าถึงเซิร์ฟเวอร์ของคุณได้อย่างไร อันที่จริงแล้วอะไรคือความแตกต่างระหว่างโซลูชันของคุณและการจัดเก็บล็อกอินหรือคีย์ api ไปยังเซิร์ฟเวอร์หลัก (ซึ่งมีข้อมูลรับรองที่เราต้องการเก็บไว้ในเซิร์ฟเวอร์ส่วนตัวของเรา)
Ken

3
@ken หมายเลขสุ่มจะได้รับการรับรองความถูกต้องกับหมายเลขโทรศัพท์และการเข้าถึงข้อความตัวอักษร หากมีคนโกงคุณคุณมีข้อมูลของพวกเขา หากยังไม่ดีพอบังคับให้พวกเขาสร้างบัญชีผู้ใช้และรหัสผ่านแบบเต็ม ถ้านั่นยังไม่ดีพอรับบัตรเครดิตด้วย หากยังไม่ดีพอให้พวกเขาโทรเข้าถ้านั่นยังไม่ดีพอที่พวกเขาพบเจอแบบตัวต่อตัว คุณต้องการความปลอดภัย / ไม่สะดวกแค่ไหน?
Bernard Igiri

7

เก็บเป็นความลับfirebase databaseและรับมันเมื่อแอพเริ่มต้นมันดีกว่าการโทรหาบริการบนเว็บ


13
แต่สิ่งที่เกี่ยวกับข้อมูลประจำตัวเพื่อ firebase?
the_joric

2
น่าเสียดายที่ฐานข้อมูล Firebase ไม่ทำงานในประเทศจีน
Konjengbam

9
ไม่สมเหตุสมผลผู้โจมตีสามารถเห็นรายละเอียด firebase ของคุณจาก decompiled code และรับข้อมูลใด ๆ จาก datababse ของคุณ
924

3
ฉันคิดว่านี่เป็นทางออกที่ดีที่สุดเนื่องจากแอป firebase ใช้ SHA1 เพื่ออนุญาตการเข้าถึงเซิร์ฟเวอร์ การถอดรหัสโค้ดจะไม่ช่วยในการโทรหา firebase เนื่องจากแอปใหม่ของแฮ็กเกอร์ควรใช้การประทับตราแอพที่แน่นอนเพื่อเข้าถึง firebase นอกจากนี้คีย์ที่เก็บไว้จะถูกเข้ารหัสก่อนที่จะจัดเก็บในฐานข้อมูล firebase และถอดรหัสเมื่อได้รับเพื่อหลีกเลี่ยงการสกัดกั้นชายกลาง
Ayman Al-Absi

เมื่อคุณได้รับความลับจากฐานข้อมูล firebase ผ่านเครือข่ายความปลอดภัยนั้นดีกว่าการรับความลับเดียวกันจากบริการเว็บอื่นผ่านช่องทางที่ปลอดภัย (https) อย่างไร คุณสามารถอธิบาย?
Csaba Toth

6

สิ่งที่คุณทำเพื่อรักษาความปลอดภัยคีย์ลับของคุณจะไม่เป็นทางออกที่แท้จริง หากนักพัฒนาสามารถถอดรหัสแอปพลิเคชันไม่มีทางที่จะรักษาความปลอดภัยของกุญแจการซ่อนกุญแจนั้นเป็นเพียงการรักษาความปลอดภัยด้วยความคลุมเครือและเป็นรหัสที่ทำให้งงงวย ปัญหาเกี่ยวกับการรักษาความปลอดภัยของรหัสลับคือเพื่อความปลอดภัยคุณจะต้องใช้รหัสอื่นและกุญแจนั้นจะต้องได้รับการรักษาความปลอดภัยด้วย นึกถึงกุญแจที่ซ่อนอยู่ในกล่องที่ถูกล็อคด้วยกุญแจ คุณวางกล่องไว้ภายในห้องและล็อคห้อง คุณเหลือกุญแจอีกดอกไว้เพื่อความปลอดภัย และกุญแจนั้นจะยังคงถูกเข้ารหัสในแอปพลิเคชันของคุณ

ดังนั้นหากผู้ใช้ป้อน PIN หรือวลีไม่มีวิธีซ่อนรหัส แต่การทำเช่นนั้นคุณจะต้องมีแผนการจัดการ PIN ที่เกิดขึ้นนอกวงซึ่งหมายความว่าผ่านช่องทางอื่น แน่นอนว่าไม่ใช่วิธีการรักษาความปลอดภัยสำหรับคีย์สำหรับบริการเช่น Google API


5

อายุโพสต์เก่า แต่ก็ยังดีพอ ฉันคิดว่าการซ่อนไว้ใน. so library นั้นยอดเยี่ยมโดยใช้ NDK และ C ++ แน่นอน สามารถดูไฟล์. so ในโปรแกรมแก้ไข hex ได้ แต่ขอให้โชคดีในการถอดรหัสว่า: P


9
ผู้ใช้สามารถเรียกใช้ฟังก์ชันไปยังไลบรารีที่ใช้ร่วมกันได้อย่างง่ายดายและรับสิ่งที่ซ่อนอยู่ที่นั่น ไม่จำเป็นต้อง decopile
david72

5
ตามandroidauthority.com/...ไม่มีวิธีที่ปลอดภัยที่จะทำมันในหุ่นยนต์ในขณะนี้
david72

1
@ AhmedAwad ไม่เข้าใจว่าทำไมถึงมี 3 upvote ผู้ใดสามารถถอดรหัสแอปได้อย่างง่ายดายและดูว่าจุดเข้าใช้งาน ndk นั้นถูกเรียกว่า: /
Johny19 19

1
คำตอบนี้เป็นหนึ่งในตัวเลือกที่ดีที่สุด แต่ผู้เขียนควรพูดถึงว่ามันสำคัญมากที่คุณควรรวมการโทร (ภายในห้องสมุด NDK ของคุณ) เพื่อดูว่าการตรวจสอบตรงกับ APK ของคุณหรือไม่ แอปของคุณ
Stoycho Andreev

@ Sniper ที่จะดียกเว้นมีปัญหาใหญ่ คุณจะรู้ได้อย่างไรว่าไฟล์คือ "การเรียก" วิธีพื้นเมือง? หากคุณยากรหัสชื่อของ apk เพื่อตรวจสอบที่ดี แต่ถ้าฉันทำ "แฮ็ค" apk โฟลเดอร์เดียวกันกับ apk "ดี"? มันจะตรวจสอบว่า apk "ดี" มีการตรวจสอบที่ดีและมันจะทำให้ฉันสามารถใช้วิธีการดั้งเดิมได้ ถ้าไม่มีวิธีที่จะรู้จักไฟล์ผู้โทรจากด้าน JNI / C ++ แล้วมันจะไม่มีจุดหมายเป็นตัวเลือกอื่น ๆ
SocketByte

5

วิธีที่แท้จริงเพียงประการเดียวในการรักษาความเป็นส่วนตัวเหล่านี้คือการเก็บไว้บนเซิร์ฟเวอร์ของคุณและให้แอปส่งสิ่งที่มันไปยังเซิร์ฟเวอร์และเซิร์ฟเวอร์จะโต้ตอบกับ Dropbox ด้วยวิธีนี้คุณจะไม่แจกจ่ายคีย์ส่วนตัวของคุณในทุกรูปแบบ


11
แต่คุณจะป้องกันไม่ให้คนทั่วโลกโทรหาเซิร์ฟเวอร์ได้อย่างไร
user2966445

ถ้าโดย "เซิร์ฟเวอร์" คุณหมายถึงเว็บเซิร์ฟเวอร์ของคุณที่มีข้อมูลประจำตัว - คุณสามารถใช้วิธีการใด ๆ ที่คุณต้องการ การพิสูจน์ตัวตนอย่างง่ายด้วยชื่อผู้ใช้ / รหัสผ่าน oauth ไดเรกทอรีที่ใช้งาน ฯลฯ ฯลฯ ขึ้นอยู่กับแอปพลิเคชันของคุณจริงๆ
Nick

บางทีฉันอาจขาดอะไรบางอย่างไป แต่สิ่งนี้ยังไม่ต้องการการจัดเก็บข้อมูลรับรองภายในแอพใช่ไหม
2966445

3
ใช่ แต่คุณบอกว่าแอปจะรับรองความถูกต้องกับเซิร์ฟเวอร์ก่อน นี่ไม่ได้หมายถึงการจัดเก็บข้อมูลรับรองอีกชุดไว้ในแอพใช่หรือไม่ ฉันเข้าใจว่าเซิร์ฟเวอร์จะจัดการกับการโทรดรอปบ็อกซ์จริง
2966445

4
มันอาจหมายถึงว่า แต่มันเป็นสิทธิ์ที่แยกจากกันโดยสิ้นเชิง แต่คุณไม่จำเป็นต้อง Usecase ที่ฉันกำลังพูดถึงคือผู้ใช้แอปของคุณจะต้องลงชื่อเข้าใช้แอพของคุณพูดโดยใช้ Facebook หรือ Twitter คุณไม่ได้จัดเก็บข้อมูลรับรองไว้ในแอปของคุณคุณไม่รู้จักเลย กระบวนการอนุญาตนั้นอนุญาตให้พวกเขาเข้าถึงเซิร์ฟเวอร์ api ของคุณซึ่งมีข้อมูลรับรองไปยังดรอปบ็อกซ์ แต่ไม่มีแอพหรือผู้ใช้ที่เข้าถึงพวกเขาโดยตรง
นิค

0

จากประสบการณ์ที่ขมขื่นและหลังจากปรึกษากับผู้เชี่ยวชาญของ IDA-Pro ทางออกที่ดีที่สุดคือการย้ายส่วนสำคัญของรหัสไปยัง DLL / SharedObject จากนั้นดึงข้อมูลจากเซิร์ฟเวอร์และโหลดที่รันไทม์

ข้อมูลที่ละเอียดอ่อนต้องได้รับการเข้ารหัสเนื่องจากมันง่ายมากที่จะทำสิ่งนี้:

$ strings libsecretlib.so | grep My
  My_S3cr3t_P@$$W0rD

3
และคุณเก็บข้อมูลรับรองสำหรับเซิร์ฟเวอร์ดังกล่าวอยู่ที่ไหน
ZX9
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.