본문 바로가기
Web/Burp Suite

Burp Suite: Server-side vulnerabilities (Part 1)

by secumark 2025. 6. 16.
728x90

Burp Suite을 운영하고 있는 Port Swiggger에도 academy 페이지가 있다. 여기 있는 Server-side Vulnerabilities를 공부해보기로 했다. 

 

출처: https://portswigger.net/web-security/learning-paths/server-side-vulnerabilities-apprentice

 

Server-side vulnerabilities - PortSwigger

Web Security Academy offers tools for learning about web application security, testing & scanning. Learn about a wide range of security tools & identify the very latest vulnerabilities.

portswigger.net

 

 

시작

 

 

Path Traversal (디렉터리 리스팅 취약점)

파일 시스템의 경로 조작을 통해 애플리케이션이 의도하지 않은 서버 내 파일에 접근하게 만드는 취약점으로 Directory Traversal 이라고도 한다. 주요 위협으로는 임의 파일 읽기, 애플리케이션 코드 및 데이터, 백엔드 시스템 접근용 자격 증명이 있다.

운영체제의 민감 시스템 파일(/etc/passwd 등), 임의 파일 쓰기 (일부 환경), 파일 내용 변경 → 애플리케이션 동작 변조, 악성 코드 삽입 → 서버 완전 장악 등의 결과를 낳게 됨

 

Path Traversal을 이용한 임의 파일 열람

<img src="/loadImage?filename=218.png">

 

/loadImage 엔드포인트가 filename 파라미터를 받아 내부적으로 /var/www/images/ 디렉터리에 붙여서 /var/www/images/218.png 파일을 읽어 반환

 

참고로 /loadImage는 클라이언트가 요청하는 주소라 디스크에 있는 파일 위치와는 상이함.. 코드가 filename 파라미터를 받으면 파일 시스템 경로 /var/www/images/218.png를 열어서 내용 반환하는 거임

>>

  • /loadImage 는 HTTP 요청을 처리하는 웹 애플리케이션의 주소(→ 엔드포인트)
  • /var/www/images/218.png 는 실제 서버 디스크상의 파일 위치

이미지를 반환할 때, 애플리케이션은 요청받은 파일 이름을 이 기본 디렉터리 뒤에 붙이고, 파일 시스템 API를 사용해 그 파일의 내용을 읽는다. 이때 파일시스템 API라는게 뭐냐면 파일 읽기·쓰기, 디렉터리 생성·삭제, 파일 존재 여부 확인 같은 파일 시스템 관련 작업을 코드로 수행하게 해주는 표준 함수들을 말함.
PHP의 file_get_contents()나 Python의 open()·read() 등이 filesystem API 에 해당함..

 

이 애플리케이션은 경로 탐색(path traversal) 공격에 대한 방어를 전혀 구현하지 않았기 때문에 공격자가 다음의 URL을 요청해 서버 파일 시스템의 /etc/passwd 파일을 가져올 수 있음.

 

https://insecure-website.com/loadImage?filename=../../../etc/passwd

 

218.png 파일이 /var/www/images 아래에 있으니까, ../../../ 세번 거슬러 올라간 후 최상위 root에서부터 재시작. /etc/passwd 파일 실행 가능

 

결국 다음과 같이 읽게 됨

/var/www/images/../../../etc/passwd

 

유닉스 계열 운영체제에서 /etc/passwd는 서버에 등록된 사용자 정보(id, password 등)가 담긴 표준 파일이지만, 공격자는 같은 방식을 써서 다른 임의의 파일도 얼마든지 가져올 수 있음.
윈도우 환경에서는 ../뿐 아니라 ..\ 형태도 경로 탐색 시퀀스로 유효함. 예를 들어, 윈도우 기반 서버를 노린 동등한 공격은 다음과 같다.

https://insecure-website.com/loadImage?filename=..\..\..\windows\win.ini

 

Lab

디렉터리 리스팅 취약점에 대한 실습을 진행해본다. /etc/passwd 파일을 실행하는 것이 목표

 

사진을 아무거나 눌러보면..

 

 

사진, 가격 및 설명 등이 나온다. 이때 url은 /product?productId=15다.

/var/www/html/productId=15 대충이런뜻이니까

