Thursday, January 5, 2017

SANS Holiday Hack 2016-Debug/Dev Server

Debug/Dev Server

Goal:

Retrieve discombobulated audio file 4.

Tools:

Android Studio
Android Emulator
Apktool
JadX
jarsigner.exe
jartool.exe
Firefox Developer Tools or Burp
Wireshark &/or TCPDump

OS:

Microsoft Windows 10 host-to run Android Studio and Android Emulator, apktool, jarsigner.exe, & jartool.exe
Kali Linux VM-to use JadX, Firefox Developer Tools, & Burp

Disassemble the apk with preferred tools:

JadX
  
Make sure to use whatever path that you used that contains the apk.
/jadx/build/jadx/bin/jadx <path to apk>
Example:
/jadx/build/jadx/bin/jadx SantaGram_4.2.apk

Reverse engineer the apk to find the code for the dev server.  The following was done in JadX.

The url that needed to be tested was found in the Resources>resources.arsc>values>strings.xml. The url is dev.northpolewonderland.com/index.php.   The strings.xml are strings that are used throughout the app programs.  If the strings need to be changed or updated, having a centralized location to change them makes it easier because instead of having to change a string in every program, they just change it in one place.  There is a string name, “debug_data_enabled”.  The “debug_data_enabled” string was set to false to begin with.  If the “debug_data_enabled” string is set to true, it allows the device to do remote debugging.  That can be confirmed by looking at the debug code.  The debug code was found in “com.northpolewonderland.santagram.EditProfile”.

