近期Android爆出SMS smishing vuln, 首先来源于http://www.csc.ncsu.edu/faculty/jiang/smishing.html, 然后github上给出了poc,具体来说是任意一个app在没有write_sms权限下可以伪造任意发件人的任意短信。

影响平台可上至Android 1.6下至4.1。由于很多以android2.3为主的手机已经不能再升级,此漏洞的危害不可小视。一个攻击场景是malicious app首先向ISP发送一条申请业务的短信,然后伪造ISP发送一条用户需要确认的短信。当用户确认时就中招了。

两张截图:

clip_image002 clip_image004

首先感谢各位大神的贡献。在github上给出poc后,我根据代码进行了一些分析。前面构造pdu的代码非常重要,但不是本文分析的重点。此次分析的POC代码在于

Intent intent = new Intent();

intent.setClassName("com.android.mms",

"com.android.mms.transaction.SmsReceiverService");

intent.setAction("android.provider.Telephony.SMS_RECEIVED");

intent.putExtra("pdus", new Object[] { pdu });

intent.putExtra("format", "3gpp");

context.startService(intent);

这里启动了com.android.mms.transaction.smsreceiverService,这个service的代码在这里. 当service启动时,调用链如下:

onStartCommand->mServiceHandler.sendMessage(msg);

消息进入ServiceHandler的消息队列中,在handleMessage中得到处理。由于Action是SMS_RECEIVED,所以进入handleSmsReceived函数:

public void handleMessage(Message msg) {

int serviceId = msg.arg1;

Intent intent = (Intent)msg.obj;

if (intent != null) {

String action = intent.getAction();

if (MESSAGE_SENT_ACTION.equals(intent.getAction())) {

handleSmsSent(intent);

} else if (SMS_RECEIVED_ACTION.equals(action)) {

handleSmsReceived(intent);

} else if (ACTION_BOOT_COMPLETED.equals(action)) {

handleBootCompleted();

} else if (TelephonyIntents.ACTION_SERVICE_STATE_CHANGED.equals(action)) {

handleServiceStateChanged(intent);

}

}

// NOTE: We MUST not call stopSelf() directly, since we need to

// make sure the wake lock acquired by AlertReceiver is released.

SmsReceiver.finishStartingService(SmsReceiverService.this, serviceId);

}

}

handleSmsReceived

private void handleSmsReceived(Intent intent) {

SmsMessage[] msgs = Intents.getMessagesFromIntent(intent);

Uri messageUri = insertMessage(this, msgs);

if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {

SmsMessage sms = msgs[0];

Log.v(TAG, "handleSmsReceived" + (sms.isReplace() ? "(replace)" : "") +

" messageUri: " + messageUri +

", address: " + sms.getOriginatingAddress() +

", body: " + sms.getMessageBody());

}

if (messageUri != null) {

MessagingNotification.updateNewMessageIndicator(this, true);

}

}

在291段用户得到通知,即一般大家看到的toast和短信提示框,再来看insertMessage,

private Uri insertMessage(Context context, SmsMessage[] msgs) {

// Build the helper classes to parse the messages.

SmsMessage sms = msgs[0];

if (sms.getMessageClass() == SmsMessage.MessageClass.CLASS_0) {

displayClassZeroMessage(context, sms);

return null;

} else if (sms.isReplace()) {

return replaceMessage(context, msgs);

} else {

return storeMessage(context, msgs);

}

}

其中replaceMessage最后调用storeMessage, storeMessage负责将短信存入数据库。这样一个fake message就成功以假乱真。

那为什么会出现这样的问题?对/system/app/Mms.apk进行反编译,获得AndroidManifest.xml,在其中可以看到:

<application android:label="@string/app_label" android:icon="@drawable/ic_launcher_smsmms" android:name="MmsApp" android:taskAffinity="android.task.mms" android:allowTaskReparenting="true">

<service android:name=".transaction.TransactionService" android:exported="true" />

<service android:name=".transaction.SmsReceiverService" android:exported="true" />

<activity android:theme="@android:style/Theme.NoTitleBar" android:label="@string/app_label" android:name=".ui.MmsTabActivity" android:launchMode="singleTop" android:configChanges="keyboardHidden|orientation" android:windowSoftInputMode="stateAlwaysHidden|adjustPan">

SmsReceiverService被export出去后没有使用permission声明signature或signatureOrSystem或Dangerous,甚至也没有Normal声明。在代码中也没有显式调用checkPermission,这违反了android开发规范[1],造成了事实上的permission-redelegation漏洞。由于Mms属于系统程序,存在于所有android-platform中,后果更加严重。

以上是对android的最新短信漏洞做的分析。由于水平所限,如果有所疏误请不吝赐教。

[email protected]

English version can be seen here:
http://blog.flanker017.me/?p=235&lang=en-us

源链接

Hacking more

...