Shang
Blog 👨‍💻
  • 🌸Introduction
  • 💻WEB SECURITY
    • Research Vulnerability
      • 📲Server-side topics
        • 🔏API Testing
        • 🔏Race conditions
        • 🔏XML external entity (XXE) injection
        • 🔏Server-side request forgery (SSRF)
        • 🔏File upload vulnerabilities
        • 🔏Access control vulnerabilities and privilege escalation
        • 🔏Business logic vulnerabilities
        • 🔏OS Command injection
        • 🔏Directory traversal
        • 🔏Authentication vulnerabilities
        • 🔏SQL injection
      • 📱Client-side topics
        • 🔏DOM-based vulnerabilities
        • 🔏Cross-origin resource sharing (CORS)
        • 🔏WebSockets
        • 🔏Clickjacking (UI redressing)
        • 🔏Cross-site request forgery (CSRF)
        • 🔏Cross-site scripting(XSS)
      • 🌀Advanced topics
        • 🔐Web cache poisoning
        • 🔐HTTP request smuggling
        • 🔐Prototype pollution
        • 🔐Server-side template injection(SSTI)
        • 🔐Insucure deserialization
    • Learn Java Vulnerability
      • Intro & Setup
      • Java Reflection Part 1
      • Java Reflection Part 2
    • Research Documents
      • 🎯DNS Rebinding
      • 🍪Remote Code Execution - Insecure Deserialization
      • 🍪Remote Code Execution on Jinja - SSTI Lab
      • 🍪Exploit cross-site request forgery (CSRF) - Lab
      • 🍪Exploit a misconfigured CORS - Lab
      • 🍪Same Origin Policy (SOP) - Lab
  • 📝WRITE-UP CTF
    • CTF Competitions
      • 🔰[WolvCTF 2023] Writeup Web
      • 🔰[M☆CTF Training 2023] Writeup Web
      • 🔰[HackTM CTF 2023] Writeup Web
      • 🔰[Incognito 4.0 2023] Writeup Web
      • 🔰[LA CTF 2023] Re-writeup Web
      • 🔰[Dice CTF 2023] Writeup Web
      • 🔰[ByteBandits CTF 2023] Writeup Web
      • 🔰[Knight CTF 2023] Writeup Web
      • 🔰[Sekai CTF 2022] Writeup Web
      • 🔰[WRECK CTF 2022] Writeup Web
      • 🔰[Maple CTF 2022] Writeup Web
    • CTF WarGame
      • ✏️[Root me] Writeup Sever Side
      • ✏️Websec.fr
      • ✏️[Root me] Writeup XSS Challenge
    • [tsug0d]-MAWC
      • 💉TSULOTT
      • 💉IQTEST
      • 🧬TooManyCrypto
      • 🧬NumberMakeup
    • Pwnable.vn
Powered by GitBook
On this page
  • Mở đầu
  • JSON Web Token (JWT) - Introduction
  • JSON Web Token (JWT) - Weak secret
  • JWT - Revoked token
  • PHP - assert()
  • PHP - Apache configuration
  1. WRITE-UP CTF
  2. CTF WarGame

[Root me] Writeup Sever Side

PreviousCTF WarGameNextWebsec.fr

Last updated 2 years ago

Mở đầu

Đây là trang write up về challenges root me về sever side. Mặc dù hiện tại có rất nhiều người write up về root me nhưng mình vẫn muốn làm và write up lại để một phần nhớ kiến thức. Nó mang theo kiểu note là chính. [Mức độ Medium trở lên _ но не все]

JSON Web Token (JWT) - Introduction

Khi vào trang web chúng ta sẽ có một form đăng nhập như sau:

Ở đây chúng ta sẽ login như là khách, sau khi login được tài khoản khách chúng ta sẽ check cookie xem có gì.

Ở đây mình nhận ra cookie có sử dụng jwt, thì mình thử decode xem nó như nào.

Ở đây mình check tool jwt nhưng không thể có được secret nào nên mình set lại jwt bằng cách không sử dụng algorithm

Đoạn code trên sẽ như này:

Thay thế cookie hiện tại ta có flag

JSON Web Token (JWT) - Weak secret

Ở bài này như tiêu đề thì là weak secret mình có thẻ brute foce được secret.

Chúng ta truy cập /token có mã token như trên:

Ở đây mình có được secret bắt đầu encode một token với role:admin

Oke bay giờ post nó lên và thêm Authorization để xác nhận là xong.

JWT - Revoked token

Ở bài này cho sẵn code để phân tích.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from flask import Flask, request, jsonify
from flask_jwt_extended import JWTManager, jwt_required, create_access_token, decode_token
import datetime
from apscheduler.schedulers.background import BackgroundScheduler
import threading
import jwt
from config import *
 
# Setup flask
app = Flask(__name__)
 
#Creat key
app.config['JWT_SECRET_KEY'] = SECRET
jwtmanager = JWTManager(app)
blacklist = set()
lock = threading.Lock()
 
