처음 화면

URL을 자세히 보면 file 변수 값이 GET 방식으로 넘어간다는 것을 알 수 있고 file이라는 이름으로 전달된 파라미터 뒤에 .php가 자동으로 붙어 해당 내용을 회색 박스 내에 출력하고 있다.

 

file=index

 

file=flag

file에 flag를 넘겼을 때, FLAG is in the code라는 문자열이 보인다. code를 분석해야 한다.

파일 경로 취약점을 알아보기 위해서 ?file=../../../../../../etc/passwd 와 같이 입력해주었으나(LFI 공격)

이 ../ 명령어가 필터링이 되어 file=etc/passwd로 인식되어 해당 공격이 실패한다는 것을 알았다. 

 

 

이 이후로는 더 이상 해결방법을 모르겠어서 검색을 통해 이 문제에선 PHP wrapper를 이용한다는 정보를 알아냈다.

+) php가 버전 5 이상이 되면서 path 중간에 널바이트가 오면 주소를 더 이상 읽지 않는 취약점이 사라졌기 때문에 php wrapper를 사용하여 lfi 공격을 수행해야 하는 것이다.

 

◎ wrapper : 래퍼

래퍼는, 실제 데이터의 앞에서 어떤 틀을 잡아 주는 데이터 또는 다른 프로그램이 성공적으로 실행되도록 설정하는 프로그램이다.

php://filter wrapper
:: 다양한 I/O스트림을 다루는데 사용하는 wrapper 이다.
:: 사용자 입력과 같은 안전하지 않은 소스로부터의 데이타를 유효성 검사하여 필터링하는데 사용되는 방식이다.
이 wrapper를 사용할 때 우리는 encode/decode 옵션을 사용하여 서버 안에 존재하는 문서들을 열람할 수 있다.
ex) www.[우리가 공격할 웹 사이트의 주소].index.php?page=php://filter/convert.base64-encode/resource=/etc/passwd
처럼 활용할 수 있다.
위의 방식으로 공격을 진행하게 되면 우리는 base64 방식으로 인코딩 된 etc/passwd의 값을 얻을 수 있다.

출처 : https://opentutorials.org/module/4291/26819
참고 : https://www.php.net/manual/en/wrappers.php.php

 

http://webhacking.kr:10001/?file=flag

→ http://webhacking.kr:10001/?file=php://filter/convert.base64-encode/resource=flag

 

 

디코딩 결과

문제
페이지 소스코드

ck() 함수에서

세 개의 칸 모두 빈칸이면 안되며(20-22번째 코드) ,

23번째 줄에 나와있는 조건처럼 마지막 칸은 보이는 식별 문자와 같게 입력해야 한다.

 

 

빈 칸 입력
결과

너무 느리다고 한다...

저 time limit 2 second가 빈칸 입력 제한 시간을 나타낸 것 같다.

그럼 뭐 어떻게 입력하라는 ㄱ...

 

 

자바스크립트의 함수를 사용하는 페이지이므로 Console 창을 이용하면 될 것 같다.

 

처음 시도

처음엔 이런식으로 새로고침한 페이지에 나온 식별문자를 직접 입력해줬는데, 

계속해서 Too Slow... 페이지가 보였다. 

 

따라서 코드에 나와있는 대로 콘솔 창에 입력해보았다.

 

이렇게 아예 처음부터 입력받는 값과 나와있는 값을 같게 설정한다면?!

 

해결~

문제
페이지 소스코드

평범한 코드이다.

제출 클릭 시

you are not admin이라는 문자열이 뜨고 몇 초 후에 다시 메인 페이지로 돌아간다.

 

guest로 제출

guest를 입력해줬더니 hello guest라는 문자열이 보인다.

 

1234로 제출

 

제출한 값 그대로 나온다.

admin을 제외하고는 모두 이렇게 뜨는 것 같다.

 

하지만, logout을 눌러도 페이지에 변화가 없고,, 주소창도 그대로여서 쿠키를 확인해봤다. 

