FourGoats Vulnerabilities: Intent Spoofing

The Android platform enables an inter application communication that can cause side effects in the security of our application. If a component allows any application to send him intents, we can end up being a puppet on any malware hands.

In order to prevent this situation, the Android platform enables two controls to limit who can talk to you application components. These controls are:

  • Permissions
  • Intents types

The first one is obvious, the component can request the calling application to present a specific permission in order to call your application.

The second one define two different type of intents:

  • Explicit intents are sent to an specific component and only delivered to him
  • Implicit intents request an action to be done and ask the system to look for the better component to perform that action. If the component is an Activity, the system will present the user a list with all the activities registered to handle that specific action. If the component is a service, it will be randomly delivered to any of them. Finally, if the component is a broadcast receiver, the system will deliver a copy to all of them.

One interesting fact is that any component is private by default. so far so good. Problems begin when a developer register a component to handle any implicit intent by declaring an intent-action. All of a sudden, that component will immediately become public with no notification to the developer. If the developer wants to keep that component private, he must declare explicitly that component as non exported.

Now, let have a look to the fourGoats app and check what applications are public. We can find three explicitly exported components:

android:label="@string/view_checkin" >

android:label="@string/profile" >

android:label="@string/authenticate" >

and if we look for implicitly exported components we will find another two:

<service android:name=".services.LocationService" >
<action android:name="" />

android:label="Send SMS" >
<action android:name="org.owasp.goatdroid.fourgoats.SOCIAL_SMS" />

As they (intentionally or not) declared public, lets see what can we do with them.


Reviewing the SocialAPIAuthentication activity, it seems that it present a login form to the user, performs the authentication and if its validated by the server, it returns a session token.

Now, let see how can we get a session token from any other app by presenting the user the same activity and ask him to enter its credentials:

<div id="file-a-java-LC1">Intent tokenIntent = new Intent();</div>
<div id="file-a-java-LC2">tokenIntent.setComponent(new ComponentName("org.owasp.goatdroid.fourgoats","org.owasp.goatdroid.fourgoats.activities.SocialAPIAuthentication"));</div>
<div id="file-a-java-LC3">startActivityForResult(tokenIntent, STATIC_INTEGER_VALUE);</div>

Now we need to handle the call back:

