
13주차 기준으로 다음주면 본격적으로 프로젝트 기간이 시작된다. 프로젝트 시작을 한 주 앞두고 있으니 설레기도 하고 걱정도 많은거 같다.
일단.. 많이 헤맸던 한 주였던거 같다. 프로젝트 방향성이 명확하게 잡혀 있다고 생각했는데, 세부적인 부분을 잡을 때마다 혼란스러웠던 순간이 왔던거 같다.
사실 지금까지 뭔가 머릿속에 정리가 안되고 그러지 않았는데 유독 정리가 안되서 조금 머리가 상당히 아팠던 한주였다. (강사님하고 4시간 동안 얘기했다ㅋㅋㅋㅋ)
일단 내가 정리가 안되니까 팀원들도 혼란스러워 하고 그냥 대환장 파티였다🤯 그래도 잘 정리해서 방향성이 명확해진 이후엔 큰 문제 없이 쭉쭉 준비를 했던거 같다.
암튼 이번주 TIL부터는 프로젝트 관련 내용을 중점적으로 다뤄 볼 생각이다. 어떤 이슈가 있었고, 고민을 했는지 최대한 잘 담아서 정리 해보도록 하겠다.
이번주 우리 팀에게 주어진 가장 큰 질문이었다.
우리 팀이 하고자 하는건 크게 "흩뿌려진 로그들을 분석을 통해 맥락(Context)을 부여한다.", "분석 결과를 바탕으로 공격자의 행위를 가시화하여 재현한다." 이 두 가지였다.
일단 결론부터 말하자면 컨셉을 첫 번째는 유지, 두 번째는 탐지를 고도화하는 방향으로 수정했다. 그래서 왜 수정이 이루어졌냐면 ..
사전 준비 과정에서 분석 파트를 담당하고 있는 친구들의 미션은 분석 도구 비교 및 구성이다. K8S 환경에서 사용할 수 있는 탐지 도구들은 정말 많다.
현재 보편적으로 가장 많이 쓰이는 Falco부터 Tracee, Tetragon, KubeArmor 등등 ... eBPF 기반인 것은 공통점이지만 각 도구의 아키텍처도 다르고 지원하는 기능들도 비슷하지만 차이점이 분명하게 있다. 또한, Network 탐지 도구로는 Zeek, Hubble 등이 있다.
업계 표준인거 쓰면 되는거 아니야? 뭘 그렇게 고민하냐고 할 수 있지만, 나와 분석쪽을 담당하고 있는 친구들의 생각은 업계 표준이라서 따랐다는 말은 논리적인 타당성이 부족 하다는 것이었다.
물론 결론적으로 표준을 따를수도 있겠다만, 도구들을 비교 분석하는 과정이 없다면 의미가 있나? 없다고 생각했기 때문에 도구 비교 과정까지 포함하여 각 도구들의 장점부터 지원하는 기능, 한계점들을 알아 가려고 노력했다.
그러던중 12/10 수요일에 분석 파트에서 이런 말이 나왔다.
공격자의 행위를 재현해서 제공하려면 공격자가 어떤 파일, 데이터에 접근했는지 파악하기 위해 Raw Packet을 봐야하는데, Raw Packet Capture를 하기 위해 Zeek나 tcpdump를 상시로 켜두면 부하가 엄청 심해요.
이 말을 듣고 좀 생각이 많아졌던거 같다.(지금 생각해보면 참 바보같다) 사실 wireshark 잠깐만 켜놔도 패킷 1만개, 2만개가 우습게 쌓이는데 이걸 계속 틀어놓는다? 말도 안되지... 그래서 곰곰히 생각 해보다가 이렇게 말했다.
그럼 이벤트가 발생했을 때만 Signal을 날려서 그때만 잠깐 캡쳐하면 되지 않나요?
그랬더니
그럼 공격 시작점을 놓칠수도 있어 의미가 없을거 같아요.
음.. 답이 없어 보였다. 일단 확실한건 계속 켜두는건 말이 안되는건 확실하고.. 강사님하고도 얘기 해봤을 때 말도 안되는거라고 하셨다ㅋㅋㅋㅋㅋ

그래서 일단 tcpdump랑 zeek 스트레스 테스트를 진행 해봤는데 Zeek는 로그 포맷을 바꾸는 기능때문에 리소스를 많이 잡아 먹어서 tcpdump를 사용하는게 맞다고 판단이 들었다.
이걸 어떻게 붙일거냐가 문제였는데, sidecar 방식으로 각 pod에 붙이고 Ring Buffer에 로그를 흘리다가 Signal이 오면 그때부터 저장해서 보내보는거 어떻겠냐라고 했는데 근본적으로 공격의 시작점을 놓칠 수 있다는 문제는 사라지지 않았다.