일반적으로 사용하는 PHPSESSID 말고 userid라는 쿠키가 있다.

 

들어있는 값을 URL 디코더로 돌린 후 %3D=를 의미한다는 것을 알았다.

어떠한 난독화된 값이 =로 끝난다면 이는 base64 로 인코딩된 것일 확률이 높다고 한다.

 

따라서 이것을 base64 방식으로 디코딩하려 했으나 오류만 나고,, 알 수 없는 문자열이 가득.. 

그래서 다시 처음부터 시작

 


 

id에 0을 입력

0을 입력했을 때는 URL 주소가 정상적으로 나타나지만 메인 페이지에 머물러 있다.

따라서 1을 입력해봤다.

 

id에 1을 입력
쿠키값 확인

비교적 짧은 쿠키값이 나왔다. 

이 또한 %3D로 끝난다. base64 방식으로 인코딩 된 것 같아서 base64 방식으로 디코딩해보았다.

 

base64로 디코딩

 

암호 알고리즘 별 해쉬값의 길이를 보니 (https://m.blog.naver.com/PostView.naver?blogId=thescream&logNo=220210025548&proxyReferer=https:%2F%2Fwww.google.com%2F)

 

32자리라면 MD5 해시값이라고 한다.

 

따라서 1을 MD5로 암호화해줬더니 

1을 MD5 방식으로 암호화한 결과

 


 

id에 11을 입력했을 떄의 쿠키값
이 쿠키값을 base64 방식으로 디코딩 한 결과

디코딩 한 결과, 앞서 봤던 1의 결과가 두번 연속으로 나타나는 것을 알 수 있다.

 

 

따라서 이 문제에선 입력한 문자열을 각각 MD5방식으로 암호화한 후, 

전체적으로 base64방식으로 또 한번 암호화하고 있다는 것을 알게되었다.

 

따라서 문제를 해결하려면

① admin 각 문자열에 대해 MD5로 암호화

② 합쳐서 base64로 암호화

③ 쿠키값에 이를 입력

하는 것이 좋겠다.

 

a → 0cc175b9c0f1b6a831c399e269772661

d → 8277e0910d750195b448797616e091ad 

m → 6f8f57715090da2632453988d9a1501b

i → 865c0c0b4ab0e063e5caa3387c1a8741

n →7b8b965ad4bca0e41ab51de7b31363a1

 

base64로 인코딩한 결과

 

이를 쿠키값에 입력할 때 주의할 점!
마지막 =는 %3D로 적어줄 것!!

 

해결~

 

문제
페이지 소스코드

소스코드를 간단히 요약하면

 

1. 우리가 입력하는 값은 'no'라는 이름으로 index.php에 GET 방식으로 넘겨진다.

2. 입력 시 공백  /   (   )   |    &   select   from   0x 문자열은 모두 걸러진다.

3. 우리가 입력하면 select id from chall18 where id='guest' and no=$_GET[no] 이 문장에 들어가게 된다.

 

1을 입력

1을 입력하니 hi guest 문자열이 뜬다.

우리는 admin의 no는 2라는 것을 알고 있다.

따라서 우리는 id가 admin이고 no=2일 때의 result가 나오게 하면 된다.

 

SQL 인젝션 공격으로 문제를 해결해보겠다.

 

where id='guest' and no=입력값

 

where 절에서 true와 false의 경우로 생각해보자.

 

TRUE and TRUE -> TRUE

TRUE and FALSE -> FALSE

TRUE or FALSE -> TRUE

(TRUE and FALSE) or TRUE -> TRUE

 

그러면 우리는 FALSE가 되게 하는 값을 입력해주고 or 로 TRUE 문을 연결해주면 되겠다.

 

입력 : 0 or no=2

 

하지만 이 문제에선 입력할 때 GET 방식으로 요청을 처리하고, 공백을 필터링 해주고 있으므로

URL 창에 입력 & 공백 자리는 URL 인코딩 방식으로 적어준다.

 

 

URL 인코딩 표 참고https://0x3700.tistory.com/entry/SQL-%EC%9D%B8%EC%A0%9D%EC%85%98-%EA%B3%B5%EB%B0%B1-%EC%9A%B0%ED%9A%8C-URL-Encode

:: 공백 문자 필터링 우회 시 %09를 사용한다.

 

 

문제
페이지 소스코드

unlock 변수에 정말 긴 값이 들어가 있다.

그리고 저 값을 빈 칸에 넣어주면 풀리는 문제이다.

 

 

콘솔 창 이용!!

콘솔 창을 이용하면 아무리 복잡한 계산도 단번에 가능하다.

해결

문제
페이지 소스코드

6) 일단, 움직이는 대상의 id가 star라는 점을 기억하자. 

 

