정말 고생했던 문제입니다.. 분명 150점 짜리이고 리메이크 되기전에 간단하게 풀었던 문제인데 몇시간을 투자해도 도저히 풀 수 없어서 그냥 rubiya님께 문의해서 힌트를 받아서 풀 수 있었습니다.. 때문에 이 문제 풀이는 접은글로 닫아두고 제가 rubiya님에게 받은 힌트를 보여드리겠습니다. 해당 힌트를 참고해서 풀어보시고 그래도 모르시겠다면 접은 글을 참고하시면 될것 같습니다.
이 문제는 PHP Wrapper 중 filter를 이용하면 풀 수 있습니다. filter의 기능중에 base64 인코딩 기능이 있는데 이를 이용해서 flag,php를 인코딩 시키면 저 텍스트 박스에 php 소스가 base64로 인코딩된 값이 출력됩니다. 해당 값을 decode하고 flag값을 인증하면 끝!
저는 이미 풀어져있는 문제라 후배 블로그에서 소스코드를 긁어왔습니다. extract 함수를 이용해 $_SERVER와 $_COOKIE를 가져오는데 두 변수는 PHP 예약 변수로 각각 서버(혹은 실행환경)의 정보를 담고 있는 배열과 쿠키의 정보를 담고 있는 배열입니다. 그 후 ip에 REMOTE_ADDR 값을, agent에 HTTP_USER_AGENT 값을 넣어줍니다.
그 뒤에 ip값을 특정 조건에 맞게 변환해준 뒤 해당 ip값이 127.0.0.1이면 solve를 호출하는 방식입니다. 이 문제의 취약점은 $_SERVER를 추출해온 뒤 $_COOKIE를 추출했다는 부분입니다. $_SERVER를 추출할때 REMOTE_ADDR값을 가져왔는데 $_COOKIE를 추출할때 쿠키 값에 똑같이 REMOTE_ADDR 값이 존재한다면 해당 값을 쿠키에 있던 값으로 덮어 씌웁니다.
대충.. 이런느낌?
위와 같은 취약점 때문에 쿠키값에 REMOTE_ADDR 값을 넣고 위의 조건에 맞춰서 127.0.0.1이 되게 만들어주면 됩니다.
unlock에 굉장히 복잡한 계산을 한 값을 넣고 sub함수에서 사용자가 텍스트 박스에 입력한 값과 unlock값을 비교하여 같다면 문제가 풀리는 방식입니다. 이 문제는 3가지 방식이 있는데 첫번째는 개발자 도구를 이용해 unlock값을 알아내는 방법이고 두번째는 함수를 재정의하는 방법이고 마지막은 직접 계산(...)하는 방법입니다. 세번째 방법은 생략하고 첫번째와 두번째 방법을 소개하겠습니다.
첫번째 방법
어차피 unlock값은 이미 페이지를 로드할때 다 계산되어 있으므로 바로 unlock을 입력해서 값을 확인하면 됩니다. 만약 확실한게 좋다고 하시는분은 소스 코드에서 unlock 연산 코드를 긁어와서 그대로 복붙해서 넣으시면 됩니다.
onkeypress를 통해 mv함수에 사용자가 입력한 키값을 넘기고 mv에서는 키값을 cd라는 변수에 받고 변수값에 따라 별의 위치를 움직입니다. 이때 100,97,119,115는 WASD의 아스키코드 값입니다. 그런데 딱 보면 알겠지만 아스키코드 값으로 124가 들어오면 별의 위치를 변경하는게 아니라 php파일로 이동합니다. 당연히 저게 solve와 관련된 php겠죠.
이 문제도 두가지 방법이 있습니다. 첫번째는 아스키코드 124에 해당하는 키 값을 입력해주는 방법이고 두번째는 개발자 도구를 이용하는 방법입니다. 둘중에 편한 방법으로 푸시면 됩니다.
첫번째 방법
구글에 아스키 코드 표를 검색하여 124의 값을 찾습니다. 위의 표를 참고하면 알 수 있듯이 | (파이프)입니다. 그래서 해당 문제의 페이지에서 Shift + \를 눌러주면 문제가 풀립니다.
ul에 URL값을 넣고 해당 값에서 .kr의 index값을 넣은 뒤 30을 곱해줍니다. 결국 텍스트 박스에 위의 연산을 끝낸 결과값을 넣고 check를 누르면 풀리는 문제입니다. 직접 다 계산하는 방법도 있겠지만 개발자 도구를 이용해 쉽게 푸는 방법이 2가지가 있습니다.
첫번째 방법
위와 같은 방법으로 콘솔에 똑같은 코드를 넣고 결과 값을 구하는 방법입니다. 직접 구하지 않고 편하게 구할 수 있고 코드가 어떻게 동작하는지 확인할 수 있는 장점이 있는 방법입니다.
두번째 방법
위와 같은 방법으로 ck함수를 재정의한 뒤 호출하는 방법이 있습니다. 편한 방법을 골라서 쓰면 됩니다.
코드가 조금 길지만 guest와 123qwe를 Base64로 20번 인코딩 해주고 인코딩된 값을 str_replace를 이용하여 코드에 맞게 치환해준 뒤 그걸 다시 원래대로 치환해준 다음 Base64로 20번 디코딩한 값이 admin, nimda 인지 체크하는 코드입니다. 그냥 id를 guest -> admin, pw를 123qwe -> nimda 로 변경해주고 위의 과정을 그대로 돌려줘서 나온 Base64값을 그대로 쿠키에 넣어주면 해결되는 문제입니다. 이 과정은 뭐 직접 php를 짜셔도 되고 파이썬으로 짜셔도됩니다.
기존의 Webhacking.kr 에서 리모델링(?)된 기념으로 All-Clear 도전하기. 리모델링도 됐겠다 새로운 계정을 파서 처음부터 해보기로 했습니다. 풀이 순서는 낮은 점수부터 높은 점수까지! 첫 문제는 old-15입니다. 클릭해보면 아래와 같은 화면을 볼 수 있습니다.
바로 Access_Denied를 뱉고 홈페이지로 돌아가는데 일단 소스코드를 살펴보겠습니다. 소스 코드를 살펴보는 방법에는 다양한 방법이 있겠지만 저는 주로 다음과 같은 방법을 사용합니다.
그냥 바로 Access_Denied alert창을 띄우고 location.href를 이용하여 webhacking.kr 홈페이지로 바로 이동하는 코드입니다. 그런데 그 바로 아래에 document.wirte("<a href=?getFlag>[Get Flag]</a>"); 가 있습니다. 해당 코드는 현재 페이지에 [Get Flag]라는 문자열을 출력해주고 해당 문자열에 ?getFlag로 이동하는 링크를 걸어줍니다. 아래의 예시를 보면 바로 이해되실겁니다.
그런데 alert후에 바로 홈페이지로 이동하게 만들어놔서 우린 위의 링크를 볼 수 없습니다. 하지만 우린 소스를 통해 주소를 알아냈으니 직접 접속해서 해결할 수 있습니다.