generate_badge.php 소스코드다
<?php
include './db/lib.php';
session_start();
if (!isset($_SESSION['username'])) {
header("Location: login.php");
exit();
}
function generateRandomKey($length = 32) {
return bin2hex(random_bytes($length / 2));
}
if ($_SERVER["REQUEST_METHOD"] == "POST") {
if (!isset($_POST['password']) || empty($_POST['password'])) {
header("Location: generate_badge.php");
exit();
}
$username = $_SESSION['username'];
$password = $_POST['password'];
$stmt = $pdo->prepare("SELECT password FROM users WHERE username = ?");
$stmt->execute([$username]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$user || ($password!==$user['password'])) {
echo "<script>alert('Wrong password.....');location.href='/generate_badge.php';</script>";
exit();
}
$stmt = $pdo->prepare("SELECT COUNT(*) FROM dreambadge WHERE username = ?");
$stmt->execute([$username]);
$badgeExists = $stmt->fetchColumn();
if ($badgeExists > 0) {
$stmt = $pdo->prepare("SELECT badge_key FROM dreambadge WHERE username = ?");
$stmt->execute([$username]);
$badgeKey = $stmt->fetchColumn();
setcookie('key', $badgeKey, time() + 3600, "/");
echo "<script>alert('your badge already exists!');location.href='/view_badge.php';</script>";
exit();
}
$badgeName = $username . "_badge";
$accessKey = generateRandomKey();
$stmt = $pdo->prepare("INSERT INTO dreambadge (username, badge_name, badge_key) VALUES (?, ?, ?)");
$stmt->execute([$username, $badgeName, $accessKey]);
setcookie('key', $accessKey, time() + 3600, "/");
echo "<script>alert('Success!');location.href='/view_badge.php';</script>";
exit();
}
?>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>Create Dream Badge</title>
<link rel="stylesheet" href="/static/css/generate_badge.css">
</head>
<body>
<div class="container">
<h1>Create Dream Badge</h1>
<p>Dream Badge를 발급하시려면 비밀번호를 입력하세요.</p>
<form action="" method="POST">
<input type="password" name="password" placeholder="비밀번호" required>
<button type="submit">Create</button>
</form>
</div>
</body>
</html>
function generateRandomKey($length = 32) {
return bin2hex(random_bytes($length / 2));
}
뱃지 비번은 랜덤한 16진수 키를 생성하는 함수 (이건 못맞출뜻)
$badgeName = $username . "_badge";
$accessKey = generateRandomKey();
$stmt = $pdo->prepare("INSERT INTO dreambadge (username, badge_name, badge_key) VALUES (?, ?, ?)");
$stmt->execute([$username, $badgeName, $accessKey]);
setcookie('key', $accessKey, time() + 3600, "/");
echo "<script>alert('Success!');location.href='/view_badge.php';</script>";
exit();
}
🔍 코드 설명: 사용자 뱃지 생성 및 쿠키 설정
이 PHP 코드의 목적은 사용자에게 랜덤한 badge_key(뱃지 키)를 생성하여 데이터베이스에 저장하고, 쿠키에 설정하는 것이야.
이를 통해 사용자는 로그인 후 특정 뱃지를 보유할 수 있고, 해당 뱃지의 키를 사용하여 인증할 수 있음.
📌 코드 분석
$badgeName = $username . "_badge"; // 사용자 뱃지 이름 생성
$accessKey = generateRandomKey(); // 랜덤한 뱃지 키 생성
- $badgeName → 사용자($username)에 "_badge"를 붙여 뱃지 이름을 생성 (admin_badge 같은 형식).
- $accessKey → generateRandomKey() 함수를 호출하여 랜덤한 32자리 키를 생성.
🔹 1️⃣ 데이터베이스(dreambadge)에 뱃지 정보 저장
$stmt = $pdo->prepare("INSERT INTO dreambadge (username, badge_name, badge_key) VALUES (?, ?, ?)");
$stmt->execute([$username, $badgeName, $accessKey]);
- SQL 실행 방식 (prepare & execute)
- prepare() → SQL 쿼리를 미리 준비하고 보안적으로 안전하게 바인딩하는 방식 (SQL 인젝션 방어 가능).
- execute([$username, $badgeName, $accessKey]) → ?에 들어갈 값을 $username, $badgeName, $accessKey로 채움.
- dreambadge 테이블에 데이터 저장
- username → 사용자 이름
- badge_name → 생성된 뱃지 이름 (admin_badge 같은 형식)
- badge_key → 랜덤한 32자리 키 (보안 용도로 사용됨)
🔹 2️⃣ 쿠키(key) 설정
setcookie('key', $accessKey, time() + 3600, "/");
- 쿠키 이름: 'key'
- 쿠키 값: $accessKey (랜덤하게 생성된 badge_key)
- 쿠키 유효 시간: time() + 3600 → 1시간(3600초) 동안 유지
- 쿠키 경로: "/" → 웹사이트 전체에서 사용 가능
✅ 이렇게 하면 사용자가 브라우저에서 자동으로 해당 쿠키를 보유하게 되므로, 이후 페이지에서 인증할 때 이 쿠키를 확인할 수 있음.
🔹 3️⃣ 사용자에게 성공 메시지 출력 및 페이지 이동
echo "<script>alert('Success!');location.href='/view_badge.php';</script>";
exit();
- <script>alert('Success!'); → "Success!" 알림 메시지를 브라우저에서 띄움.
- location.href='/view_badge.php'; → 사용자를 /view_badge.php 페이지로 자동 리디렉션.
- exit(); → PHP 실행을 즉시 종료.
🚀 최종 코드 동작 과정
1️⃣ 사용자가 특정 동작(예: 버튼 클릭, 로그인 등)을 수행하면 이 코드가 실행됨.
2️⃣ 랜덤한 badge_key를 생성 (generateRandomKey()).
3️⃣ 사용자의 뱃지 정보를 dreambadge 테이블에 저장.
4️⃣ 사용자의 브라우저에 key라는 이름의 쿠키를 설정 (1시간 유지).
5️⃣ 성공 메시지를 띄우고 /view_badge.php로 이동.
🔥 결론
✅ 사용자에게 랜덤한 뱃지 키(badge_key)를 생성하여 데이터베이스에 저장
✅ 해당 키를 브라우저 쿠키(key)에 저장하여 이후 인증에 활용 가능
✅ 성공 메시지를 출력하고 /view_badge.php로 자동 이동
🚀 이제 해당 뱃지 정보를 /view_badge.php에서 확인할 수 있을 거야! 🎯
db 폴더의 lib.php 파일
<?php
$dbname = '/db/dreamdatabase.sqlite';
try {
$pdo = new PDO("sqlite:$dbname");
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->exec("
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT UNIQUE NOT NULL,
password TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS dreambadge (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT UNIQUE NOT NULL,
badge_name TEXT UNIQUE NOT NULL,
badge_key TEXT NOT NULL
);
INSERT OR IGNORE INTO users (username, password)
VALUES ('admin', '{{**REDACTED**}}');
INSERT OR IGNORE INTO dreambadge (username, badge_name, badge_key)
VALUES ('admin', 'admin_badge', '{{**REDACTED**}}');
");
} catch (PDOException $e) {
die("Database Failed: " . $e->getMessage());
}
?>
admin에 비번은 redacted라고 되어있음 redact - 기밀 혹은 민감한 내용을 지우다라고 사전 검색하니 나온다
알려줘요 비번...
register.php 파일을 살펴보자
회원가입할때 뭔가 꼼수가 있지않을까?
<?php
include './db/lib.php';
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$username = $_POST['username'];
$password = $_POST['password'];
$stmt = $pdo->prepare("SELECT COUNT(*) FROM users WHERE username = ?");
$stmt->execute([$username]);
$userExists = $stmt->fetchColumn();
if ($userExists > 0) {
echo "<script>alert('username already exists...'); location.href='register.php';</script>";
exit();
}
$stmt = $pdo->prepare("INSERT INTO users (username, password) VALUES (?, ?)");
if ($stmt->execute([$username, $password])) {
echo "<script>alert('Register Success!');location.href='login.php';</script>";
} else {
echo "<script>alert('Something Wrong....')</script>";
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Register</title>
<link rel="stylesheet" href="/static/css/register.css">
</head>
<body>
<div class="register-container">
<h2>회원가입</h2>
<form action="register.php" method="POST">
<input type="text" name="username" placeholder="아이디" required>
<input type="password" name="password" placeholder="비밀번호" required>
<button type="submit">회원가입</button>
</form>
</div>
</body>
</html>
그냥 평범한 회원가입 코드 같은데...
login.php 파일도 보자
로그인 할때 취약점이 있을 수 있으니..!
<?php
include './db/lib.php';
session_start();
$errorMessage = "";
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$username = $_POST['username'];
$password = $_POST['password'];
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ?");
$stmt->execute([$username]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if ($user && ($password === $user['password'])) {
if (isset($_COOKIE['key'])) {
setcookie('key', '', time() - 3600, '/');
}
$_SESSION['username'] = $username;
$stmt = $pdo->prepare("SELECT badge_key FROM dreambadge WHERE username = ?");
$stmt->execute([$username]);
$dreamBadge = $stmt->fetch(PDO::FETCH_ASSOC);
if ($dreamBadge) {
setcookie('key', $dreamBadge['badge_key'], time() + 3600, '/');
}
echo "<script>alert('Login Success!');location.href='/';</script>";
} else {
$errorMessage = "Wrong ID or Password.....";
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login</title>
<link rel="stylesheet" href="/static/css/login.css">
</head>
<body>
<div class="login-container">
<h2>로그인</h2>
<?php if ($errorMessage): ?>
<div class="error-message"><?php echo $errorMessage; ?></div>
<?php endif; ?>
<form action="login.php" method="POST">
<input type="text" name="username" placeholder="아이디" required>
<input type="password" name="password" placeholder="비밀번호" required>
<button type="submit">로그인</button>
</form>
</div>
</body>
</html>
....그냥 평범해보이는데...?
curl -b "PHPSESSID= efcb2c0d7f4c693fe0c659137202c5a7 " http://host1.dreamhack.games:18772/view_badge.php
Login
host1.dreamhack.games:18772
세션은 아니고...
C:\WINDOWS\system32>curl -s http://host1.dreamhack.games:18772/static/badge.png
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL was not found on this server.</p>
<hr>
<address>Apache/2.4.62 (Debian) Server at server Port 80</address>
</body></html>
캐싱도 아니야...
'Dreamhack > Dreamhack Wargame (Challenge)' 카테고리의 다른 글
[156] IT 비전공자 [dreamhack] baby-jwt문제풀기 (2) | 2025.02.13 |
---|---|
[155] IT 비전공자 [dreamhack]Simple Note Manager문제 풀기 (0) | 2025.02.12 |
[153] IT 비전공자 [dreamhack]INVERSE문제 풀기 (0) | 2025.02.10 |
[152] IT 비전공자 [dreamhack]Insecure Seed문제 풀기 (0) | 2025.02.10 |
[151] IT 비전공자 [dreamhack]Password in the gift box문제 풀기 (0) | 2025.02.10 |