app.post('/report',(req,res)=>{consturl=req.body.url;if(!checkUrl(url)){res.redirect('/?message=invalid argument');}elseif(unescape(url).indexOf('chart')!==-1){res.redirect('/?message=sorry, headchef doesn\'t like chart!');}elseif(!checkRateLimit(req.ip)){res.redirect(`/?message=rate limited`);}else{visitUrl(url).then(()=>res.redirect('/?message=reported'));}});
report page를 통해 전달된 url에 chart가 있으면 bot이 접속을 안한다. 하지만 chrome browser는 url에 포함된 tab, null문자를 무시하기 때문에 chart사이에 %09나 %00을 넣어주면 우회할 수 있다. 이전에 썻던 페이로드 그대로 가져와서 보내주니 플래그를 얻을 수 있었다.
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 쪽에서 가변변수를 사용하는 것을 확인할 수 있었다.
$netCancel은 우리가 컨트롤 할 수 있기 때문에 우리의 서버로 http request를 보내고 body data를 적절하게 잘 주면 echo할 때 flag를 출력시킬 수 있을 것이다.
가변 변수를 2번 사용하므로 $netcancelResultString에 처음엔 우리가 컨트롤 할 수 있는 변수명을 주고 이후에 가변변수를 사용할 때 flag값이 들어가게 하면 될 것 같다. try문에서 에러 발생은 잘못된 url을 줘서 http connect error를 트리거하면 된다.
예를 들어서 query는 insert into posts values (?, ?, ?, ?)와 같고 params는 [ noteId, title, content, login ]라 했을 때 title에 ?, content에 ||(select flag from flag),'1234')-- - 를 넣으면 return되는 query는 다음과 같다.
insert into posts values ("12341234", ""||(select flag from flag),'1234')-- - "", "test", ?)
이걸 이용하면 된다.
FLAG : hsctf{038d083216a920c589917b898ff41fd9611956b711035b30766ffaf2ae7f75f2}
잘보고갑니당