format string 을 이용한 php sprintf 버그
오랜만에 CTF에 참가하여 WEB 문제 중, php의 `sprintf()` 함수를 이용한 문제가 있었다.
아래 코드를 보면, SQL `addslashes()` 함수 때문에 SQLI 가 불가능한 것처럼 보이지만, `sprintf()` 함수에서 format string을 이용하면 이를 bypass 할 수 있다. 이를 설명하기 위해 글을 계속 읽어보자.
<?php
error_reporting( E_ALL );
ini_set( "display_errors", 1 );
$user = sprintf("%s", addslashes($_GET["user"]));
$password = md5($_GET["password"]);
echo $user . "<br>";
echo sprintf("SELECT * FROM user WHERE user_id='$user' AND password='%s'", $password);
?>
아래 코드를 보면, $name 과 $money 변수의 값을 서식 문자로 받아 출력이 된다.
<?php
$name = "John";
$money = "500";
echo sprintf('The %s has %s dollar.', $name, $money);
?>
# The John has 500 dollar.
위 코드의 서식 문자를 아래 코드처럼 인자의 순서를 지정할 수 있다.
(이는 C언어에서 Format String Bug를 이용한 explit 할 때도 사용된다.)
<?php
$name = "John";
$money = "500";
echo sprintf('The %1$s has %2$s dollar.', $name, $money); # Change
?>
# The John has 500 dollar.
위 예제에서는 코드에 전혀 문제가 없다. 하지만 `sprintf()` 함수를 다음과 같은 사례로 2번 이상 사용하게 된다면 어떻게 될까
5번째 줄에서, `sprintf()` 함수의 결과를 `$user` 변수에 저장하고, 이를 9번째 줄에서 query 문에 사용된다.
<?php
error_reporting( E_ALL );
ini_set( "display_errors", 1 );
$user = sprintf("%s", addslashes($_GET["user"]));
$password = md5($_GET["password"]);
echo $user . "<br>";
echo sprintf("SELECT * FROM user WHERE user_id='$user' AND password='%s'", $password);
?>
만약 공격자가 user 파라미터에 `%s` 라는 문자열을 전송할 경우 서버는 다음과 같이 에러를 출력한다.
`sprintf()` 함수에서 인자의 개수가 작아서 발생한 에러이다.
즉, 서버 입장에서 보면 user 변수의 값이 %s 이므로 다음과 같은 코드가 동작하려가다 에러가 발생한 것이다.
echo sprintf("SELECT * FROM user WHERE user_id='%s' AND password='%s'", $password);
해당 에러를 발생시키지 않기 위해, 위에서 설명한 `%1$s` 를 사용하여 첫번째 인자를 사용하도록 만든다.
결국엔, user_id에는 password 변수의 값이 들어간 것을 볼 수 있다.
바로 위에서 입력한 `%1$s` 에서 s만 빼고 `%1$` 만 입력 한다면, 신기한 결과를 얻을 수 있다.
$ 다음에는 s나 d와 같은 서식 문자의 정의가 있어야 하는데, 이러한 문자가 없어서 기존에 있던 싱글쿼터를 먹어버리게 된 것이다. 마찬가지로 \(역 슬레시) 문자도 먹어버린다.
위 상황을 이용하여 `%1$'` 라는 문자열을 전송하게 되면, 다음과 같이 `addslashes()` 함수로 역 슬레시가 붙어 있었지만, SQL query 문에서는 없어진 것을 볼 수 있다.
Reference
'🔒Security' 카테고리의 다른 글
nodejs express routing case sensitive options (0) | 2022.03.06 |
---|---|
java URL class를 이용한 내부 파일 읽기 (0) | 2022.03.02 |
Log4j 취약점(CVE-2021-44228) Log4Shell 발생 원인 및 실습 (0) | 2021.12.24 |
[CVE-2021-39350] wordpress FV flowplayer 분석 (0) | 2021.10.10 |
frida를 이용한 후킹 예제 (0) | 2021.07.30 |
댓글
이 글 공유하기
다른 글
-
nodejs express routing case sensitive options
nodejs express routing case sensitive options
2022.03.06 -
java URL class를 이용한 내부 파일 읽기
java URL class를 이용한 내부 파일 읽기
2022.03.02 -
Log4j 취약점(CVE-2021-44228) Log4Shell 발생 원인 및 실습
Log4j 취약점(CVE-2021-44228) Log4Shell 발생 원인 및 실습
2021.12.24 -
[CVE-2021-39350] wordpress FV flowplayer 분석
[CVE-2021-39350] wordpress FV flowplayer 분석
2021.10.10