public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode) {
if (resultCode == Activity.RESULT_OK) {
Log.w("alvms", "4Goats SessionToken: " + data.getStringExtra("sessionToken"));

Ok, it doesn’t look a big deal since the malware app can also fake the login form and get the credentials if the user is willing to authenticate himself from another application, lets see another abuse case


Ok, so this receiver is registered to handle the action: org.owasp.goatdroid.fourgoats.SOCIAL_SMS but the developer forgot to declare the component as private so it will be automatically be registered in the system as public because it handles an implicit action.

So if its public, we can call it:

Intent broadcastIntent=new Intent();

And voila, we are sending an SMS from the user phone without him noticing.

If the developer meant this component to be public but protect it from being call from any application, he needs to declare a strong permission so only those apps with that permission granted can call that component.

You can find the intent spoofer client here:


FourGoats Vulnerabilities: Promiscuous SSL HostName Verifier

Continuing the previous post …

RestClient was getting an HttpClient instance using the CustomSSLSocketFactory.getNewHttpClient static method:

public static HttpClient getNewHttpClient() {
try {
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, null);
SSLSocketFactory sf = new CustomSSLSocketFactory(trustStore);
HttpParams params = new BasicHttpParams();
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
registry.register(new Scheme("https", sf, 443));

ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
return new DefaultHttpClient(ccm, params);
} catch (Exception e) {
return new DefaultHttpClient();

Can you spot another, related, vulnerability?

So either if we set up a secure TrustManager for the SSL Socket Factory using the default TrustManager that uses the Android KeyStore, we are setting its HostNameVerifier to ALLOW_ALL_HOSTNAME_VERIFIER.

So, again, if we have a legit certificate signed by any trusted CA (in the Android KeyStore) for our own domain, we will be able to use it to perform a man-in-the-middle attack since the SSL TrustManager will trust the certificate as it is signed by a trusted CA but then it will fail to verify that the certificate was issued for the server we are connecting to.

FourGoats Vulnerabilities: Promiscuous SSL TrustManager

The login activity uses an asynchronous task to validate the user credentials. The ValidateCredsAsyncTask performs this validation

private class ValidateCredsAsyncTask extends
AsyncTask<Void, Void, HashMap<String, String>> {

Login mActivity;

public ValidateCredsAsyncTask(Login activity) {
mActivity = activity;

protected HashMap<String, String> doInBackground(Void... params) {
LoginRequest client = new LoginRequest(context);
String userName = userNameEditText.getText().toString();
String password = passwordEditText.getText().toString();
boolean rememberMe = rememberMeCheckBox.isChecked();
HashMap<String, String> userInfo = new HashMap<String, String>();
if (allFieldsCompleted(userName, password)) {
UserInfoDBHelper dbHelper = new UserInfoDBHelper(context);
try {
userInfo = client.validateCredentials(userName, password);
if (userInfo.get("success").equals("false"))
userInfo.put("errors", Constants.LOGIN_FAILED);
else {
if (rememberMe)
saveCredentials(userName, password);
// our secret backdoor account
if (userName.equals("customerservice")
&& password.equals("Acc0uNTM@n@g3mEnT"))
userInfo.put("isAdmin", "true");
} catch (Exception e) {
userInfo.put("errors", Constants.COULD_NOT_CONNECT);
userInfo.put("success", "false");
Log.w("Failed login", "Login with "
+ userNameEditText.getText().toString() + " "
+ passwordEditText.getText().toString() + " failed");
} finally {
} else {
userInfo.put("error", Constants.ALL_FIELDS_REQUIRED);
userInfo.put("success", "false");

return userInfo;

protected void onPostExecute(HashMap<String, String> results) {
if (results.get("success").equals("true")) {
if (!previousActivity.isEmpty()) {
ComponentName toLaunch = new ComponentName(
"org.owasp.goatdroid.fourgoats", previousActivity);
Intent intent = new Intent();
} else if (results.get("isAdmin").equals("true")) {
Intent intent = new Intent(mActivity, AdminHome.class);
} else {
Intent intent = new Intent(mActivity, Home.class);
} else {
Utils.makeToast(context, results.get("errors"),

The doInBackground method will execute the task and the first thing it does is to get an instance of LoginRequest that will perform the validation, so lets take a look at this method:

public HashMap<String, String> validateCredentials(String userName,
String password) throws Exception {

RestClient client = new RestClient("https://" + destinationInfo
+ "/fourgoats/api/v1/login/authenticate");
client.AddParam("userName", userName);
client.AddParam("password", password);
client.Execute(RequestMethod.POST, context);

return LoginResponse.parseLoginResponse(client.getResponse());

It basically instanciates a RestClient that sends a POST request to a RESTful API to validate the credentials. The URL used states that it is using the SSL protocol to send the credentials out the wire (https://&#8221; + destinationInfo + “/fourgoats/api/v1/login/authenticate). So far so god, it looks secure! 🙂 or not?

Lets take a deeper look to the RestClient Class.

RestClient exposes a method to execute requests (execute) that basically wraps up the executeRequest method:

private void executeRequest(HttpUriRequest request, String url,
Context context) {

HttpClient client = CustomSSLSocketFactory.getNewHttpClient();
HashMap<String, String> proxyInfo = Utils.getProxyMap(context);
String proxyHost = proxyInfo.get("proxyHost");
String proxyPort = proxyInfo.get("proxyPort");

if (!(proxyHost.equals("") || proxyPort.equals(""))) {
HttpHost proxy = new HttpHost(proxyHost,
HttpResponse httpResponse;

try {
httpResponse = client.execute(request);
responseCode = httpResponse.getStatusLine().getStatusCode();
message = httpResponse.getStatusLine().getReasonPhrase();

HttpEntity entity = httpResponse.getEntity();

if (entity != null) {

InputStream instream = entity.getContent();
response = convertStreamToString(instream);

// Closing the input stream will trigger connection release

} catch (ClientProtocolException e) {
} catch (IOException e) {

We are using an HTTPClient to send the request but we are getting the HTTPClient from a custom SSLSocket Factory. This really start to smell relly bad. Custom SSL Socket Factory are words that we should not see in the same sentance!

And here things start looking pretty ugly.

CustomSSLSocketFactory is extending SSSocketFactory and initializating its SSLContext with a custom and promiscuous TrustManager:

public CustomSSLSocketFactory(KeyStore truststore)
throws NoSuchAlgorithmException, KeyManagementException,
KeyStoreException, UnrecoverableKeyException {

TrustManager tm = new X509TrustManager() {
public[] getAcceptedIssuers() {
return null;

public void checkClientTrusted([] chain, String authType)
throws {
// TODO Auto-generated method stub


public void checkServerTrusted([] chain, String authType)
throws {
// TODO Auto-generated method stub


sslContext.init(null, new TrustManager[] { tm }, null);

This TrustManager is not throwing any so it will trust any certificate presented making it useless to use SSL!

You can use any intercepting proxy and present any certificate to the application, FourGoats will trust it and send the credentials using your certificate through your proxy!

Unfortunately, this is something that happens quite often when developers start having problems with server certificates. After trying it a couple of times, some of them just give up and implement a trust-all trust manager.

You can find plenty of questions in StackOverflow asking how to trust any certificates:…

The good news is that you can also find good articles on how to use SSL properly to import your own certificates without ending up trusting everyone:…