正常的密码修改流程是"设置"->“安全”->“屏幕锁定”->“确认你的PIN”,如下:
![](http://imgq8.q578.com/ef/0925/c5e1f2558b4d734e.jpg)
如果利用攻击代码,即可跳过“确认你的PIN”直接进入“选择你的PIN”页面,如下:
![](http://imgq8.q578.com/ef/0925/f2fececce7a76758.jpg)
注:漏洞虽然修复了,但是修复能力主要依赖于开发人员的安全能力问题,这类问题在新版本上,依然存在
2.1 修复建议
- 如果应用的Activity组件不必要导出,或者组件配置了intent filter标签,建议显示设置组件的“android:exported”属性为false
- 重写继承子类的isValidFragment方法,验证Fragment来源的正确性
- 当targetSdk大于等于19时,强制实现了isValidFragment方法;小于19时,在PreferenceActivity的子类中都要加入isValidFragment ,两种情况下在isValidFragment方法中进行fragment名的合法性校验。
- isValidFragment(String fragmentName) 返回Boolean(子类应当重写这个方法,并对fragment进行校验判断)
public final class MyPreferenceActivity extends PreferenceActivity {
private boolean doValidcheck(String fragmentName) throws IllegalArgumentException {
// TODO 做合法性检查return true;// 注意check,千万要注意}
// 添加上这个方法,以使2.x~4.3的代码在4.4上可以正常运行
protected boolean isValidFragment(String fragmentName) {
return doValidcheck(fragmentName);
}@Overrideprotected void onCreate(Bundle savedInstanceState) {
// 在onCreate前就做合法性判断String
fragmentname = getIntent().getStringExtra(":android:show_fragment");
doValidcheck(fragmentname);
super.onCreate(savedInstanceState);
}
}
0x03 Android Fragment之拒绝服务
样本APK下载地址:https://github.com/AndroidAppSec/vuls/releases/tag/v4.2
由于通过该漏洞可以加载APP里面的任何类,包括未导出类,如果未导出类对畸形消息处理不当,将会导致本地拒绝服务漏洞。下面以vuls.apk为例
ddns.android.vuls.activities.Activity.FragmentActivity组件对外导出:
![](http://imgq8.q578.com/ef/0925/3c2c276481bf1a3d.jpg)
ddns.android.vuls.activities.Activity.FragmentActivity组件继承自PreferenceActivity:
public class FragmentActivity extends PreferenceActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
protected boolean isValidFragment(String fragmentName) {
Log.e("FragmentVuls", "fragmentName: " + fragmentName);
return true;
}
}
![](http://imgq8.q578.com/ef/0925/132557b0be114e13.jpg)
由于没有对Fragment注入漏洞进行防御,可通过该漏洞加载app内任意不导出的组件。选择com.irccloud.android.fragment.ServerReorderFragment作为攻击目标:
public class TargetFragment extends Fragment {
public TargetFragment() {
Log.e("DDNS: ", "TargetFragment's constructor");
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_target,null);
WebView webview = (WebView) view.findViewById(R.id.webview_fragment);
webview.getSettings().setJavaScriptEnabled(true);
webview.loadUrl(getActivity().getIntent().getDataString());
return view;
}
}