How to discover Developer Backdoor – Insecure Bank

บทนำ (Overview)

“Developer Backdoor” นั้นถือว่าเป็นช่องโหว่ของความปลอดภัยชนิดหนึ่ง เนื่องจากมีความเชื่อว่ารหัสผ่าน หรือประตูลับดังกล่าวถูก “Compile” อยู่ในรูปแบบของ “Byte-code” แล้วไม่สามารถที่จะอ่านออกได้ โดยส่วนมาก “Backdoor” ในมุมมองของ “Developer” นั้นก็ใส่ไว้เพื่อเป็นประตูผ่านสะดวกเมื่อถึงเวลา “Support” โปรแกรมแก้ไขปัญหา แต่ก็มีส่วนมากใส่ไว้เพื่อการณ์ประสงค์ร้าย บทความนี้นำเสนอวิธีการตรวจสอบ “Source-code” เพื่อค้นหา “Backdoor” ดังนี้

ขั้นตอน (Steps)

  1. ทำการ “Convert Bytecode” ให้เป็น “Source code” สามารถติดตามได้จากบทความ (How to reverse engineer .apk – Insecure Bank)
  2. จากนั้นค้นหา “Classes”, “Methods”, “Properties” ที่เกี่ยวข้องกับ “Login” insecurebank-backdoor01
  3. ผลการค้นหาเราพบว่ามี “Class” ที่เกี่ยวข้องกับการ “Login” คือ “LoginActivity” ให้ค้นหา “Method” ที่ชื่อ “onCreate” เนื่องจากเป็นส่วนเริ่มต้นแรกของ “Activity” โดยส่วนมากคือส่วนที่นำมาตั้งค่า “Content View” ต่าง ๆ เกี่ยวกับ “Layout” ที่ใช้สำหรับเขียนโปรแกรม
    insecurebank-backdoor02
  4. เมื่อตรวจสอบต่อไปพบว่า มีการสร้าง “Listener” สำหรับปุ่มกดเวลาเราจะ “Login” โดยเมื่อกดปุ่มแล้วจะเรียกใช้งาน “method” ที่ชื่อ  “performlogin” บรรทัดที่ 5 ในส่วนของ “onClick” ดังนี้
    this.login_buttons.setOnClickListener(new View.OnClickListener()
        {
          public void onClick(View paramAnonymousView)
          {
            LoginActivity.this.performlogin();
          }
        });
    
  5. ทีนี้เราไปตามหา “method” ที่ชื่อ “performlogin” จาก “Source code” ข้างล่างเราพบว่าโปรแกรมจะส่ง “username” และ “password” ไปยัง “object” อีกตัวที่สร้างมาจาก “class” ที่ชื่อว่า “DoLogin” บรรทัดที่ 5 – 8
      protected void performlogin()
      {
        this.Username_Text = ((EditText)findViewById(2131558520));
        this.Password_Text = ((EditText)findViewById(2131558521));
        Intent localIntent = new Intent(this, DoLogin.class);
        localIntent.putExtra("passed_username", this.Username_Text.getText().toString());
        localIntent.putExtra("passed_password", this.Password_Text.getText().toString());
        startActivity(localIntent);
      }
    
  6. เราก็ยังตามต่อไปที่ “Class” ที่ชื่อว่า “DoLogin” พยายามค้นหา “Method” ที่ชื่อ “onCreate” เราจะพบว่า โปรแกรมจะอ่าน “username” และ “password” เก็บไว้ แล้วเรียกใช้งาน “Class” ที่ชื่อ “RequestTask” บรรทัด 12 -14
      protected void onCreate(Bundle paramBundle)
      {
        super.onCreate(paramBundle);
        setContentView(2130968602);
        finish();
        this.serverDetails = PreferenceManager.getDefaultSharedPreferences(this);
        this.serverip = this.serverDetails.getString("serverip", null);
        this.serverport = this.serverDetails.getString("serverport", null);
        if ((this.serverip != null) && (this.serverport != null))
        {
          Intent localIntent = getIntent();
          this.username = localIntent.getStringExtra("passed_username");
          this.password = localIntent.getStringExtra("passed_password");
          new RequestTask().execute(new String[] { "username" });
          return;
        }
        startActivity(new Intent(this, FilePrefActivity.class));
        Toast.makeText(this, "Server path/port not set!", 1).show();
      }
    
  7. ข้อมูลเพิ่มเติม: “AsyncTask” เป็น “Class” สำหรับเปิดใช้งาน “UI thread” ที่อนุญาตให้ใช้งานใน “Background operations” โดยมี “Methods” ที่น่าสนใจดังนี้
    • doInBackground: ใช้สำหรับประมวลใน “Background operations” สามารถประมวลผลข้อมูลที่มีระยะเวลายาวนานได้
    • onProgressUpdate: ใช้แสดง “Progress” สำหรับแสดงให้ “user” ทราบว่า ยังมีการประมวลผลอยู่
    • onPostExecute: ใช้สำหรับแสดงผลการประมวลผล insecurebank-backdoor03
  8. ให้ตามไปที่ “Class” ที่ชื่อ “RequestTask” ให้พยายามหา “Methods” ดังนี้ “onPreExecute”, “doInBackground”, “onProgressUpdate” และ “onPostExecute”
    class RequestTask
         extends AsyncTask<String, String, String>
      {
      }
    
  9. จากการค้นหาเราพบ “Method” ที่ชื่อ “doInBackground” เพียงอันเดียว และมีการใช้งาน “Method” ที่ชื่อ “postData”  บรรทัดที่ 5
    protected String doInBackground(String... paramVarArgs)
        {
          try
          {
            postData(paramVarArgs[0]);
            return null;
          }
        }
    
  10. เราตามต่อที่ “Method” ที่ชื่อ “postData” พบว่ามีการตรวจสอบว่าถ้า “username” เท่ากับ “devadmin” บรรทัดที่ 10
        public void postData(String paramString)
          throws ClientProtocolException, IOException, JSONException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException
        {
          DefaultHttpClient localDefaultHttpClient = new DefaultHttpClient();
          HttpPost localHttpPost1 = new HttpPost(DoLogin.this.protocol + DoLogin.this.serverip + ":" + DoLogin.this.serverport + "/login");
          HttpPost localHttpPost2 = new HttpPost(DoLogin.this.protocol + DoLogin.this.serverip + ":" + DoLogin.this.serverport + "/devlogin");
          ArrayList localArrayList = new ArrayList(2);
          localArrayList.add(new BasicNameValuePair("username", DoLogin.this.username));
          localArrayList.add(new BasicNameValuePair("password", DoLogin.this.password));
          if (DoLogin.this.username.equals("devadmin")) {
            localHttpPost2.setEntity(new UrlEncodedFormEntity(localArrayList));
          }
          for (HttpResponse localHttpResponse = localDefaultHttpClient.execute(localHttpPost2);; localHttpResponse = localDefaultHttpClient.execute(localHttpPost1))
          {
            InputStream localInputStream = localHttpResponse.getEntity().getContent();
            DoLogin.this.result = convertStreamToString(localInputStream);
            DoLogin.this.result = DoLogin.this.result.replace("\n", "");
            if (DoLogin.this.result != null)
            {
              if (DoLogin.this.result.indexOf("Correct Credentials") == -1) {
                break;
              }
              Log.d("Successful Login:", ", account=" + DoLogin.this.username + ":" + DoLogin.this.password);
              saveCreds(DoLogin.this.username, DoLogin.this.password);
              trackUserLogins();
              Intent localIntent2 = new Intent(DoLogin.this.getApplicationContext(), PostLogin.class);
              localIntent2.putExtra("uname", DoLogin.this.username);
              DoLogin.this.startActivity(localIntent2);
            }
            return;
            localHttpPost1.setEntity(new UrlEncodedFormEntity(localArrayList));
          }
          Intent localIntent1 = new Intent(DoLogin.this.getApplicationContext(), WrongLogin.class);
          DoLogin.this.startActivity(localIntent1);
        }
      }
    
  11. ที่นี้ลองเอา “username” ที่ค้นพบไป “login” โดยไม่จำเป็นต้องใส่ “password” พบว่าสามารถเข้าถึงหน้าหลัง “login” ได้insecurebank-backdoor04insecurebank-backdoor05

 

ใส่ความเห็น