BINDER SECCTX PATCH ANALYSIS

在2019年初,Binder內核模塊中添加了一項新功能。 此修補程序允許在Binder事務中發送調用方SElinux上下文。 該功能實際上是CVE-2019-2023的修復程序。 此漏洞與不正確使用getpidcon函數有關,從而導致ACL繞過。

本文研究此修補程序的詳細信息及其對安全性的影響。

getpidcon ACL繞過

關於getpidcon()使用的問題在Android中由來已久。 Jann Horn的問題報告詳細說明了硬件服務管理器容易受到攻擊,並且由於使用了不安全的getpidcon() ,已經報告了幾個類似的錯誤。 正如Jann Horn在其問題之一中所解釋的,此功能不是獲取調用過程的SELinux上下文的安全方法:

這是有問題的,因爲只有在調用者知道$ pid最初引用的進程不能從殭屍過渡到死進程(通常是因爲它是$ pid的父級或ptracer getpidcon($pid)纔可以安全使用。調用者可以根據$ pid指向getpidcon()之後指向的進程的年齡,驗證$ pid引用的進程在$ pid引用正確的進程之前是否已經生成。 (同一件事幾乎適用於所有引用使用PID的進程的API。)

換句話說,存在競爭條件:給定pid引用的過程可以在接收到事務的時間與對getpidcon的調用之間進行更改。

解決此設計問題的一種乾淨方法是將SELinux上下文與活頁夾事務一起發送。 這就是我們今天將分析的補丁的目的。

補丁概述

補丁詳細信息可在lore.kernel.org找到 。 提交標題爲“創建節點標誌以請求發送者的安全上下文”。

讓我們分析此補丁的主要部分:

  // @@ -3020,6 +3027,20 @@靜態空值bind_transaction(struct bind_proc * proc,
     t- > 標誌 = tr- > 標誌;
     t- > 優先級 = task_nice(當前);
 + if (target_node && target_node- > txn_security_ctx) {
 + u32 secid;
 +
 + security_task_getsecid( proc- > tsk 和 secid);
 + ret = security_secid_to_secctx(secid, & secctx, & secctx_sz);
 + if (ret) {
 + return_error = BR_FAILED_REPLY;
 + return_error_param = ret;
 + return_error_line = __LINE__;
 + 轉到 err_get_secctx_failed;
 + }
 + extra_buffers_size + = ALIGN(secctx_sz, sizeof (u64));
 + }

 + if (secctx) {
 + size_t buf_offset = ALIGN( tr- > data_size, sizeof ( void * )) +
 + ALIGN( tr- > offsets_size, sizeof ( void * )) +
 + ALIGN(extra_buffers_size, sizeof ( void * )) -
 + ALIGN(secctx_sz, sizeof (u64));
 + char * kptr = t- > 緩衝區 -> 數據 + buf_offset;
 +
 + t- > security_ctx = ( uintptr_t )kptr +
 + binder_alloc_get_user_buffer_offset( & target_proc- > 分配 );
 + memcpy(kptr, secctx, secctx_sz);
 + security_release_secctx(secctx, secctx_sz);
 + secctx = NULL;
 + }

發送綁定程序事務時,內核會檢查目標進程是否需要SELinux上下文( target_node->txn_security_ctx )。 可以在綁定器對象初始化上使用標誌FLAT_BINDER_FLAG_TXN_SECURITY_CTX來指定此選項。

例如,硬件服務管理器啓用此功能:

  //platform/system/hwservicemanager/service.cpp
     int main () {
         // [...]

         sp < ServiceManager > 管理器 = 新 ServiceManager();
         setRequestingSid(manager, true);
     }

啓用此功能後,內核會增加extra_buffers_size的大小以在之後存儲安全上下文。 收到的交易如下:

 

活頁夾接收事務緩衝區

然後,接收者可以使用getCallingPid()檢索事務中的安全上下文。

  pid_t IPCThreadState :: getCallingPid() 常量
     {
         返回 mCallingPid;
     }

     // /platform/system/libhwbinder/IPCThreadState.cpp
     status_t IPCThreadState :: executeCommand( int32_t cmd)
     {
     // [...]
     structinder_transaction_data_secctx {
             struct binder_transaction_data transaction_data;
             binding_uintptr_t secctx;
     };

     binding_transaction_data_secctx tr_secctx;
     活頁夾數據 & tr = tr_secctx.transaction_data;

     如果 (cmd == ( int ) BR_TRANSACTION_SEC_CTX) {
         結果 = mIn.read( & tr_secctx, sizeof (tr_secctx));
     } 其他 {
         結果 = mIn.read( & tr, sizeof (tr));
         tr_secctx.secctx = 0 ;
     }
     // ...
     mCallingSid = reinterpret_cast < const char *> (tr_secctx.secctx);

漏洞1:整數溢出

快速瀏覽可以確定整數溢出。

  extra_buffers_size + = ALIGN(secctx_sz, sizeof (u64));

用戶通過BC_TRANSACTION_SG事務完全控制BC_TRANSACTION_SG 。 如果extra_buffers_size , tr->data_sizetr->offsets_size等於零,則以下指令將在t->buffer->data buf_offset t->buffer->data之前複製安全上下文( buf_offset爲負)。

  size_t buf_offset = ALIGN( tr- > data_size, sizeof ( void * )) +
                 ALIGN( tr- > offsets_size, sizeof ( void * )) +
                 ALIGN(extra_buffers_size, sizeof ( void * )) -
                 ALIGN(secctx_sz, sizeof (u64));
     char * kptr = t- > 緩衝區 -> 數據 + buf_offset;

     t- > security_ctx = (binder_uintptr_t)kptr +
         binding_alloc_get_user_buffer_offset( & target_proc- > alloc);
     memcpy(kptr, secctx, secctx_sz);

此漏洞被標識爲CVE-2019-2181並在提交0b0509508beff65c1d50541861bc0d4973487dc5中進行了修補 。

它已在2019年9月的Android安全公告中發佈.https: //source.android.com/security/bulletin/2019-09-01.html#kernel-components

漏洞2:安全上下文覆蓋

當綁定程序事務包含BINDER_TYPE_PTR對象時,內核會在extra部分複製發送方進程的緩衝區。 我們可以在上面看到,爲了存儲安全上下文,增加了extra_buffers_size 。 但是,內核不會在額外緩衝區中區分標準數據和安全上下文。 用戶可以製作一個綁定交易,該交易會覆蓋安全上下文。

BINDER_TYPE_PTR覆蓋安全上下文

這比getpidcon()競爭條件更容易繞過ACL!

此漏洞已通過名爲的提交進行了修補: 活頁夾:正確設置SG緩衝區的結尾

結論

Binder內核補丁的目的是提高安全性,並提供另一種方法來檢索調用進程的上下文,以避免使用getpidcon() 。

矛盾的是,最初的補丁程序版本增加了更多的安全漏洞,並使ACL旁路比以前的漏洞更容易!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章