[1]PendingIntent核心:异步激发intent
PendingIntent的理解:延迟执行intent
官方文档:PendingIntent By giving a PendingIntent to another application, you are granting it the right to perform the operation you have specified as if the other application was yourself (with the same permissions and identity). As such, you should be careful about how you build the PendingIntent: almost always, for example, the base Intent you supply should have the component name explicitly set to one of your own components, to ensure it is ultimately sent there and nowhere else.
大意:应用A将PendingIntent发送给应用B让应用B以应用A自己的权限和身份执行指定的操作(Intent),即B此时有了越权操作,是A赋予的
- 根据官方文档的介绍可以想到,当我们拿到PendingIntent,修改了其中的Intent(PendingIntent本质上只是延迟激发intent),就可以用他的权限来开那些未导出的活动、服务、广播
官方文档:intent.fillIn Copy the contents of other in to this object, but only where fields are not defined by this object. For purposes of a field being defined, the following pieces of data in the Intent are considered to be separate fields:
大意:将other的内复制到这个对象中,但是要求这个对象内的字段为空。
- intent.fillIn方法:
大部分属性字段 只有原始intent的mAction为空或者设置的flags不为0才可以覆盖,有两个比较特殊mComponent 、mSelector 必须设置标志flags才可以修改,但是一般开发人员不会主动设置。所以出现几种情况:
- 双空(mAction、mComponent为空),可以给intent赋值,启动特定组件
- 更改可以更改的属性,故意造成数据异常,可以实现拒绝服务等其他行为
@FillInFlags
public int fillIn(@NonNull Intent other, @FillInFlags int flags) {
int changes = 0;
boolean mayHaveCopiedUris = false;
if (other.mAction != null
&& (mAction == null || (flags&FILL_IN_ACTION) != 0)) { //只有原始intent的mAction为空或者设置的flags不为0才可以覆盖
mAction = other.mAction; //other是用来改变原始intent内容的
changes |= FILL_IN_ACTION;
}
if ((other.mData != null || other.mType != null)
&& ((mData == null && mType == null)
|| (flags&FILL_IN_DATA) != 0)) {
mData = other.mData;
mType = other.mType;
changes |= FILL_IN_DATA;
mayHaveCopiedUris = true;
}
if (other.mCategories != null
&& (mCategories == null || (flags&FILL_IN_CATEGORIES) != 0)) {
if (other.mCategories != null) {
mCategories = new ArraySet<String>(other.mCategories);
}
changes |= FILL_IN_CATEGORIES;
}
.........
// Selector is special: it can only be set if explicitly allowed,
// for the same reason as the component name.
if (other.mSelector != null && (flags&FILL_IN_SELECTOR) != 0) {
if (mPackage == null) {
mSelector = new Intent(other.mSelector);
mPackage = null;
changes |= FILL_IN_SELECTOR;
}
}
.........
// Component is special: it can -only- be set if explicitly allowed,
// since otherwise the sender could force the intent somewhere the
// originator didn't intend.
if (other.mComponent != null && (flags&FILL_IN_COMPONENT) != 0) {
mComponent = other.mComponent;
changes |= FILL_IN_COMPONENT;
}
return changes;
}
实例1:android 4.4.2中系统settings->addAccount()存在"双空"PendingIntent的漏洞
我们应该知道的:除了人工点击settings->添加账户来触发addAccount()方法
![](https://img.haomeiwen.com/i13671484/209838883d7b48b0.png)
settings已经提供了接口让我们,在代码里就可以触发申请添加账户
源码位置:/packages/apps/Settings/src/com/android/settings/accounts/AddAccountSettings.java
178 @Override
179 protected void onSaveInstanceState(Bundle outState) {
180 super.onSaveInstanceState(outState);
181 outState.putBoolean(KEY_ADD_CALLED, mAddAccountCalled);
182 if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "saved");
183 }
184
185 private void addAccount(String accountType) {
186 Bundle addAccountOptions = new Bundle();
187 mPendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(), 0); //双空PendingIntent出现的地方
188 addAccountOptions.putParcelable(KEY_CALLER_IDENTITY, mPendingIntent);
189 addAccountOptions.putBoolean(EXTRA_HAS_MULTIPLE_USERS, Utils.hasMultipleUsers(this));
190 AccountManager.get(this).addAccount(
191 accountType,
192 null, /* authTokenType */
193 null, /* requiredFeatures */
194 addAccountOptions,
195 null,
196 mCallback,
197 null /* handler */);
198 mAddAccountCalled = true;
199 }
200}
Questions:
- 怎么由PendingIntent对象修改intent对象
[Anwser] intent.fillIn - 没有找到AddAccountSettings.java类在哪里定义导出?
[Anwser] 源码位置:/packages/apps/Settings/AndroidManifest.xml
<activity android:name="com.android.settings.accounts.AddAccountSettings"
android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:configChanges="orientation|keyboardHidden|screenSize"
android:label="@string/header_add_an_account"
android:taskAffinity="com.android.settings"
android:parentActivityName="Settings$ManageAccountsSettingsActivity">
<intent-filter> //有意图过滤intent-filter但是没有android:exported="false"就是默认可以导出
<action android:name="android.intent.action.MAIN" />
<action android:name="android.settings.ADD_ACCOUNT_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
网友评论