网页读取器
1.介绍
1.1python代码审计
1.2ssrf白名单绕过
2.步骤
2.1下载附件进行python代码审计
from flask import Flask, render_template, request, send_from_directory import requests # well, requests is designed for humans, and I like it. app = Flask(__name__) whitelist_hostname = ["example.com", "www.example.com"] whitelist_scheme = ["http://"] def check_hostname(url): for i in whitelist_scheme: if url.startswith(i): url = url[len(i):] # strip scheme url = url[url.find("@") + 1:] # strip userinfo if not url.find("/") == -1: url = url[:url.find("/")] # strip parts after authority if not url.find(":") == -1: url = url[:url.find(":")] # strip port if url not in whitelist_hostname: return (False, "hostname {} not in whitelist".format(url)) return (True, "ok") return (False, "scheme not in whitelist, only {} allowed".format(whitelist_scheme)) ## for “遍历循环” 从变量结构中逐一提取元素,放到循环变量中。 startswith() 方法用于检查字符串是否是以指定子字符串开头,如果是则返回 True,否则返回 False。如果参数 beg 和 end 指定值,则在指定范围内检查。 len() 方法返回列表元素个数。 find() 方法检测字符串中是否包含子字符串 str ,如果指定 beg(开始) 和 end(结束) 范围,则检查是否包含在指定范围内,如果包含子字符串返回开始的索引值,否则返回-1。 python分片方法 str[i:j] 返回i-j的字符串 ## @app.route("/") def index(): return render_template("index.html") @app.route("/request") def req_route(): url = request.args.get('url') status, msg = check_hostname(url) if status is False: # print(msg) return msg try: r = requests.get(url, timeout=2) if not r.status_code == 200: return "We tried accessing your url, but it does not return HTTP 200. Instead, it returns {}.".format(r.status_code) return r.text except requests.Timeout: return "We tried our best, but it just timeout." except requests.RequestException: return "While accessing your url, an exception occurred. There may be a problem with your url." ## 当需要获取前端页面表单传过来的id值的时候,我们就需要用request.args.get ## @app.route("/source") def get_source(): return send_from_directory("/static/", "app.py", as_attachment=True) if __name__ == '__main__': app.run("0.0.0.0", 8080, debug=False)
首先判断url是不是以http://开头然后从这个地方截断,取后面的内容。
再判断是不是有 @取后面的内容进行判断,那我们其实可以把想访问的东西写在这里。
http://127.0.0.1/flag@example.com 这样他截断后去访问的都是后面的东西,可以通过白名单。
但是现在url是无效的,我们需要把后面的用#注释掉
最终payload:
http://127.0.0.1/flag#@example.com
2.2传入pyload,得到flag。
3.借鉴
Python3 startswith()方法 | 菜鸟教程 (runoob.com)
Python List len()方法 | 菜鸟教程 (runoob.com)
(17条消息) request.args.get()用法_yk 坤帝-CSDN博客_request.args
Python for 循环语句 | 菜鸟教程 (runoob.com)
Python find()方法 | 菜鸟教程 (runoob.com)
(17条消息) python的字符串分片_weixin_30477293的博客-CSDN博客
https://ce.pwnthebox.com/writeup?id=104