
첫 번째 문제를 번역기로 해석해 보니
파일 업로드 중 경로 탐색
이 과제에서는 파일 시스템의 특정 파일을 덮어쓰는 것이 목표입니다. 물론 WebGoat은 사용자를 신경 쓰기 때문에 일반적인 업로드 위치 외의 다음 위치에 파일을 업로드해야 합니다.
요약
1. 업로드 파일의 위치를 정해진 일반적인 위치가 아니라 다른 곳으로 업로드해야한다.

파일을 업로드 하였더니 저장된 경로는 /root/.webgoat-2023.3/PathTraversal/123123/123" 로 파일의 저장 상태를 확인해 보니 본인의 사용자 계정ID(123123) 으로 폴더가 하나 생기고 그 아래에는 필드에서 입력한 FULL NAME(123)으로 파일이 저장되는 거로 예상할 수 있습니다. 그렇다면 FULL NAME을 기준으로 사용자의 입력에 따라 그대로 인용하는 걸 보니 해당 필드에 파일의 위치를 다르게 할 수 있는 방법으로 공격을 시도해 보면 좋을 거 같다고 생각됩니다.

예상했던 대로 ../123으로 FULL NAME에 작성한 후 업데이트를 해보니 기존의 파일 저장위치에 저장되는 게 아니라 상위 디렉터리에 저장이 되어 문제가 해결된 걸 알 수 있습니다.

두 번째 문제를 번역기로 해석해 보니
파일 업로드 중 경로 탐색
개발자는 취약점을 인지하고 입력에서 ..../를 제거하는 수정 사항을 구현했습니다. 동일한 할당이지만 구현된 수정 사항을 우회할 수 있나요?
요약
1. 개발자가 취약점을 인지한 후 해당 문제를 수정했다.
2. 우회해서 공격을 해보자.

첫 번째 문제와 동일하게 진행해 보겠습니다. 먼저 임의의 파일을 업로드합니다. 이후 결과에 대한 메시지를 확인합니다. 아직은 별다른 차이점을 모르겠으니, 이번에는 공격을 해보겠습니다.

파일 이름에 ../12345를 입력하고 공격을 시도해 봤더니 ../ 부분이 사라져 있습니다. 그렇다면 개발자는 아마 해당 이름 필드 값에 필터링을 걸어서 ../ 부분을 제외시킨거 같습니다. 하지만 전에도 말했지만, 필터링은 좋은 대처 방안이 아닙니다. 우회하는 방법이 여러 개 존재하기 때문이죠. 그러면 우리는 SQL injection에서 사용했던 필터링 우회 방법을 다시 시도해 보면 좋을 거 같습니다.