protected void onCreate(Bundle bundle) {
        boolean z;
        super.onCreate(bundle);
        setContentView((int) R.layout.edit_profile);
        super.setRequestedOrientation(1);
        b.a(getApplicationContext(), getClass().getSimpleName());
        if (getString(R.string.debug_data_enabled).equals("true")) { //if the debug_data_enabled string is true
            Log.i(getString(R.string.TAG), "Remote debug logging is Enabled”);  //Remote debug logging is Enabled
            z = true;  //z is the boolean value-couldn’t use the string because strings and booleans don’t compare 
            correctly.  //booleans mean 1 or 0, on/off, true/false, strings are a sequence of characters, so true is not     
            the same as “true”.
        } else { //else, meaning if anything else-like false for instance,
            Log.i(getString(R.string.TAG), "Remote debug logging is Disabled”);  //Remote debug logging is Disabled
            z = false;
        }

The debug code describes how debug data is sent to the server.  The debug code must be sent to the server via a POST request, with the Content-Type set to application/json.  There are certain parameters that may be set.  The only parameter that seems to matter is the “debug” parameter. The server doesn’t seem to care what is in the other parameters. 

        if (z) { //meaning if true
            try { //try
                final JSONObject jSONObject = new JSONObject(); //create a JSON Object
//Put the date, udid, area that needs debugging, total mem-freemem names in the JSON object that     
               was just created and their corresponding values.  The date also has a formatter.  It just makes sure that 
               the date looks pretty.
                jSONObject.put("date", new SimpleDateFormat("yyyyMMddHHmmssZ").format(Calendar.getInstance().getTime()));
                jSONObject.put("udid", Secure.getString(getContentResolver(), "android_id"));
                jSONObject.put("debug", getClass().getCanonicalName() + ", " + getClass().getSimpleName());
                jSONObject.put("freemem", Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory());
                new Thread(new Runnable(this) {
                    final /* synthetic */ EditProfile b;

                    public void run() {                      
b.a(this.b.getString(R.string.debug_data_collection_url), jSONObject); //get the debug_data_collection_url string and the data in the JSONObject
                    }
                }).start(); //send the debug JSONObject to the debug_data_collection url

Using apktool.  Disassemble the apk.

apktool d SantaGram_4.2.apk

Use Android Studio to look at the disassembled apk and to change the values of the strings.  JadX decompiles the apk to Java, which is more human readable.  The language used in apktool is closer to machine language.  It isn’t machine language, but it’s close.  It’s called smali.  Android Studio understands the apk when it is decompiled using apktool.

Find the strings.xml file.  In Android Studio, it was in res>values>strings.xml.

Change the value of the “data_debug_enabled” string to “true”.

Save the changes.  In Android Studio:  File>Save All

Recompile the apk

Note apktool will want the directory that the original apk is in, not the apk file itself.

apktool b <directory of app>
apktool b SantaGram

The new build will be in the SantaGram directory, in a new directory called “dist” SantaGram/dist

The manipulated apk will not run in an emulator until it has been signed.  Fortunately, the signature doesn’t have to be signed with a trusted key. It can self-signed.

Make a directory to store keys:

mkdir keys

Make new keystore.
Note:  The path may be different depending on where the keys were stored and where the newly created apk was placed.

“C:\Program Files\Java\jdk<your version>\bin\keytool.exe” -genkey -v -keystore keys\SantaGram.keystore -alias SantaGram -keyalg RSA -keysize 1024 -sigalg SHA1withRSA -validity 10000
Enter a keystore password:
Re-Enter new password:
Fill in the requested information or type enter to select the default “Unknown”
Create a new password for keystore, or press enter to accept the same password.

Sign the newly created apk

“C:\Program Files\Java\jdk<your version>\bin\keysigner.exe” -sigalg SHA1withRSA -digestalg SHA1 -keystore keys\SantaGram.keystore dist\SantaGram.apk SantaGram

Install a the new app on Android Emulator

The apk can be dragged onto Android Emulator, which will install it or it can be installed by typing adb install SantaGram.apk

Open Wireshark or tcpdump.  Set it to capture the traffic on the correct interface.  If in doubt, select any.  One can filter it afterwards.  The filter would be ip.addr == <ip of dev server>  One can get the IP by pinging the server, using nmap, looking it up on VirusTotal-take your pick.

Open the SantaGram app and navigate to the EditProfile portion of the app.

Note about Wireless Internet Connection:  If using a wireless access point-the emulated device may assume that there is a wired connection.  If there is trouble connecting, attempt to disabled the wired connection.

Wireshark or tcpdump should have captured traffic from the emulated Android device and dev.northpolewonderland.com/index.php.

Read the response from the server.  It should be noted that there is an extra parameter that was not in the EditProfile part of the app.  The parameter is the “verbose” parameter.  For the query from the emulated Android device to the dev server, the verbose parameter has been set to false. 
The emulated Android device doesn’t have to be used to send queries to the server.  Use a normal computer,  In Firefox, in Developer Tools, one may send a request to the server and capture the traffic in the Network portion of the tools.  Manipulate the request as follows:

Click on the request
Select Edit & Resend
Make certain that the url is http://dev.northpolewonderland.com/index.php?
Change the query type to POST
Change the Content-Type in the request header to application/json
Type in the request parameters with the addition of verbose set to true.

Example:

{“date”:”<any date here will do>”,”udid”:”<whatever tickles your fancy>”, “debug":"com.northpolewonderland.santagram.EditProfile, EditProfile”,”freemem”:<whatever you want>,”verbose":true}

Solution:

{“date”:”17760704000615+0000”,”udid”:”SomeGuy”, “debug":"com.northpolewonderland.santagram.EditProfile, EditProfile”,”freemem”:555555,"verbose":true}

Note:  “verbose”:true is not the same as “verbose”:”true”.  One is a boolean, the other is a string.  The server is expecting a boolean value.

When the verbose value is set the true, the server sends back an array of report names, including an mp3. 

The mp3 is debug-20161224235959-0.mp3.  Any browser capable of handling mp3s may be used to navigate to that report.  dev.northpolewonderland.com/debug-20161224235959-0.mp3.  The page plays the 3rd audio file.  In Firefox that audio may be saved by right-clicking, selecting “Save Audio As”, filling in the “Save-As”:name, “Where”:path and format:type of file information, and clicking the “Save” button.

Note:  Keep track of where the file is saved.  By default, it is usually saved to the Downloads file.

Mitigation:

Don’t have the remote debugging parameter located in the app itself.  Have that switch controlled server-side and restricted to only the devices that need it.
If management insists on having that parameter controlled in the app:
Make the server validate the request:
Make certain that the request is coming from a valid device. (assuming the app only runs on phones.)
Have strict types.  If the types do not match, drop the request.
If “verbose” is set to false, don’t send the “verbose” parameter back with the report data from the server side.

No comments:

Post a Comment