Description

Category: Crypto/Web

Source: DEFCON CTF 2018 Quals.

Points: 104

Author: Jisoon Park(js00n.park)

Description:

There, I've said it…

http://ssat-ps.iptime.org:5101

samples.tgz

Write-up

(*. 문제 환경을 재구성하여 풀이하였습니다.)

주어진 압축 파일을 풀어보면 네 가지 파일이 있는데, pdf 파일 두개와 sign 파일 두개이다. pdf 파일은 ECHO 또는 EXECUTE로 시작하는 command를 담고 있고, sign 파일은 hex string이다.

문제 사이트에 들어가보면 payload에 대한 sign을 할 수 있는 부분과 sign된 payload를 실행할 수 있는 부분이 있다. 양쪽 모두 source code link가 제공되니 코드를 확인 해보자.

먼저, 서명을 생성하는 sign.php이다.

[...]

$file_info = $_FILES['userfile'];
check_uploaded_file($file_info);

$text = pdf_to_text($file_info['tmp_name']);
print "Extracted text: \"$text\"<br/>";

$execute_query = "EXECUTE ";
$echo_query = "ECHO ";
if (substr($text, 0, strlen($execute_query)) === $execute_query) {
  print "I don't sign EXECUTE commands. Go away.<br/>";
} else if (substr($text, 0, strlen($echo_query)) === $echo_query) {
  print "I'm OK with ECHO commands. Here is the signature: <br/>";
  $data = file_get_contents($file_info['tmp_name']);
  openssl_sign($data, $signature, $privkey);
  print bin2hex($signature);

[...]

pdf_to_text() 함수가 있는 것을 보면, sample로 주어진 것과 같은 pdf 파일을 입력으로 받아서 텍스트를 추출하는 것 같다. 그러고 난 다음에, command가 ECHO이면 sign을 생성해서 알려주고 EXECUTE이면 reject을 하도록 되어 있다. 그러니까, sign.php가 제공하는 기능은 ECHO command가 적혀있는 pdf 파일을 받아서 거기에 대한 sign을 생성해주는 것으로 생각된다.

다음은 execute.php를 살펴보자.

[...]

$data = file_get_contents($file_info['tmp_name']);
$signature = hex2bin($_POST['signature']);
if (openssl_verify($data, $signature, $pubkey)) {
  print 'Signature is OK.<br/>';
} else {
  die('Bad signature.');
}

$text = pdf_to_text($file_info['tmp_name']);
print "Text: \"$text\"<br/>";

$execute_query = "EXECUTE ";
$echo_query = "ECHO ";
if (substr($text, 0, strlen($execute_query)) === $execute_query) {
  $payload = substr($text, strlen($execute_query));
  print "About to execute: \"$payload\".<br/>";
  $out = shell_exec($payload);
  print "Output: $out";
} else if (substr($text, 0, strlen($echo_query)) === $echo_query) {
  $payload = substr($text, strlen($echo_query));
  print "About to echo: \"$payload\".<br/>";
  echo $payload;

[...]

pdf에서 command를 추출하는 부분은 sign.php와 동일하다. 다만, 추출 전에 file과 함께 입력받은 sign 값을 이용해서 서명을 검증하는 단계를 거치는 것과, 서명 검증에 성공한 경우 추출한 command를 실행해 주는 부분이 추가되어 있다.

이 문제를 풀 때는 pdf에 대한 서명을 생성하는 점에서 SHA1 collision을 이용한 문제임을 파악했다. (그 즈음에 SHA1 collision을 이용하는 CTF 문제가 몇 군데서 나왔었다.) SHA1 collision 문제임을 확인하기 위해서 php의 default signature scheme을 확인해 보았다.

역시나 default hash algorithm으로 SHA1을 사용하고 있었다.

이 문제를 해결하기 위해서는 ECHO 명령을 사용하는 pdf 문서 A와 그에 대한 sign을 생성하고, 문서 A와 동일한 sha1sum을 갖는 EXECUTE 명령을 사용하는 pdf 문서 B를 만들면 된다.

sha1 collision이 발표되고 난 후 이를 공격하기 위한 오픈소스도 여러개가 공개되었는데, 그 중에 하나를 사용하였다.

우선, echo 문서를 하나 만들고, EXECUTE ls -l . 을 수행하는 문서를 하나 만들어서 sha1sum이 동일하도록 하였다.

먼저 echo 문서를 대상으로 하여 sign을 생성하였다.

execute 문서를 echo 문서에 대한 sign과 함께 submit 하여 디렉토리의 파일 목록을 조회한 결과, flag 파일이 확인되었다.

동일한 방법으로 echo 문서 하나와 cat flag를 수행하는 execute 문서를 만들어 submit 한 결과 flag를 얻을 수 있었다.

Flag : OOO{phP_4lw4y5_d3l1v3r5_3h7_b35T_fl4g5}

'writeups > Crypto' 카테고리의 다른 글

Blind  (0) 2019.11.26
babyrsa  (0) 2019.11.26
Count me in  (0) 2019.11.26
Help Rabin  (0) 2019.11.26
Easy RSA  (0) 2019.11.25

+ Recent posts