productId=../../../etc/passwd로 공격해봤다.

 

 

invalid product ID라고 함.

 

 

burp suite의 proxy -> repeater를 통해 확인해봤다. get 요청 부분을 수정해 /etc/passwd라고 보내봤는데, 400 Bad Request가 떴다.

 

위에서 했던 방법대로 ../../../etc/passwd라고 날려봤는데 똑같이 400 Bad Request가 뜬다. 

 

자세히 보니까 이미지를 로딩하는 과정이 있었다. proxy에 가서, 다시 시도를 해봤다. forward를 몇 번 눌렀더니, 일단 productId 페이지로 이동을 한 후에 GET /image?filename=으로 이미지만 따로 받아오는 request가 또 있었던 것..

 

이때 /etc/passwd 파일을 읽어오면 된다.

 

대신 여기서 바로 읽을 수는 없고, http request에 가면 내가 수정한 request와 response 결과까지 알 수 있음.

 

 

※ 여기서 하나 궁금했던 거. 왜 브라우저에서 직접 보면 이렇게 깨진 이미지로만 나오고 /etc/passwd 파일을 실제로 볼 수 없을까? chatgpt에게 물어봤는데, Burp 에서는 Raw 응답을 텍스트로 볼 수 있지만, 브라우저는 Content-Type 대로 이미지만 렌더링하기 때문에 /etc/passwd 내용이 화면에 보이지 않는다고 한다.

 

Content-Type이 image/jpeg임. 

 

 

이렇게 깨져서 보이는.. 참고로 개발자 도구에서도 확인 가능하다. 


브라우저 개발자 도구 → Network 탭 에서 해당 요청을 클릭한 뒤 → Response 를 “Preview” 가 아니라 “Response” (이게 원시 텍스트로 보여줌) 를 선택하면 확인 가능하다고 함.

 

Access control

접근제어. 누가 어떤 자원에 접근할 수 있도록 제한하는 것. 웹 애플리케이션의 맥락에서는 접근 제어가 인증과 세션관리에 의존한다. 

인증: 사용자가 자신이 주장하는 사람이 맞는지 확인

세션관리: 동일한 사용자가 이후에 보내는 http 요청 식별

접근제어: 사용자가 수행하려는 행위가 허용된 것인지 확인

 

이 접근 제어가 제대로 작동하지 않으면, 치명적인 보안 취약점이 될 수 있다. 접근 제어의 설계와 관리는 기술적 구현뿐 아니라 비즈니스적, 조직적, 법적 제약까지도 함께 고려해야 한다. (휴먼 에러 발생 o)

 

constraints: 제약, 제한

 

Vertical privilege escalation

수직 권한 상승, 사용자가 원래 접근해서는 안 되는 기능에 접근하는 경우로, 관리자 권한이 없는 일반 사용자가 관리자 페이지에 접근해 일반 사용자 계정을 사용할 수 있는 경우 수직적 권한 상승에 해당한다.

 

수직 권한 상승은 application이 sensitive한 기능에 대해서 아무런 보호 조치를 하지 않았을 때 발생한다. 관리자 기능은 특정 링크에만 연결되어 있고, 일반 사용자 페이지에선 보이지 않는데 단순 url 입력으로 접근이 가능하다면 수직 권한 상승이 이뤄졌다고 할 수 있다. 

예)
https://insecure-website.com/admin

 

robots.txt 파일도 그 예? 

url이 직접적으로 노출되지 않았더라도 wordlist를 사용해서 brute-force 공격을 할 수도 있다. 

 

Lab

 

Disallow 부분에 /administrator-panel이 적혀있는 것을 확인했다.

/robots.txt를 지우고 administrator-panel을 입력했더니 다음과 같이 뜬다.

 

carlos 계정을 지웠더니 다음과 같이 LAB solved 완료.

 

Unprotected functionality

security by obscurity (은폐에 의한 보안)에 의해 민감 기능을 예상하기 어려운 수준으로 url에 숨겨서 감추기도 하는데, 이게 실질적으로 접근제어 역할을 하지는 않는다. (어떻게든 url 주소를 알아내면 끝이므로) 

 
https://insecure-website.com/administrator-panel-yb556

 

