天天看點

關于CVE-2017-8890的一點細節

因為有很多分析這個漏洞的文章是以我不詳細分析了,隻是總結要注意的細節,抛磚引玉。

感謝非常棒的幾篇文章:

  • https://www.freebuf.com/articles/terminal/160041.html
  • https://xz.aliyun.com/t/2383
  • https://xz.aliyun.com/t/2385

1. 如何用qemu+busybox搭建調試環境?

因為漏洞存在于核心的網絡實作,需要在menuconfig中進行一些額外的設定。詳情參考這篇文檔:基于virtio的網卡使用。

開啟虛拟機之後ifconfig lo up&ifconfig eth0 up啟動網卡。

2. ip_mc_socklist對象是如何被double free的?

通過兩次調用close最終調用到ip_mc_drop_socket中的kfree_rcu,使用RCU機制最終實作了ip_mc_socklist對象的釋放。

簡單來說:對于被RCU保護的共享資料結構,讀者不需要獲得任何鎖就可以通路它,但寫者在通路它時首先拷貝一個副本,然後對副本進行修改,最後使用一個回調機制在适當的時機把指向原來資料的指針重新指向新的被修改的資料。

這段等待的時間叫寬限期。如果每個CPU都經過一次搶占,就認為度過了寬限期。時鐘中斷處理函數會依次調用update_process_timers->rcu_check_callbacks->rcu_pending判斷,之後在invoke_rcu_core中調用軟中斷處理函數rcu_process_callbacks,然後依次調用__rcu_process_callbacks ->invoke_rcu_callbacks->rcu_do_batch->__rcu_reclaim調用回調函數head->func(head)。

3. 為什麼不能直接劫持ip_mc_socklist對象中的這個函數指針來劫持EIP?

因為kfree_rcu會依次調用__kfree_rcu->kfree_call_rcu->__call_rcu,在__kfree_rcu中func會被設定成該成員在對象中的偏移,最終在__call_rcu中再次指派給head->func。

#define kfree_rcu(ptr, rcu_head)                  \

    __kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head))
           
static void __call_rcu(struct rcu_head *head,

               rcu_callback_t func,

               struct rcu_ctrlblk *rcp)

{

    unsigned long flags;



    debug_rcu_head_queue(head);

    head->func = func;

    head->next = NULL;



    local_irq_save(flags);

    *rcp->curtail = head;

    rcp->curtail = &head->next;

    RCU_TRACE(rcp->qlen++);

    local_irq_restore(flags);



    if (unlikely(is_idle_task(current))) {

        /* force scheduling for rcu_sched_qs() */

        resched_cpu(0);

    }

}
           

是以需要一個多線程在__rcu_reclaim執行前再次修改ip_mc_socklist對象中的函數指針,但是我們并不能通路到堆噴的核心對象。剛好ip_mc_socklist對象的前8個位元組是next_rcu指針,該指針指向rcu連結清單中的下一個ip_mc_socklist對象。可以通過僞造next_rcu指針使其指向我們在使用者空間僞造的ip_mc_socklist對象,然後再通過僞造使用者空間對象的函數指針來劫持EIP。

關于CVE-2017-8890的一點細節

4. 如何尋找堆噴的對象?

ip_mc_socklist對象大小是0x30位元組,由于slab配置設定機制是以需要找到在核心中穩定配置設定0x40位元組大小并且能夠控制配置設定内容的方法。首先想到的是類似的ipv6_mc_socklist對象。這個對象不合适的話可以從sock_kmalloc入手尋找調用鍊,最終找到适合的對象(這裡采用的是ip_mc_source中的sock_kmalloc)。

關于CVE-2017-8890的一點細節

在找到可能合适的對象之後還需要調試觀察對象中是否包含其它幹擾核心執行流程的資料,資料是否可控或者是固定的。一時找不到合适的對象也可以通過修改核心源碼的方法強行構造出合适的對象,這就是源碼在手的好處。

5. 為什麼建立堆噴的socket會失敗?

linux系統對于每個程序可以打開的檔案數目是有限制的,可以通過ulimit -n修改,不過修改是需要root權限的。

6. 為什麼堆噴時setsockopt會傳回-1?

系統提示的錯誤資訊是no such device。

關于CVE-2017-8890的一點細節

這和目前的網絡配置有關,因為系統中沒有路由表,route add default gw 127.0.0.1即可。

7. 為什麼不能調用commit_creds(prepare_kernel_cred(0))提權?

在commit_creds前面的注釋中有一句:Install new credentials upon the current task。在代碼中也是通過current宏擷取目前task然後擷取cred的。因為前面說了ip_mc_socklist對象的真正釋放是在核心軟中斷進行中,不處于exp程序的上下文,是以這種方法并不能成功。可以修改exp程序的cred結構體來達到提權目的。

8. 剩下的ROP繞過SMEP這些都是正常操作了,不再展開。

最後給出qemu模拟環境kernel4.10.6下繞過SMEP提權的代碼和截圖,也是東拼西湊沒啥技術含量。還是有一些時候會崩掉的,不過我不想浪費時間再完善它了。

關于CVE-2017-8890的一點細節

代碼:

https://github.com/houjingyi233/my-exploits/blob/master/CVE-2017-8890/exp-with-smep.c

關于CVE-2017-8890的一點細節

- End -

關于CVE-2017-8890的一點細節

看雪ID:houjingyi                              

https://bbs.pediy.com/user-734571.htm

本文由 houjingyi 原創

轉載請注明來自看雪社群

關于CVE-2017-8890的一點細節

熱門圖書推薦:

關于CVE-2017-8890的一點細節

 立即購買!

熱門技術文章推薦:

  • 看雪CTF.TSRC 2018 團隊賽 第十題『俠義雙雄』 解題思路

  • 從更新檔到Root——CVE-2014-4323分析

  • 看雪CTF.TSRC 2018 團隊賽 第九題『諜戰』 解題思路

  • CVE-2014-6332學習筆記

關于CVE-2017-8890的一點細節

公衆号ID:ikanxue

官方微網誌:看雪安全

商務合作:[email protected]