18) kk() 함수 ~

Math.random() : 0 이상 1 미만의 난수 생성 

Math.floor() :  주어진 숫자와 같거나 작은 정수 중에서 가장 큰 수를 반환

--> 19번째 코드에서 색상을 나타내는데 쓰이는 6자리 숫자 만들기 위함

 

19) (x,y) 좌표에 랜덤의 색상을 가지는 * 모양 찍기

 

10) mv() 함수가 실행될 때마다 kk() 함수가 작동하여 해당 위치에 * 문자열을 찍게 된다.

9) mv() 함수를 이해하기 위해선 4번째 줄에 있는 onkeypress() 함수를 먼저 알아야 한다.

 

onkeypress(ASCII 값) : 사용자가 키보드를 눌렀을 때 해당하는 자바스크립트 수행

 

11) onkeypress에 들어가는 ASCII 값이 100 이라면? 이것은 키보드 'd'를 눌렀을 때를 의미

이러면 star의 left 좌표가 50px 씩 커지며 오른쪽으로 이동한다.

 

12) 키보드 'a'를 눌렀을 때

13) 키보드 's'를 눌렀을 때

14) 키보드 'w'를 눌렀을 때

 

이리저리 움직인 결과

 

그러면 우리는 ASCII 값이 124에 해당하는 키보드( | )를 눌러주면 문제를 해결할 수 있다.

 

 

문제
페이지 소스코드

12번째 줄부터 18번째 줄이 핵심이다.

13) ul 변수에 이 페이지의 URL을 넣고

14) ul 변수에 ".kr" 문자열이 처음 등장하는 인덱스를 넣고

15) ul 변수에 그 인덱스에 30을 곱한 값을 넣는다

16) 입력한 값과 ul이 같다면 풀리는 문제

 

URL 확인 후 pw 입력
해결

 

 

 

들어가자마자 alert 창이 뜬다

들어가자마자 Access_Denied라는 문자열을 띄우는 alert 창이 뜬다. 

클릭하면 Webhacking.kr 의 index 페이지로 넘어간다.

 

 

이는 alert를 띄우는 자바스크립트를 무력화시키면 되는 문제이다.

 

크롬 상단 메뉴
'자바스크립트' 검색 후 클릭
차단 목록에 추가

 

차단목록에 추가하면 아래와 같은 소스코드가 정상적으로 나온다.

페이지 소스코드

URL에 ?getFlag를 적으면 풀릴 것 같다.

 

성공

문제

 

페이지 소스코드 확인

놀리고 있는 것 같다.

 

<script> 태그 내에 아래와 같은 문자가 있다.