무한 반복이었다.. 결국 멘토님께 분석 파트 담당하고 있는 친구가 질문을 드렸고 답변이 왔다.
Q. 현재 저희 팀은 쿠버네티스 환경에서 eBPF 기반 공격 탐지·분석을 주제로 프로젝트를 진행하고 있으며, 그 과정에서 수집·분석 범위를 어디까지 설정해야 할지 고민이 있어 조언을 구하고자 합니다.
일반적으로 Raw 패킷 데이터는 별도로 저장하지 않고 메타데이터 수준만으로도 상당 부분 탐지가 가능한 것으로 알고 있습니다. 다만 저희 팀은 보다 심층적인 분석과 재현 가능성을 확보하기 위해 Raw 데이터를 추가로 수집해야 할지 고민하고 있습니다.
문제는 Raw 데이터 수집이 성능 부담이 크고, 쿠버네티스 환경의 eBPF 기반 탐지 자체가 메타데이터 중심의 정보만 제공한다는 한계가 있다는 점입니다. 이 때문에 eBPF 이벤트 발생 시 tcpdump로 Raw Packet을 연계 수집하는 방안도 검토했지만, 전체 캡처는 부하가 과도하고 이벤트 기반 캡처는 구현 난이도가 높고 안정성이 떨어지는 문제가 있었습니다.
A. raw 데이터에 대한 수집은 비추천합니다. 말씀주신 이유도 있고, 필요시 단발성으로 수집하는 것이지, 상시로 수집은 현업에서도 비추천하는 방식입니다.
근데 지금 생각 해보면 다 너무 당연한거고 왜 얘기가 이렇게 흘러갔는지 도통 모르겠다. 처음 프로젝트 주제 잡을 때 "탐지 고도화"가 핵심이었는데 어느 순간 "재현"에 집중되어 눈이 멀었던거 같다.
그래서 결론은 raw data는 보지 않고, Header와 Metadata 정보를 가지고 분석을 통해 시스템 로그와 네트워크 로그의 Context를 부여하여 탐지 Rule을 고도화하는 방향으로 잡았다.
정말 토할거 같았다 이 과정이 참 힘들었지만 프로젝트 방향성을 명확하게 잡았다는 것에 의의를 두며.. 하루를 마무리했다.
2명씩 쪼개져서 인프라, Red Teaming, 분석 세 가지로 나뉘어 준비 작업을 하는데 나는 주로 Red Teaming을 담당하게 되었다. 이 파트에서 주어진 미션은 "공격 시나리오 설계", "컨테이너 환경에서의 취약점 분석"이다.
쿠버네티스 환경을 타겟으로 공격을 진행 해야하니 우선 오픈소스로 Pen Test를 할 수 있는 도구들을 먼저 찾아 본 결과 "Peirates"와 "CDK" 두 가지 공격 도구들을 확인할 수 있었다.
또한, 우리가 하고자 하는게 경계망이 아니라 인프라 내에서의 보안이기 때문에 외부에서 내부 침투하는 과정은 생략하고, 공격자가 내부로 침투했음을 가정하고 시나리오를 설계하기 시작했다.

Peirates는 외부에서 내부로 침투 된 상황을 가정하고 lateral movement, privilege escalation를 통해 서비스 계정 토큰을 수집하는 데 중점을 둔 모의 해킹 도구이다.
이 도구는 K8S에 특화되어 있고, 손상된 Pod 하나를 통해 클러스터 전체를 장악하는 것이 핵심 컨셉이다. 즉, 공격자가 이미 내부 Pod 하나에 침투했다고 가정했을 때, 그 안에서 권한을 상승시키고 다른 컨테이너로 이동하는 과정을 자동화 해준다.
파악한 결과 가능한 공격 시나리오는 다음과 같다.
Service Account Token을 자동으로 수집한다.Secrets나 ConfigMap에 저장된 민감한 정보(DB 패스워드, API 키 등)를 Dump한다.kubectl binary가 없더라도, Peirates 자체가 kubectl 기능을 내장하고 있어 API 서버와 직접 통신하며 명령을 내릴 수 있다.hostPath mount가 되어 있는 취약점을 찾아내서 이를 이용해 Node의 제어권을 획득하려 시도한다.
해당 도구를 실행했을 때 다음과 같은 화면이 나오면 실행에 성공한 것이고 가능한 공격 옵션은 다음과 같다.



