외로운 Nova의 작업실
insecurebankv2 - 개발자 백도어 본문
- 취약점 소개
개발자들이 유지보수나 디버깅시 인증을 회피할 목적으로 만든 백도어가 있을 수 있습니다. 이러한 개발자의 백도어가 공격자에게 발견되면 시스템에 큰 위험을 초래할 수 있습니다.
- 취약점 진단 과정
DoLogin$RequestTask.class 코드를 보겠습니다.
package com.android.insecurebankv2;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.util.Base64;
import android.util.Log;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONException;
class DoLogin$RequestTask extends AsyncTask {
final DoLogin this$0;
DoLogin$RequestTask(DoLogin var1) {
this.this$0 = var1;
}
private String convertStreamToString(InputStream var1) throws IOException {
try {
DoLogin var4 = this.this$0;
InputStreamReader var2 = new InputStreamReader(var1, "UTF-8");
BufferedReader var3 = new BufferedReader(var2);
var4.reader = var3;
} catch (UnsupportedEncodingException var5) {
var5.printStackTrace();
}
StringBuilder var6 = new StringBuilder();
while(true) {
String var7 = this.this$0.reader.readLine();
if (var7 == null) {
var1.close();
return var6.toString();
}
var6.append(var7 + "\n");
}
}
private void saveCreds(String var1, String var2) throws UnsupportedEncodingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
SharedPreferences.Editor var3 = this.this$0.getSharedPreferences("mySharedPreferences", 0).edit();
this.this$0.rememberme_username = var1;
this.this$0.rememberme_password = var2;
var2 = new String(Base64.encodeToString(this.this$0.rememberme_username.getBytes(), 4));
CryptoClass var4 = new CryptoClass();
this.this$0.superSecurePassword = var4.aesEncryptedString(this.this$0.rememberme_password);
var3.putString("EncryptedUsername", var2);
var3.putString("superSecurePassword", this.this$0.superSecurePassword);
var3.commit();
}
private void trackUserLogins() {
this.this$0.runOnUiThread(new DoLogin.RequestTask.1(this));
}
protected String doInBackground(String... var1) {
Object var10;
try {
this.postData(var1[0]);
return null;
} catch (InvalidKeyException var2) {
var10 = var2;
} catch (NoSuchAlgorithmException var3) {
var10 = var3;
} catch (NoSuchPaddingException var4) {
var10 = var4;
} catch (InvalidAlgorithmParameterException var5) {
var10 = var5;
} catch (IllegalBlockSizeException var6) {
var10 = var6;
} catch (BadPaddingException var7) {
var10 = var7;
} catch (IOException var8) {
var10 = var8;
} catch (JSONException var9) {
var10 = var9;
}
((Exception)var10).printStackTrace();
return null;
}
protected void onPostExecute(Double var1) {
}
protected void onProgressUpdate(Integer... var1) {
}
public void postData(String var1) throws ClientProtocolException, IOException, JSONException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
DefaultHttpClient var5 = new DefaultHttpClient();
HttpPost var3 = new HttpPost(this.this$0.protocol + this.this$0.serverip + ":" + this.this$0.serverport + "/login");
HttpPost var2 = new HttpPost(this.this$0.protocol + this.this$0.serverip + ":" + this.this$0.serverport + "/devlogin");
ArrayList var4 = new ArrayList(2);
var4.add(new BasicNameValuePair("username", this.this$0.username));
var4.add(new BasicNameValuePair("password", this.this$0.password));
HttpResponse var6;
if (this.this$0.username.equals("devadmin")) {
var2.setEntity(new UrlEncodedFormEntity(var4));
var6 = var5.execute(var2);
} else {
var3.setEntity(new UrlEncodedFormEntity(var4));
var6 = var5.execute(var3);
}
InputStream var7 = var6.getEntity().getContent();
this.this$0.result = this.convertStreamToString(var7);
this.this$0.result = this.this$0.result.replace("\n", "");
if (this.this$0.result != null) {
Intent var8;
if (this.this$0.result.indexOf("Correct Credentials") != -1) {
Log.d("Successful Login:", ", account=" + this.this$0.username + ":" + this.this$0.password);
this.saveCreds(this.this$0.username, this.this$0.password);
this.trackUserLogins();
var8 = new Intent(this.this$0.getApplicationContext(), PostLogin.class);
var8.putExtra("uname", this.this$0.username);
this.this$0.startActivity(var8);
} else {
var8 = new Intent(this.this$0.getApplicationContext(), WrongLogin.class);
this.this$0.startActivity(var8);
}
}
}
}
PostData 함수의 var3와 var2를 보면 httpPost 객체가 2개가 있음을 알 수 있습니다. var2에는 정상적인 /login요청이 아닌 /devlogin 요청이 있습니다. 좀 더 아래코드에는
if (this.this$0.username.equals("devadmin")) {
var2.setEntity(new UrlEncodedFormEntity(var4));
var6 = var5.execute(var2);
이러한 코드가 있습니다. 즉 username이 devadmin이면 /devlogin 요청을 보내는 처리 코드입니다. 그러면 한번 devadmin으로 로그인해보겠습니다.
로그인이 됨을 알 수 있습니다.
- 취약점 대응 방안
백도어 코드부분을 없애고 정상적인 로그인 로직만 남겨둡니다.
'Mobile App Penetesting > Android App Vulnerability' 카테고리의 다른 글
insecurebankv2 - 취약한 패스워드 변경 실행 (0) | 2023.06.05 |
---|---|
insecurebankv2 - 사용자 정보 목록 이슈화 (0) | 2023.06.03 |
insecurebankv2 - 하드코딩 보안 (2) | 2023.06.02 |
insecurebankv2 - 인자전달값 조작 (0) | 2023.06.01 |
insecurebankv2 - 안전하지 않은 HTTP 통신 (0) | 2023.05.29 |
Comments