예를 들어 이런 url은 공격자가 guess할 순 없어도 애플리케이션에서 해당 url을 유출시킬 수도 있다.

 

JavaScript 코드에서 사용자 역할(role)에 따라 UI를 구성하는 코드가 있을 수 있다면 다음과 같을 것이다. 

 

<script> var isAdmin = false;
if (isAdmin) { ... var adminPanelTag = document.createElement('a');
adminPanelTag.setAttribute('href', 'https://insecure-website.com/administrator-panel-yb556');
adminPanelTag.innerText = 'Admin panel'; ... } </script>

 

isAdmin이 true이면 UI에 관리자 패널링크를 생성하는  스크립트다. 하지만 URL 자체로는 모든 사용자가 페이지 소스를 열거나 개발자 도구에서 확인할 수 있다. 

Lab

홈페이지 소스코드에서 관리자 url을 찾고, 그 url을 열어서 carlos를 삭제하는 것. 위에서 진행한 lab과 동일한 것이지만 방법이 조금 다르다. 내가 그 url을 찾아내는 것이 문제

 

소스코드는 burp suite 이용해도 되고, 그냥 개발자 도구 이용해도 된다. 

 

 

개발자 도구로 보는게 좀 불편하면 ctrl+u로 view source로 봐도 된다.

 

 

잘 찾아보면.. admin 페이지 관련 script가 보인다.

 

소스코드 읽을 줄을 몰라서 정리를 해봤다.

1. var adminPanelTag = document.createElement('a');
> document:  지금 보고 있는 웹페이지 전체
createElement('a'): 웹페이지에 'a'라는 태그를 새로 만듦 (a는 html에서 링크로 연결)
>> 여기까지가 웹페이지에 새 링크를 만들고 싶다는 뜻으로 해석

 

var adminPanelTag = ... 에서 var는 변수를 만들어서 이름을 붙임. 그 이름표에 적힌 이름이 adminPanelTag

 

--> 내가 만든 이 링크 이름이 adminPanelTag야~

 

2. adminPanelTag.setAttribute('href', '/admin-412ndo');

setAttribute: 속성을 설정한다는 뜻

attribute: 태그에 붙는 정보들

<a href="주소">text</a>에서 href="주소"가 속성이 됨,, 실제로 이동할 경로

a 태그에 href 속성 설정..

 

 

Solved!

 

Parameter-based access control methods

(파라미터 기반 접근 제어 방식)

일부 웹 애플리케이션은 사용자가 로그인할 때 사용자의 권한이나 역할을 결정하고, 이 정보를 사용자가 직접 수정할 수 있는 위치에 저장한다.

hidden field, cookie, query string parameter가 대표적인데, 아래와 같이 서버가 전달받은 값에 따라 접근 권한을 결정한다. 

 

https://insecure-website.com/login/home.jsp?admin=true  
https://insecure-website.com/login/home.jsp?role=1
 
그래서 사용자 권한 정보를 url 파라미터로 받는 방식은 보안상 취약하다고 할 수 있다. (사용자가 이 값을 직접 바꿀 수 있으므로) 

어떻게? 일반 사용자가 주소창에서 admin=false → admin=true로 바꾸거나 role=2를 role=1로 바꾸는 식으로
원래 접근할 수 없는 관리자 기능을 열람하거나 조작할 수 있게 됨. 그래서 안전한 조치는 서버 측에서 로그인하면 세션에 권한을 저장하고, 모든 요청마다 서버가 직접 검증해야 함. 민감한 기능은 role-based 접근 제어를 수행하면 된다. 

 

 

실습에서 제공한 일반 사용자 권한으로 로그인을 해봤다.

/admin으로 접속하니까 admin interface only available if logged in as an administrator라고 한다.

 

myaccount로 가서 개발자 도구 -> 네트워크 -> my-account?id=wiener -> 쿠키를 선택하면 

쿠키 요청에 admin과 session이 있는데, 값이 false인 것을 확인할 수 있다.

이 academyLabHeader에도 cookie 값에 admin=false인 것 확인 PortSwigger Web Security Academy에서 페이지 상단에 표시되는 헤더 UI 구성 파일이라 이건 무시해도 됨..

 

애플리케이션 탭의 쿠키로 가면 아까와 같은 cookie 값들이 있는 것을 확인할 수 있다. 여기서 admin의 false값을 true로 변경해주면 된다.

 