일단 결론은 이 도구는 사용하지 않기로 했다. 공격 수행을 위해 일부러 취약하게 환경을 세팅했는데도 불구하고 안되는 옵션들이 많았다.
왜냐면 마지막 업데이트가 2022년 .. 너무 오래된 공격 도구여서 우리가 보안적인 조치를 취하지 않아도 쿠버네티스 자체에서 지원하는 기능들로 충분히 막히는 것을 확인해서 사용하지 않기로 했다.

AWS CDK 아니고 Pen test 도구 CDK이다. Pen test 도구치고 로고가 너무 귀엽다.
암튼 Peirates와 같이 컨테이너 환경 대상 Pen test를 수행할 수 있는 도구다. 마지막 업데이트가 2025년 2월이니 가능한 공격들이 많을 것으로 예상했다.
CDK(Container Digging Kit)를 활용하여 Lateral Movement, Container Escape, Priviliege Escalation 세 가지 공격을 수행할 수 있는 취약한 환경 세팅을 진행한다. Privilege Escalation을 동반한 Lateral Movement 시나리오로 공격을 진행했다.
초기 공격자가 침투한 Pod는 권한이 없지만 Node의 취약점을 이용해 같은 Node에 떠 있는 Admin Pod의 Token을 훔쳐내서 진행했다.
service namespace의 web-appdev namespace의 db-admin 탈취web-app 장악db-admin Pod의 Token 검색 및 탈취db-admin을 사칭하여 dev 영역의 Secret 탈취먼저 현재 위치한 Pod가 가지고 있는 권한을 확인했다.

403 Forbbidden 즉, 현재 접근 권한이 없다는 것을 확인했다.

admin으로 보이는 컨테이너와 통신이 가능하다는 것을 확인
c16f0bfd4db6653813dc90dedocker -H unix:///var/run/docker.sock run -it --rm --privileged --net=host -v /:/host ubuntu:24.04 chroot /host
Host 루트 디렉토리를 /host에 마운트한 컨테이너 하나를 생성했다.

pod 목록을 확인할 수 있었고 이 중 DB 관리자 권한을 갖는 pod가 있을 것이다.

우리가 타겟으로 한 token을 발견할 수 있었다. 해당 토큰을 통해 ./cdk run k8s-secret-dump /tmp/token.txt 명령으로 API 서버에 질의를 보냈더니 failed라고 떴지만 response를 봤더니 secret-key를 확인할 수 있었다.

인코딩 된 키를 디코딩 해보니 설정 해놓은 Flag를 확인할 수 있었다.
Peirates보단 수행할 수 있는 공격 유형이 다양했지만, 불가능한 공격들이 있었다. CDK를 안쓰기엔 가능한 공격들도 있고 편의성을 가져다 주는 측면이 있어서 이 스크립트를 수정해서 공격에 활용하기로 했다.

공격 시나리오를 설계하던중 React2Shell이라는 React Library가 가진 취약점이 발견된 것이다. 현재 나와 있는 대부분의 서비스가 React를 이용하여 만들어졌으니 모든 서비스 운영사들은 초긴장 상태에 있을거 같다. 내 주변만 하더라도 이미 공격을 당했다는 소식이 들려오니.. 참 올해 보안과 관련해서 이슈가 정말 많은거 같다.
그래서! 공격 시나리오 방향을 틀었다. 외부에서 내부로 침투는 하지 않기로 했는데 React2Shell 취약점이 발견됐으니 우리도 이를 반영하여 공격 시나리오의 한 꼭지를 넣어보고자 했다.
사실 공격 시나리오 설계 과정에서 "다양한 공격 시나리오"라는게 공격 방식의 다양성을 의미하는지 스토리 라인의 다양성을 의미하는지 감이 안잡혀서 멘토님께 질문을 드렸었다.

답변이 왔는데 역시 둘 다 의도하신거였다🫠 그래서 우선 React2Shell 취약점을 가지고 있는 서비스 환경을 구성해서 공격을 수행 해보고자 했다.

질문하기 전에 React2Shell 취약점이 처음 발표되고 한 3일? 정도 뒤에 이 공격에 대해 Study를 진행했었다. 취약점을 가진 Service랑 PoC를 찾아서 Docker Image화 하고 실습을 바로 진행해봤다. (아 사진은 멘토님이 1 따봉 주셨다ㅋㅋㅋㅋㅋ 멘토님의 긍정 시그널은 큰 힘이 되기에..ㅎ)
React2Shell 취약점을 가진 즉, RSC(React Server Components)를 사용하는 서비스를 Docker image로 띄워서 민감 파일 읽기, 민감 파일 유출, Reverse Shell 공격을 통해 내부로 침투하여 Lateral Movement, Container Escape와 같은 다양한 공격을 시도 해봤다.
공격은 정찰 -> 내부 침투 -> Lateral Movement -> Container Escape 순서로 진행했다.