# Free memory from expired tokens, as they are no longer useful
def delete_expired_tokens():
    with lock:
        to_remove = set()
        global blacklist
        for access_token in blacklist:
            try:
                jwt.decode(access_token, app.config['JWT_SECRET_KEY'],algorithm='HS256')
            except:
                to_remove.add(access_token)
       
        blacklist = blacklist.difference(to_remove)
 
@app.route("/web-serveur/ch63/")
def index():
    return "POST : /web-serveur/ch63/login <br>\nGET : /web-serveur/ch63/admin"
 
# Standard login endpoint
@app.route('/web-serveur/ch63/login', methods=['POST'])
def login():
    try:
        username = request.json.get('username', None)
        password = request.json.get('password', None)
    except:
        return jsonify({"msg":"""Bad request. Submit your login / pass as {"username":"admin","password":"admin"}"""}), 400
 
    if username != 'admin' or password != 'admin':
        return jsonify({"msg": "Bad username or password"}), 401
 
    access_token = create_access_token(identity=username,expires_delta=datetime.timedelta(minutes=3))
    ret = {
        'access_token': access_token,
    }
   
    with lock:
        blacklist.add(access_token)
 
    return jsonify(ret), 200
 
# Standard admin endpoint
@app.route('/web-serveur/ch63/admin', methods=['GET'])
@jwt_required
def protected():
    access_token = request.headers.get("Authorization").split()[1]
    with lock:
        if access_token in blacklist:
            return jsonify({"msg":"Token is revoked"})
        else:
            return jsonify({'Congratzzzz!!!_flag:': FLAG})
 
 
if __name__ == '__main__':
    scheduler = BackgroundScheduler()
    job = scheduler.add_job(delete_expired_tokens, 'interval', seconds=10)
    scheduler.start()
    app.run(debug=False, host='0.0.0.0', port=5000)

Chúng ta sẽ phân tích đoạn code này như sau:

  1. Đoạn code trên có 3 hàm quan trọng đó là:

    • def delete_expired_tokens(): 
      #ở hàm này sẽ đưa các token hết hạn vào blacklist 
    • def login(): 
      #Ở đây yêu cầu login với user/pass là admin->sau khi login thì sẽ tạo ra một token có hiệu lực trong 3 phút ** 
    • def protected(): 
      #ở hàm này nếu xác thực được token mà token đó không ở trong blacklist thì sẽ có flag

** -> như đã nói ở trên rằng token sẽ có hạn là 3p nhưng có điều là khi token được tạo ra đã bị add vào blacklist.

Chú ý cách tạo token JWT header.payload.signature

Ở đây cần chú ý tới cách tạo ra signature:

data = base64urlEncode( header ) + “.” + base64urlEncode( payload )
hashedData = hash( data, secret )
signature = base64urlEncode( hashedData )

Ở đây theo gợi ý ở metarial trang root-me cho thì có thể bypass bằng cách dùng ký tự non-alphabet nhưng ở đây chúng ta thấy rằng signature được base64urlEncode() . Thì trong base64 thường có dấu = kết thúc ở cuối mà mình nhận ra dù bạn thêm hay bớt dấu = thì nó vẫn decode ra một giá trị.

Ví dụ như: aG9haG9uZ2Rv= và aG9haG9uZ2Rv đều decode ra hoahongdo

Oke bây giờ thêm Authorization header và thêm dấu = ở cuối JWT hoặc một non-alphabet như tiếng Nga(л), tiêng Trung...

PHP - assert()

Bài này có lỗ hổng LFI nhìn qua khi mình thử xem đọc được file passwd không thì nó hiện ra như này:

Ở đây hiện ra hai hàm assert() và strpos(). Trong đó hàm assert() kiểm tra đầu vào và trả về giá trị bool. Nếu kết quả là fallse thì nó sẽ thực hiện ném lỗi ra. Còn hàm strpos() dùng để tìm vị trí xuất hiện đầu tiên của chuỗi con trong chuỗi cha.

Chú ý rằng khi đúng tra truyền ../../../etc/passwd thì thấy rằng chúng ta có thể inject được dòng code.

Code PHP ở dòng có thể là:

assert("strpos('includes/$file.php', '..') === false") or die("Detected hacking attempt!");

Payload lúc này sẽ là: ','')+or+die(show_source('.passwd'));//

Lúc đó đoạn code:

assert("strpos('includes/','')+or+die(show_source('.passwd'));//.php', '..') === false") or die("Detected hacking attempt!");

PHP - Apache configuration

Mình dùng tool để brute foce secret mã trên:

Đối với hàm assert() thì có hai tham số assert( $assertion, $exception = ?): bool nếu mà nó check $assertion false thì sẽ ném ra $exception, còn đối với hàm cũng thể strpos( $str, $char, $position) .

📝
✏️
jwt
mixed
Throwable
Show_source file .passwd