그리고 새로고침을 했더니 아까는 보이지 않던 admin panel이 생겼다.

 

/admin으로 접속이 가능하고, carlos 계정을 삭제할 수 있다.

 

Horizontal Privilege Escalation (수평적 권한 상승)

아까는 수직, 지금은 수평적 권한 상승이다.  사용자가 자신이 아닌 '다른 사용자'의 자원에 접근할 수 있는 경우 발생하는 취약점으로 "수평적" = 같은 권한 레벨 (예: 일반 사용자 → 다른 일반 사용자)에 해당

반대로 수직적(Vertical)은 일반 사용자 → 관리자 권한으로 상승하는 것.

https://insecure-website.com/myaccount?id=123 인데 이 id를 124로 변경한다든가.. 
-> 수평적 권한 상승이 발생

 

IDOR (Insecure Direct Object Reference)
= “안전하지 않은 직접 객체 참조” 취약점

말 그대로 검증 없이 직접 객체(계정, 파일 등)에 접근을 허용하는 구조로 서버가 사용자가 전달한 값을 검증없이 신뢰하고 이에 해당하는 데이터를 권한 확인 없이 그대로 보여주는 경우

 

가끔 GUID를 사용하기도 하는데, (id=123아니고 asdjifh3-4fio 등) 추측은 어렵지만, 이 guid가 다른 화면에 노출되면 여전히 IDOR 공격에 악용될 수 있음

 

보안 조치 매 요청마다 "이 사용자에게 이 자원에 대한 권한이 있는가?"를 서버가 직접 확인해야 안전하다.

실습

carlos의 guid를 찾아서 API key를 제출하라고 한다.

 

burp suite말고 개발자 도구로 주어진 내 계정에 로그인을 해봤다. id에 다음과 같이 guid가 뜬다.

 

carlos가 쓴 blog post를 찾아서 그의 ID가 포함된 URL 정보를 습득하고, 그 암호로 account 페이지에 로그인을 하면 된다고 한다. 그 id 파라미터 값을 저장된 user ID로 변경하면 API Key 값을 찾을 수 있다. 

 

carlos가 쓴 글을 찾았다.

 

 

소스코드를 살펴보니까 blog-author 부분에 href로 링크가 걸려있더라. 

 

 

커서를 올려보면 링크로 이동된다는 것을 알 수 있다.

 

 

해당 링크에 적힌 id 값을 my account 페이지로 이동해 url에 적힌 내 id를 carlos의 id로 변경하면 carlos account로 이동해 API Key를 얻을 수 있다.

 


Horizontal to vertical privilege escalation

수평적 권한에서 수직적 권한 상승

수평적 권한은 공격자가 다른 사용자의 비밀번호를 초기화하거나 저장할 수 있다. administrative user의 계정을 탈취하면 그 권한까지 얻게 돼서 수직 권한 상승이 가능해진다.  

 

다른 user의 id값을 url parameter를 통해서 바꿀 수 있다는 것을 이전 교육에서 배웠는데, 이를 통해서 권한 상승이 가능해지고 admin 계정을 공개하거나, 변경 등의 기능을 수행할 수 있다. 

 

LAB

<input type="password" value="secret123">

 

account page에 가면 패스워드가 masked input, 즉 가려서 표시될 것이다. admin의 패스워드를 알아내고 carlos 계정을 삭제하는 것이 목표다. 

 

wiener 계정으로 로그인해보니 password로 가려져 있는 걸 확인했다.

 

 

저 hidden 타입의 csrf value가.. 비밀번호인가보다.

 

 

url에 id 파라미터 값이 wiener로 되어 있길래 carlos로 바꿔보니까 carlos의 account로 접근할 수 있었다.

 

 

마찬가지로 id를 administrator로 바꿔서 소스코드를 확인하면 value가 보이니 이 값으로 로그인을 하면 되겠다.

 

 

접속 성공!

 

admin panel로 접근 가능해서 carlos 계정을 삭제했다.

 

 

와 아직 한참 남았는데 글이 너무 길어져서 2탄으로 나눠야겠다.

 

 

access control (접근제어)까지 완료!

728x90

댓글