먼저 정찰 단계에서 해당 서비스에서 사용하는 함수에 대한 Action ID 값을 얻을 수 있었다. Action ID는 서비스의 기능을 정의하고 있는 함수의 식별자라고 생각하면 된다.
이를 통해 특정 함수의 호출 안에 명령을 삽입하여 정의한 기능 외에 삽입한 명령이 실행될 수 있게 할 수 있다.

위에서 얻은 Action ID를 이용해서 id 명령어를 서버 요청에 담아서 보냈는데 200 코드가 뜬거 보면 요청을 거부하지 않고 정상적으로 수신했음을 알 수 있다.
그리고 response body를 보면 id 명령의 결과를 담고 있는데, 인코딩 된 형태로 반환되었지만 서버가 정상적으로 응답을 했다는거 자체가 RCE 경로가 열려 있음을 의미한다고 볼 수 있다.

서비스를 운영하고 있는 Pod의 Shell을 딸 수 있었다. 즉, 내부로 진입한 것이다.

namespace 접근 권한을 확인했다. 아쉽게도(?) 접근 권한은 없었다.

env 명령어를 이용해서 조회 해봐도 API server와 현재 pod의 IP 주소밖에 안보인다.
환경변수 조회의 이유
공격자가 침투한 이후 환경변수를 조회하는 이유는 크게 두 가지로 내부망 구성 확인, 관리적 실수로 남겨져 있는 기밀 정보 확보이다.

/etc/resolv.conf를 확인 해봐도 별 다른 정보가 안나온다. 그래서 반복문을 이용해서 다른 Namespace를 찾아봤다.

internal-ops에 admin-bot pod가 있는 것을 확인했다.

shell이 바뀐 것을 보면 기존 서비스 Pod에서 admin-bot Pod로 이동 했음을 알 수 있다. 이렇게 내부망에서 다른 구성 요소로 이동하는 공격을 Lateral Movement라고 한다.
CI/CD 파이프 라인 관리의 편의성, 컨테이너 모니터링 등 관리적 편의성을 위해 docker socket을 마운트 했다는 설정으로 환경을 구성했기 때문에 docker.sock의 위치를 찾아서 Host OS를 장악하면 끝이다. Docker socket은 호스트에 직접 명령을 내릴 수 있는 수단이기 때문에 노출되면 정말 위험하다.
docker -H unix:///var/run/docker.sock run -it --rm --privileged --net=host -v /:/host alpine chroot /host
docker.sock이 마운트 되어 있는 위치에서 위와 같은 명령을 수행하면 root file system 전체가 마운트 되게 된다. 서버에 담겨 있는 모든 것에 접근이 가능하다는 얘기랑 똑같다. (결과 사진이 어디 갔는지 ... )
고민에 고민에 고민에 고민이 거듭됐던 한 주였다. 과정은 힘들었지만 결과는 얻었으니 나름 괜찮았던거 같다.
그리고 9주차 이후에 부트캠프 끝나고 집에 와서 저녁 식사하고 다시 책상에 앉아 작업 하는게 습관이 됐다. 프로젝트 준비하는 데 시간을 쏟다 보니까 할 수 있는게 더 많아졌다. 물론 고민은 배가 된거 같지만ㅋㅋㅋㅋㅋ 좋은 습관이 하나 생긴거 같다.
보통 주말에 TIL을 쓰는 편인데 좀 어디에 따로 기록을 수시로 해놨다가 써야겠다. 최대한 그날에 그 감정과 했던 생각들을 녹여 내려고 해도 뭔가 점점 벅차다 해야하나? 플젝 생각하기도 빠듯해서 다른 부분에서 기억력이 좀 딸리는거 같아서 .. 다음주에는 더 생동감 있는 우리 팀의 이야기와 프로젝트 진행 상황에 대해 적을 수 있도록 하겠다!
TIL 외에 팀 별 프로젝트 관련 블로그 글을 작성하라고 전달 받아서 그 글에는 프로젝트 진행 상황, 내부적으로 검토중인 사안들에 대해 잘 정리 해보도록 하고 여기선 내용적인 부분 뿐만 아니라 내가 했던 생각들, 감정들을 녹여서 작성 해보려고 한다.
이번주 TIL은 여기서 마무리 짓도록 하겠다! 다들 이번 한 주도 고생하셨습니다!