SQL Injection에서 사용했던 우회 방법을 다시 생각해 볼까요? 그때 우리는 공백에 대한 필터링과 SELECT, FROM에 대한 필터링 우회도 해결했었죠? 마찬가지로 이번 문제도 똑같습니다. ../ 문자를 제외했다면 해당 문자를 표현하고자 하는 문자 가운데에 끼워 넣어서 필터링되는 문자가 사라지면 그때 우리가 원하는 문자가 표현됩니다.
ex) 표현하고 싶은 문자(../) -> 필터링되는 문자(../) -> 문자 사이에 끼워 넣는 우회 방법(....//)
이렇게 표현하면 기존의 필터링 되는 문자가 지워지고 공간은 자동으로 채워지게 되면서 우리가 원하는 문자를 표현할 수 있습니다. 이렇게 해서 이번 문제도 필터링을 우회하여 해결하였습니다.

세 번째 문제를 번역기로 해석해 보니
파일 업로드 중 경로 탐색
개발자는 전체 이름 입력 필드의 입력을 검증하지 않음으로써 취약점을 다시 인식하게 되었습니다. 이 취약점을 해결하기 위해 수정 사항이 적용되었습니다.
다시 같은 과제인데, 구현된 수정 사항을 우회할 수 있나요?
요약
1. 또다시 개발자가 취약점을 인지하여 수정했다.
2. 다시 우회하여 공격할 수 있을까?

같은 방식으로 임의의 파일을 업로드 하였습니다. 그런데 이번에는 이름 필드를 사용하지 않고 파일명을 그대로 사용하는 방식으로 바뀌었습니다. 그렇다면 어떡해야 할까요? 어떤 분은 파일명을 ../식으로 이름을 바꾸면 되지 않느냐? 하실 수도 있습니다. 물론 좋은 접근방식입니다. 하지만 안타깝게도 파일명에는 사용 불가한 특수문자가 엄청 많습니다. 그러므로 파일명을 변경해 공격하는 건 그리 쉬운 것이 아닙니다. 그렇지만 우리는 해당 문제를 해결할 아주 좋은 도구를 이미 사용하고 있습니다.

이럴 때를 위해 존재하는 도구인 Burp Suite를 사용하는 겁니다. 바로 중간에 메시지를 가로채는 방법이죠. 보통 우리가 사용했을 때는 변조를 위해 사용을 많이 했었죠. 여기서도 마찬가지입니다. 중간쯤에 보시면 우리가 입력한 값인 파일에 대한 정보가 담긴 게 있습니다. 이 부분을 우리가 계속 공격해 왔던 방식대로 수정해 줄 겁니다.

이렇게 가로챈 메시지에 있는 파일명에 ../문자를 집어넣어서 요청을 시도합니다. 그렇게 되면 우리가 원하는 대로 파일 업로드 저장 경로를 벗어나게 저장하게 될 것입니다.

이제 intercept를 풀고 다시 문제를 돌아와보면 하단에 문제를 해결했다는 메세지를 볼 수 있습니다.

네 번째 문제를 번역기로 해석해 보니
경로 탐색을 통해 다른 파일 가져오기
경로 탐색은 파일 업로드에만 국한되지 않습니다. 파일을 검색할 때는 시스템에서 다른 파일을 검색할 수 있는 경로 탐색이 가능할 수 있습니다. 이 할당에서 path-traversal-secret.jpg라는 파일을 찾아보세요
요약
1. 경로 탐색(Path Traversal) 공격이 파일 업로드뿐만 아니라, 시스템 내의 파일을 조회(Retrieving)할 때도 발생

먼저 show random cat picture를 눌러서 요청을 시도합니다. 상당히 귀여운 고양이가 나옵니다.

이번에는 요청을 확인해 보겠습니다. 해당 경로로 요청을 보내고 있습니다.

그런데 응답에서는 location 헤더가 보입니다. 상태코드도 200인데 왜 리다이렉션이 일어날 때 생기는 location 헤더가 있는 걸까요? 해당 응답이 요청에 대한 리다이렉션이 발생했다기보다는 아마 개발자가 실제 자원이 위치한 힌트를 주기 위한 의도적으로 흘린 힌트 같은 거 같습니다. 즉, 우리가 요청하면 서버는 해당 location에 작성된 URI로 요청을 보내서 응답을 다시 사용자에게 전달했다고 할 수 있겠습니다. 덕분에 우리는 보낸 요청에 id 파라미터만 추가된 걸 확인할 수 있습니다.

우리는 이제 응답에서 봤듯이 id 파라미터를 추가해서 사진을 가져온다는 것을 알았으니 실제로 그러한지 요청을 보내봤습니다.

그런데 응답을 확인해 보니 404 오류코드가 나왔습니다. 그리고 본문에는 알 수 없는 내용이 나왔습니다. 응답에 있는 location 헤더를 확인해 보니. jpg가 하나 더 붙어있는걸 볼 수 있습니다. 그렇다면 우리가 요청을 보낼 때 서버는 해당 파라미터에. jpg를 붙여서 해당 URI로 다시 요청을 보내서 응답을 전달했기 때문에 이런 결과가 나온 거 같습니다.
id=4로 요청했을 때

id=4 응답

역시 .jpg가 없는 상태에서는 서버가 해당 요청에 파라미터에 추가로 .jpg를 추가하는게 맞는걸 알 수 있습니다.

그렇다면 응답 본문은 무엇에 대한 것일까요? 응답 본문은 id 파라미터에 입력한 값과 동일한 이름의 파일을 찾아봤을 때 해당 결과가 없으면 나오는 값입니다. 본문을 자세히 보면 모두 같은 디렉터리에 존재하는 파일입니다. 그런데 아쉽게도 cat 폴더에는 우리가 찾는 파일이 존재하지 않습니다. 하지만 얻은 게 없는 것은 아닙니다. 응답 본문처럼 파일이 존재하지 않을 때 생기는 오류로 인해서 우리는 공격을 시도해 볼 수 있는 겁니다.

../를 이용해서 상위 디렉터리로 올라가서 조회를 시도해 봤습니다.

물론 123이라는 파일이 없겠죠. 그렇게 되면 오류가 나오면서 해당 위치에 존재하는 파일경로가 나와야 했는데 응답 본문에는 Illegal characters are not allowed in the query params 라는 내용을 볼 수 있는데요. 내용을 해석해 보니 사용할 수 없는 문자가 있다. 123은 아닐 거 같고 그러면 ../을 사용할 수 없다는 건데 이럴 때는 우회하는 방법을 시도해 보는 게 좋습니다.

../를 URL인코딩해서 %2e%2e%2f 변환해 주었습니다.

다행히 우회방법이 성공했습니다. 하지만 여기서도 우리가 찾는 파일이 없습니다. 어쩔수없습니다. 나올때 까지 가는겁니다.

한번더 상위 디렉터리로 올라가기 위해서 ../../두번해줍니다.

마침내 /root/.webgoat-2023.3까지 올라가서야 해당 고양이파일을 찾을 수 있었습니다.

이제 찾은 고양이 파일을 직접 조회해 봐야겠죠? 다음과같이 파라미터에 ../../path-traversal-secret를 추가해서 요청을 보내봤습니다.

그랬더니 응답 본문에 고양이 찾았으니, 너의 이름을 SHA-512로 해서 보내라고 합니다.

저는 구글에 SHA-512 암호화를 검색해서 아무 사이트나 방문했습니다.

그러면 이렇게 사용자계정에 맞게 해싱이 완료됩니다.

이렇게 해싱된 사용자계정을 입력해서 해당 문제를 해결하였습니다.

다섯 번째 문제를 번역기로 해석해 보니
Zip 슬립 할당
이번에는 개발자가 zip 파일만 업로드할 수 있도록 허용합니다. 하지만 zip 파일을 업로드하는 과정에서 프로그래밍 실수가 발생하여 압축 파일이 추출되지만 이미지가 대체되지는 않습니다. 프로그래밍 실수를 우회하여 현재 이미지를 덮어쓸 수 있는 방법을 찾을 수 있나요?
아래에서 과제를 조금 더 쉽게 만들기 위해 교체해야 할 프로필 이미지의 위치를 찾을 수 있습니다:
요약
1. zip 파일만 업로드 가능
2. 개발 과정에서 실수가 있어 압축 파일이 해제된다.
3. 실수를 이용해서 덮어쓰기를 해보자.

압축 파일을 업로드 해보았습니다. 메시지에서 압축 파일은 잘 해제되었지만 복사하는 데는 실패했다고 헬프데스크에 문의하라고 합니다. 해당 실패를 통해 압축 파일에 있는 파일들이 어딘가로 복사 된다는 걸 알 수 있습니다. 근데 만약에 파일명을 그대로 사용한다면 지금까지 공격했던 방법들이 생각이 납니다. path traversal 공격을 시도할 수 있다면 우리는 다른 곳에 파일을 복사할 수도 있다는 것입니다.

일반 파일이면 burp suite를 사용해 요청에서 파일명을 변조하면 되겠지만 이번에는 압축 파일에 있는 파일의 이름을 변조해야 하므로 해당 방법으로 불가능하고 또 파일이름에는 사용하지 못하는 특수 문자가 많으니 쉽지가 않습니다. 일단 Ubuntu 기반 컨테이너를 하나 생성합니다. 그다음 apt update && apt install zip을 설치합니다.

만들어진 컨테이너로 들어오면 공격용 압축 파일을 위해 webogat에서 제시한 동일한 환경을 구축할 겁니다. /root/.webgoat-2023.3/PathTraversal/123123/123123.jpg 그런 다음 최상위 경로 /root에서 위와 같이 디렉터리와 파일을 생성해 줍니다.

실습과 동일한 환경을 구축하였다면 zip 명령어를 사용해 압축파일을 생성합니다. 만들 때 중요한 점이 있습니다. 압축파일을 업로드했을때 압축파일이 어디에서 해제되고 어디로 복사하는지를 모릅니다. 그러므로 최대한 많은 ../를 넣어서 최상위 디렉터리로 올라갑니다. zip zipslip.zip ../../../../../../../../../../root/.webgoat-2023.3/PathTraverSal/123123/123.jpg 그렇게 한 다음 실습에서 덮어쓰게 할 파일의 경로와 동일하게 만든 123.jpg 파일을 찾아서 경로를 설정해 줍니다.

이제 생성한 zipzlip.zip 파일을 컨테이너에서 빼기 위해 명령어를 입력해 줍니다.
1. docker cp temp_linux:/root/zipslip.zip C:\Users\th\Desktop
2. cd C:\Users\th\Desktop
3. dir zipslip.zip
여기까지 복사를 잘했다면 이제 공격하면 됩니다.

다음과 같이 문제를 해결됨을 볼 수 있습니다.
이번 실습에서는 파일 업로드 공격들에 대해서 알아보았습니다. 그런데 대부분에 문제를 보면 프런트엔드에서만 검증하고 백엔드 쪽에서는 검증하지 않는걸 볼 수 있는데 실제로는 그렇지 않습니다. 필자도 개발할 때 프런트엔드 쪽에서만 검증을 끝내지 않고 백엔드에서도 검증을 2차로 합니다. 왜냐하면 이러한 부분에 대해서 방어하기 위해서죠. 예를 들면 권한이 없는 사람이 다른 사람의 게시물을 수정하면 안 되겠죠? 그래서 백엔드에서도 해당 사용자가 게시물의 주인이 맞는지에 대한 로직을 구현해서 판단합니다. 또한 파일 업로드 부분에서도 필자는 프런트엔드에서도 파일확장자를 검사하거나 파일의 크기 등을 고려하고 백엔드에서도 확장자 혹은 파일의 크기, 개수 등을 판단하여 필터링합니다. 결론적으로 프런트엔드 쪽과 백엔드 둘 다 검증해야 최대한 이러한 방법으로 중간에 데이터를 가로채버리면 큰일이 일어날 수 있습니다.