゚ω゚ノ= /`m´)ノ ~┻━┻ //*´∇`*/ ['_']; o=(゚ー゚) =_=3; c=(゚Θ゚) =(゚ー゚)-(゚ー゚); (゚Д゚) =(゚Θ゚)= (o^_^o)/ (o^_^o);(゚Д゚)={゚Θ゚: '_' ,゚ω゚ノ : ((゚ω゚ノ==3) +'_') [゚Θ゚] ,゚ー゚ノ :(゚ω゚ノ+ '_')[o^_^o -(゚Θ゚)] ,゚Д゚ノ:((゚ー゚==3) +'_')[゚ー゚] }; (゚Д゚) [゚Θ゚] =((゚ω゚ノ==3) +'_') [c^_^o];(゚Д゚) ['c'] = ((゚Д゚)+'_') [ (゚ー゚)+(゚ー゚)-(゚Θ゚) ];(゚Д゚) ['o'] = ((゚Д゚)+'_') [゚Θ゚];(゚o゚)=(゚Д゚) ['c']+(゚Д゚) ['o']+(゚ω゚ノ +'_')[゚Θ゚]+ ((゚ω゚ノ==3) 

자바스크립트가 난독화된 것 같다.

 

콘솔창에서 실행

이를 콘솔창에서 그대로 복붙하여 실행해주었다.

이렇게 하면 오류가 나는데, 마지막 ( '_' )

이 부분을 그냥 으로 고쳐서 입력하면 난독화 된 코드가 보인다.

 

해석된 코드

이를 더블클릭하여 함수를 확인해본다.

 

anonymous 함수

※ substr()

:: 파라미터로 입력받은 start index부터 length 길이만큼 string을 잘라내어 반환하는 함수

첫번째 글자의 index는 0에서 시작

 

※ indexOf()

:: 해당 문자열의 인덱스 값을 반환하는 함수

 

※ fromCharCode

:: 아스키코드 번호를 받아 문자열을 구성해주는 함수

 

※ charCodeAt

:: 주어진 인덱스에 대한 UTF-16(유니코드 문자 인코딩 방식의 하나)코드를 나타내는 0부터 65535 사이의 정수를 반환 /

문자열중 하나를 선택하여 아스키코드 번호로 변환해주는 함수

 


if(ck=="="+String.fromCharCode(enco_(240))+String.fromCharCode(enco_(220))+String.fromCharCode(enco_(232))+String.fromCharCode(enco_(192))+String.fromCharCode(enco_(226))+String.fromCharCode(enco_(200))+String.fromCharCode(enco_(204))+String.fromCharCode(enco_(222-2))+String.fromCharCode(enco_(198))+"~~~~~~"+String.fromCharCode(enco2)+String.fromCharCode(enco3)){
  location.href="./"+ck.replace("=","")+".php";

만약 ck 가 어떤 값이라면 ./어떤 값.php로 페이지가 이동하는 것을 알 수 있다.

 

 

콘솔 창의 편리함을 알 수 있는 문제,,!

더보기

Console

:: 실시간으로 자바스크립트를 실행하고, 에러 메시지등을 출력해주는 기능이다.

 

https://opentutorials.org/course/580/2872

 

console 창에 함수를 입력한 후 문자열을 해석해본다.

따라서 ck는 =youaregod~~~~~~~! 임을 알 수 있었다.

 

=를 NULL로 바꾼 후 URL 주소에 이를 입력해줬다.

 

성공

 

문제
페이지 소스코드

GET 요청시 val이라는 파라미터 안에 $pat 변수의 값을 넣어줘야 풀리는 문제이다.

 

$pat = /[1-3][a-f]{5}_.*$_SERVER[REMOTE_ADDR].*\tp\ta\ts\ts/

 

pat 변수는 정규표현식으로 나타나 있다.

 

[1-3] 은 1,2,3 문자 중 어떤 하나를 의미한다.

[a-f] 은 a,b,c,d,e,f 문자 중 어떤 하나를 의미한다.

{5} 는 앞에 나온 표현식을 5번 반복하라는 의미이다. (a,b,c,d,e,f 중 하나)

.* ~ .*는 .* 뒤에 0개 이상의 문자열을 .*이 나올 때 까지 반복하라는 의미이다.
\t 는 탭(tab)을 의미한다.

 

즉, 1aaaaa_IP주소(탭)p(탭)a(탭)s(탭)s 를 넣어주면 될 것 같다.

 

URL에 들어가는 특수문자는 URL 인코딩 방식된 형태로 넣어줘야 한다.

탭(\t)은 URL 인코딩하면 %09 이다.

 

+ Recent posts