서문
Unix와 Linux 시스템은 보이지 않는 곳에서 작동하며 기술 인프라의 상당 부분을 조용히 뒷받침하고 있습니다. 이러한 시스템을 노리는 위협이 점점 더 복잡해짐에 따라 보안을 보장하는 것이 그 어느 때보다 중요해졌습니다.
Unix 및 Linux 시스템 내에서 작업하는 보안 탐지 엔지니어의 무기고에 있는 기본 도구 중 하나는 Auditd입니다. 이 강력한 유틸리티는 시스템 이벤트를 모니터링하고 기록하도록 설계되어 누가 언제 무엇을 했는지에 대한 자세한 감사 추적을 제공합니다. 포렌식 분석 및 실시간 모니터링에 중요한 시스템 호출, 파일 액세스 및 시스템 변경에 대한 자세한 정보를 순찰하고 기록하는 감시자 역할을 합니다.
이 글의 목적은 다방면에 걸쳐 있습니다:
- 보안 탐지 엔지니어링 분야에서 Auditd의 기능과 막강한 힘을 보여주는 추가 정보를 제공하고자 합니다.
- 고객의 특정 모니터링 요구사항에 맞게 자체 시스템에 Auditd를 설정하는 방법을 안내해 드립니다. Auditd 규칙을 만들고 수정하는 방법을 이해함으로써 모니터링하려는 정확한 동작을 캡처하고 결과 로그를 해석하여 자신만의 탐지 규칙을 만드는 방법을 배울 수 있습니다.
- 시스템 전반에서 Auditd의 관리를 간소화하여 Auditd의 활용도를 높여주는 통합 도구인 Auditd 매니저를 소개합니다.
이 게시물이 끝나면 Auditd Manager를 사용하여 미리 구축된 탐지 규칙 중 일부를 보안 전략에 통합하는 방법을 배울 수 있을 뿐만 아니라 Auditd에 대한 포괄적인 이해와 이를 활용하여 자체 탐지 규칙을 구축하는 방법도 배울 수 있습니다.
Auditd 소개
Auditd는 시스템 이벤트를 모니터링하고 기록하여 사용자 활동, 시스템 변경 사항 및 보안 액세스에 대한 포괄적인 감사 추적을 제공하도록 설계된 Linux 도구입니다. Auditd는 Linux 커널에 연결하여 시스템 호출 및 기타 시스템 이벤트가 발생할 때 자세한 정보를 캡처하는 방식으로 작동합니다. 그런 다음 이러한 이벤트는 파일에 기록되어 타임스탬프가 찍힌 기록을 제공합니다. 관리자는 기록할 이벤트를 지정하는 규칙을 정의하여 특정 관심 분야나 우려 사항에 집중할 수 있는 유연성을 제공할 수 있습니다. 로깅된 데이터는 규정 준수 감사부터 상세한 포렌식 분석까지 다양한 용도로 사용할 수 있습니다.
감사 설정
Auditd를 시작하기 위해 Elastic은 몇 가지 옵션을 제공합니다:
이 글에서는 후자의 두 가지에 초점을 맞추고, Elastic 에이전트를 활용하여 Elasticsearch로 로그를 쉽게 수집하는 방법에 대해 설명합니다. Elasticsearch를 처음 사용하는 경우 30일 체험판 라이선스가 포함된 Elastic Cloud 계정을 쉽게 생성하거나 로컬 테스트를 위해 Elastic 컨테이너 프로젝트를 다운로드하고 .env에서 라이선스 값을 체험판으로 설정할 수 있습니다. 파일을 만듭니다.
설정 지침은 위에 링크된 문서를 참조하여 Auditbeat 또는 Filebeat를 사용하여 자유롭게 따라해 보세요. Auditd 로그 통합은 audit.log 파일을 구문 분석하여 작동하므로 로그를 수집하려는 Linux 호스트에 Auditd를 설치해야 합니다. Linux 배포판 및 선택한 패키지 관리자에 따라 Auditd 패키지를 설치해야 하며, Auditd 서비스를 시작하고 사용하도록 설정해야 합니다. 데비안 기반 배포판의 경우:
sudo apt update
sudo apt install auditd
sudo systemctl start auditd
sudo systemctl enable auditd
이제 /var/log/audit/audit.log 파일에 Auditd 로그가 채워져야 합니다. 다음으로, Auditd Logs 통합을 설치하고, 새로 설치된 통합으로 Fleet에서 에이전트 정책을 생성한 다음, Auditd가 설치된 호환되는 Elastic 에이전트에 통합을 적용해야 합니다.
대부분의 시나리오에서는 기본 설정으로 충분합니다. 다음으로, 에이전트 정책에 통합을 추가하고 데이터를 수집하려는 Elastic 에이전트에 에이전트 정책을 추가해야 합니다. Elastic 에이전트는 로그를 logs-auditd.log-[네임스페이스]로 전송합니다. 데이터스트림. 이제 새 데이터 보기를 만들어 수신되는 Auditd 로그와만 일치하도록 할 수 있습니다.
이제 수집된 Auditd 로그를 탐색할 수 있습니다. 하지만 금방 눈치챌 수 있겠지만, Auditd는 기본적으로 많은 로그를 기록하지 않으므로 Auditd의 잠재력을 최대한 활용하려면 Auditd 규칙을 활용해야 합니다.
Auditd rules
감사 규칙은 모니터링하고 기록할 시스템 활동을 지정하는 데 사용되는 지시어로, 보안 감사 프로세스를 세밀하게 제어할 수 있습니다. 이러한 규칙은 일반적으로 /etc/audit/audit.rules 파일에 구성됩니다. 감사 규칙은 3 종류가 있습니다: control, file, 및 syscall. 자세한 내용은 여기에서 확인할 수 있습니다.
제어 유형 규칙
대부분의 경우 제어 유형은 모니터링할 이벤트를 지정하기보다는 Auditd를 구성하는 데 사용됩니다. 기본적으로 감사 규칙 파일에는 다음과 같은 제어 유형 설정이 포함되어 있습니다:
-D
-b 8192
-f 1
--backlog_wait_time 60000
-D실행 시 모든 규칙을 삭제합니다(Audited는 파일의 규칙을 위에서 아래로 구문 분석합니다. 시작 시 모든 규칙을 제거하면 구성이 깔끔해집니다).-b 8192커널에 있는 기존 감사 버퍼의 최대 용량을 설정합니다.-f 1: Auditd의 실패 모드를 로그로 설정합니다.--backlog_wait_time 60000감사 백로그 한도에 도달하면 감사 레코드를 삭제하기 전에 감사 시스템이 대기할 시간(ms)을 지정합니다.
파일 시스템 규칙
이러한 기본 제어 유형 설정을 기반으로 파일 시스템 규칙(시계라고도 함)을 만들 수 있습니다. 이러한 규칙을 통해 관심 있는 파일의 읽기, 쓰기, 변경 및 실행 작업을 모니터링할 수 있습니다. 일반적인 파일 시스템 규칙은 다음과 같습니다:
-w [path-to-file] -p [permissions] -k [keyname]
-w모니터링할 파일 또는 디렉토리의 경로입니다.-p읽기(r), 쓰기(w), 실행(e) 또는 변경(a) 권한 중 하나를 선택합니다.-k감사 로그를 보다 쉽게 검색하는 데 사용할 수 있는 키 식별자의 이름입니다.
/etc/shadow 파일에서 파일 읽기, 쓰기 및 변경을 모니터링하고 이러한 이벤트를 shadow_access라는 키로 저장하려는 경우 다음 규칙을 설정할 수 있습니다:
-w /etc/shadow -p rwa -k shadow_access
시스템 호출 규칙
시스템 호출 규칙으로 작업할 때 Auditd의 진정한 힘이 드러납니다. 감사 시스템 호출 규칙은 모니터링하고 기록할 시스템 호출(syscall)을 지정하는 구성으로, 시스템 활동 및 운영 체제 커널과의 상호 작용을 자세히 추적할 수 있습니다. 각 시스템 호출을 가로채서 규칙에 일치시키므로 관심 있는 시스템 호출만 캡처하고 가능하면 하나의 규칙에 여러 개의 시스템 호출을 캡처하여 이 기능을 신중하게 활용하는 것이 중요합니다. 일반적인 시스템 호출 규칙은 다음과 같습니다:
-a [action],[filter] -S [syscall] -F [field=value] -k [keyname]
-a 플래그 뒤에 action,filter 을 사용하여 이벤트가 기록되는 시기를 선택할 수 있으며, 여기서 action 은 always (항상 이벤트 생성) 또는 never (이벤트 생성 안 함)이 될 수 있습니다.
필터를 사용할 수 있습니다:
task: 작업 생성 이벤트를 기록합니다.entry: 시스템 호출 진입 지점을 기록합니다.exit: 시스템 호출 종료/결과를 기록합니다.user: 사용자 공간 이벤트를 기록합니다.exclude: 이벤트를 로깅에서 제외합니다.
다음으로, 여러분이 있습니다:
-S관심 있는 시스템 호출(이름 또는 시스템 호출 번호)을 입력합니다.-F일치시킬 대상을 선택할 수 있는 필터를 하나 이상 설정합니다.-k키 식별자입니다.
위에 제공된 정보를 통해 대부분의 Auditd 규칙의 기본 사항을 이해할 수 있을 것입니다. 이러한 규칙에 추가할 수 있는 값에 대한 자세한 내용과 예제는 여기에서 자세히 알아보세요.
조직을 위한 포괄적인 전용 Auditd 규칙 파일을 구축하고 테스트하는 것은 어렵게 느껴질 수 있습니다. 다행히도 깃허브에 좋은 공개 규칙 파일 예제가 몇 가지 있습니다. 개인적으로 가장 좋아하는 템플릿은 가시성과 성능의 균형이 잘 잡힌 Neo23x0입니다.
감사 로그 통합 기능 사용의 한 가지 단점은 모니터링하려는 각 호스트에 수동으로 감사드를 설치하고 실행 중인 각 감사드 인스턴스에 규칙 파일을 수동으로 적용해야 한다는 점입니다. 즉, 규칙 파일을 업데이트할 때마다 모든 호스트에서 업데이트해야 합니다. 요즘에는 많은 조직에서 이 프로세스에 소요되는 시간을 줄여주는 관리 도구를 활용하고 있습니다. 그러나 Elastic은 관리 부담을 덜어주는 Auditd Manager 통합을 통해 Auditd 로그를 수집하는 또 다른 방법도 제공합니다.
Auditd 관리자 소개 및 설정
Auditd 관리자 통합은 Linux 커널의 일부인 Linux 감사 프레임워크에서 감사 이벤트를 수신합니다. 이 통합은 이벤트가 발생할 때 이를 수신하기 위해 커널에 대한 구독을 설정합니다. Linux 감사 프레임워크는 감사 가능한 단일 이벤트에 대해 여러 개의 메시지를 보낼 수 있습니다. 예를 들어 rename() 시스템 호출은 커널이 8개의 개별 메시지를 보내도록 합니다. 각 메시지는 발생 중인 활동의 다양한 측면(시스템 호출 자체, 파일 경로, 현재 작업 디렉터리, 프로세스 제목)을 설명합니다. 이 통합은 각 메시지의 모든 데이터를 하나의 이벤트로 결합합니다. Auditd 매니저에 대한 자세한 내용은 여기에서 확인할 수 있습니다.
또한 감사 매니저는 Fleet을 통해 중앙 집중식 관리가 가능하므로 관리 부담을 덜어줍니다. 통합 업데이트는 변경된 에이전트 정책의 일부인 모든 Elastic 에이전트에 자동으로 적용됩니다.
Auditd 매니저 연동 설정은 간단합니다. 서비스를 중지하고 비활성화하여 Auditd가 더 이상 호스트에서 실행되지 않도록 해야 합니다.
sudo systemctl stop auditd
sudo systemctl disable auditd
이제 상담원 정책에서 감사 로그 연동 서비스를 제거하고 대신 감사 관리자 연동 서비스를 설치/추가할 수 있습니다.
통합을 구성하는 데 사용할 수 있는 몇 가지 옵션이 있습니다. 감사 관리자에서는 감사 구성을 변경 불가능으로 설정하는 옵션(감사 구성에서 -e 2 제어 유형 규칙을 설정하는 것과 유사)을 제공하여 권한이 없는 사용자가 감사 시스템을 변경할 수 없도록 보안을 강화하여 악의적인 활동을 숨기기가 더 어려워집니다.
ID 확인 기능을 활용하여 UID 및 GID를 관련 이름으로 확인하도록 설정할 수 있습니다.
감사 규칙 관리의 경우 감사 규칙 섹션에서 규칙을 제공하거나 규칙 파일을 활용하고 이 파일을 읽을 파일 경로를 지정할 수 있습니다. 규칙 형식은 감사 로그 통합을 위한 규칙 형식과 유사합니다. 그러나 규칙 파일에 제어 플래그를 제공하는 대신 통합 설정에서 이러한 옵션을 설정할 수 있습니다.
감사 관리자는 구성에 제공된 새 규칙을 추가하기 전에 기존 규칙을 모두 자동으로 제거하므로 규칙 파일에 -D 플래그를 지정할 필요가 없습니다. 또한 설정에서 장애 모드를 silent 으로 설정할 수 있으므로 -f 플래그도 제공하지 않아도 됩니다.
백로그 제한도 설정할 수 있으며, 이는 -b 플래그를 설정하는 것과 유사합니다.
--backlog_wait_time 설정에 해당하는 배압 전략을 설정하는 옵션도 있습니다.
마지막으로 원본 이벤트 보존 옵션을 선택하면 나중에 이벤트를 더 쉽게 분석할 수 있습니다.
이제 통합을 저장하고 Auditd 로그를 수신하려는 호스트에 대한 상담원 정책에 적용할 수 있습니다.
감사 규칙 파일 문제 해결
Neo23x0에서 제공하는 규칙 파일은 기본적으로 감사 관리자에서 작동하지 않습니다. 이 기능을 사용하려면 제어 유형 플래그 제거, 기본 시스템에 없는 사용자에 대한 UID를 사용자로 변환하거나 중복 규칙 항목을 추가하는 등 몇 가지 사소한 조정을 해야 합니다. 변경해야 하는 사항은 궁극적으로 사용자 환경에 따라 달라질 수 있습니다.
호환되지 않는 파일을 감사 관리자 통합에 복사하여 붙여넣을 때 생성되는 오류를 식별하는 두 가지 방법이 있습니다. 정책을 수신한 상담원으로 이동하여 연동 서비스 입력 오류를 확인할 수 있습니다. 오류를 하나씩 분석하고 충돌하는 줄을 변경하거나 제거할 수 있습니다.
검색 탭을 사용하여 감사 관리자 데이터 보기를 선택한 다음 auditd.warnings 필드가 있는 이벤트를 필터링하고 경고를 하나씩 살펴볼 수도 있습니다.
예를 들어, 오류에 "알 수 없는 규칙 유형" 이라는 문구가 표시되는 것을 볼 수 있는데, 이는 Auditd가 제어 규칙을 지원하지 않는 것과 관련이 있습니다. "사용자 'x'를 숫자 ID로 변환하지 못했습니다."라는 오류는 시스템에 존재하지 않는 사용자와 관련이 있습니다. 마지막으로 "규칙 'x'는 'x'의 중복입니다."는 중복 규칙과 관련이 있습니다. 이제 충돌하는 항목을 제거하고 상담원 상태가 정상으로 돌아왔으니 이제 일부 Auditd 데이터 분석을 시작할 수 있습니다!
감사 관리자 이벤트 분석
이제 이전과 마찬가지로 Elasticsearch 클러스터에서 Auditd Manager 데이터를 사용할 수 있으므로 logs-auditd_manager.auditd* 인덱스에 대한 데이터 뷰를 생성하여 이 데이터를 구체적으로 필터링할 수 있습니다. 구현된 규칙 파일에는 다음 항목이 포함되어 있습니다:
-w /etc/sudoers -p rw -k priv_esc
이렇게 하면 /etc/sudoers 파일에 대한 읽기 및 쓰기 작업을 캡처하고 이러한 이벤트를 priv_esc 키를 사용하여 로그에 기록합니다. cat /etc/sudoers 명령을 실행하고 이벤트를 분석해 보겠습니다. 먼저 일반 정보가 포함된 몇 가지 필드를 살펴보겠습니다.
/usr/bin/cat 바이너리가 openat() 시스템 호출을 통해 /etc/sudoers 파일에 액세스한 것을 확인할 수 있습니다. 파일 소유자 및 그룹이 root 이고 이 파일에 대한 액세스를 요청하는 사용자가 UID 0 (루트)가 아니므로 로그에 openat() syscall이 실패한 것으로 표시됩니다. 마지막으로 이 특정 활동과 연결된 태그를 볼 수 있습니다.
조금 더 자세히 살펴보면 이벤트에 대한 추가 정보를 확인할 수 있습니다.
실행된 프로세스 명령줄과 활동을 시작한 프로세스 ID 및 프로세스 상위 ID를 확인할 수 있습니다. 또한 이벤트가 발생한 아키텍처와 명령이 실행된 tty (표준 입력에 연결된 터미널)을 확인할 수 있습니다.
a0-3 값을 이해하려면 Unix 시스템 호출에 대해 자세히 알아볼 필요가 있습니다. 이쯤 되면 시스콜이 무엇인지 알고 계실 텐데요, 간단히 설명하자면 유닉스 시스콜(시스템 호출)은 프로그램이 운영 체제의 커널에 파일 작업, 프로세스 제어 또는 네트워크 통신과 같은 서비스를 요청할 수 있는 기본적인 인터페이스입니다.
openat() 시스콜을 살펴보겠습니다. open(2) 맨 페이지(소스)를 참조하면 다음 정보를 확인할 수 있습니다.
openat() 는 open() syscall의 발전된 버전으로, 디렉토리 파일 설명자(dirfd)를 기준으로 파일에 액세스할 수 있습니다. 이 시스템 호출을 통해 프로그램은 파일이나 디렉터리를 열 수 있으며, 이는 많은 시스템 작업에서 중요한 작업입니다. 시스템 호출은 표준 C 라이브러리의 일부이며 #include <fcntl.h> include 문을 통해 fcntl.h 헤더에서 사용할 수 있습니다.
매뉴얼을 참조하면 openat() syscall 구문은 다음과 같습니다:
int openat(int dirfd, const char *pathname, int flags, /* mode_t mode */);
dirfd디렉터리 파일 기술자를 지정합니다.*pathname는 열려는 파일/디렉토리의 이름을 가리키는 포인터입니다.flags작업 모드(예: 읽기, 쓰기, 만들기 등)를 결정합니다.
원래 이벤트로 돌아가서 이제 auditd.data.a0-a3 필드를 이해할 준비가 되었습니다. 감사 로그의 a0 ~ a3 값은 시스템 호출에 전달된 인수를 나타냅니다. 이러한 인수는 시스템 호출 실행의 컨텍스트와 세부 사항을 이해하는 데 매우 중요합니다. 앞서 살펴본 내용을 바탕으로 이러한 값이 openat() 와 어떤 관련이 있는지, 그리고 시도된 작업에 대해 무엇을 알려주는지 분석해 보겠습니다.
auditd.data.a0(dirfd): a0 값(ffffff9c)은 특수 지시어(AT_FDCWD)를 나타내며, 현재 작업 디렉터리에 상대적인 작업임을 나타냅니다.auditd.data.a1(pathname):a1값인7ffd0f81871d은 대상 파일 또는 디렉터리의 경로명 문자열을 가리키는 16진수 메모리 주소를 나타냅니다. 이 경우/etc/sudoers파일에 액세스하려는 시도를 의미합니다.auditd.data.a2(flags):0의a2값으로 반영되는 flags 인수는 파일에 액세스하는 모드를 지정합니다.0은 특별한 플래그가 사용되지 않았음을 나타내며, 이는 기본 작업(대부분 읽기 전용 액세스)을 의미합니다.auditd.data.a3(mode):a3값 역시 0은 파일이 만들어지는 컨텍스트에서 새 파일에 설정된 권한을 지시하는 관련 값이 됩니다.
위의 분석을 바탕으로 이제 Auditd 매니저 이벤트를 해석하는 방법을 꽤 잘 이해하셨을 것입니다.
감사 관리자 이벤트가 무엇을 의미하는지 빠르게 파악하는 또 다른 방법은 Elastic의 기본 제공 AI 어시스턴트를 사용하는 것입니다. whoami 명령을 실행하고 이벤트 내의 auditd.messages 필드를 살펴보겠습니다.
Elastic AI 어시스턴트에게 무거운 작업과 이벤트 분석을 요청할 수 있으며, 그 후에는 시스템 호출 매뉴얼을 참조하여 올바른지 확인하기만 하면 됩니다. 먼저 이와 다소 유사한 Auditd 로그 분석에 초점을 맞춘 새 시스템 프롬프트를 만들어 보겠습니다:
이제 새로 생성된 시스템 프롬프트를 활용하여 별도의 서식 지정 없이 감사 메시지를 붙여넣고 다음과 같은 응답을 받을 수 있습니다:
생성형 AI 도구는 이벤트에 대한 빠른 설명을 받는 데 매우 유용합니다. 그러나 생성형 AI는 실수를 할 수 있으므로 이러한 유형의 분석에 AI 도구를 활용할 때는 항상 주의해야 하며, 생성된 결과물을 다시 한 번 확인해야 합니다. 특히 이러한 도구의 결과를 탐지 규칙 개발에 활용할 때는 사소한 실수 하나가 잘못된 로직으로 이어질 수 있습니다.
감사 관리자 탐지 규칙 예시
이전 섹션을 읽으셨다면 이제 Auditd 매니저 로그 분석을 시작할 수 있는 충분한 지식을 갖추셨을 것입니다. 현재 Elastic 탐지 규칙 규칙 세트는 대부분 Elastic Defend 통합을 활용하지만, Auditd를 활용하는 규칙의 수가 크게 증가하고 있습니다. 이 섹션에서는 Auditd를 활용하는 몇 가지 탐지 규칙을 살펴보고, 그 이유를 설명하며, 탐지 규칙 쿼리 작성에 잘 사용되지 않는 몇 가지 기법을 알려드리려고 합니다.
UDP를 통한 잠재적 리버스 셸
잠재적 리버스 셸 경유 UDP 규칙은 UDP 기반 리버스 셸을 식별하는 것을 목표로 합니다. Elastic Defend는 현재 UDP 트래픽을 캡처하지 않으므로, Auditd를 활용하여 이러한 가시성 격차를 줄일 수 있습니다. 이 규칙은 다음 로직을 활용합니다:
sample by host.id, process.pid, process.parent.pid
[process where host.os.type == "linux" and event.type == "start" and event.action == "executed" and process.name : (
"bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish", "perl", "python*", "nc", "ncat", "netcat", "php*",
"ruby", "openssl", "awk", "telnet", "lua*", "socat"
)]
[process where host.os.type == "linux" and auditd.data.syscall == "socket" and process.name : (
"bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish", "perl", "python*", "nc", "ncat", "netcat", "php*",
"ruby", "openssl", "awk", "telnet", "lua*", "socat"
) and auditd.data.a1 == "2"]
[network where host.os.type == "linux" and event.type == "start" and event.action == "connected-to" and
process.name : (
"bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish", "perl", "python*", "nc", "ncat", "netcat", "php*",
"ruby", "openssl", "awk", "telnet", "lua*", "socat"
) and network.direction == "egress" and destination.ip != null and
not cidrmatch(destination.ip, "127.0.0.0/8", "169.254.0.0/16", "224.0.0.0/4", "::1")]
이 규칙은 시간순으로 정렬되지 않은 일련의 이벤트를 설명하고 일치시키는 샘플 기능을 활용합니다. 이렇게 하면 이벤트가 동일한 밀리초 내에 발생하는 경우에도 시퀀스가 트리거됩니다. 또한 화이트리스트 접근 방식을 활용하여 역 연결을 생성할 수 있는 의심스러운 바이너리를 지정함으로써 오탐률을 최소화할 수 있습니다.
당사는 UDP 연결과 관련된 Auditd 데이터를 활용하여 socket() syscall.
a0 값은 도메인을, a1 은 유형을, a2 은 사용된 프로토콜을 나타냅니다. 이 규칙은 auditd.data.a1 == "2" 구문을 활용하며, 이는 UDP인 SOCK_DGRAM 유형으로 변환됩니다.
마지막으로 호스트에서 송신 네트워크 연결만 캡처하고 IPv4 및 IPv6 루프백 주소, IPv4 링크-로컬 및 멀티캐스트 주소를 제외하도록 하고 process.pid 및 process.parent.pid 으로 쿼리를 정렬하여 이벤트가 동일한 (상위) 프로세스에서 발생하는지 확인합니다.
UDP 소켓을 여는 의심스러운 프로세스를 찾고 싶다면 auditd.data.a1 == "2" 으로 모든 socket() syscall을 쿼리하여 고유한 프로세스 발생 수를 세고 오름차순으로 정렬하여 이상 징후를 찾을 수 있습니다. 이를 위해 이 ES|QL 쿼리를 활용할 수 있습니다:
FROM logs-*, auditbeat-*
| EVAL protocol = CASE(
auditd.data.a1 == "1", "TCP",
auditd.data.a1 == "2", "UDP"
)
| WHERE host.os.type == "linux" and auditd.data.syscall == "socket" and protocol == "UDP"
| STATS process_count = COUNT(process.name), host_count = COUNT(host.name) by process.name, protocol
| SORT process_count asc
| LIMIT 100
결과를 살펴보면 흥미로운 프로세스가 꽤 많이 나타나는데, 이는 위협 헌팅을 위한 좋은 출발점이 될 수 있습니다.
잠재적 미터프리터 리버스 셸
Auditd를 활용한 또 다른 흥미로운 유형의 리버스 연결은 메타스플로잇 프레임워크 내에서 널리 사용되는 리버스 셸인 Meterpreter 셸을 탐지한 것입니다. 잠재적 미터프리터 리버스 셸 규칙은 미터프리터의 기본 호스트 열거 동작을 활용하여 그 존재를 감지합니다.
sample by host.id, process.pid, user.id
[file where host.os.type == "linux" and auditd.data.syscall == "open" and auditd.data.a2 == "1b6" and file.path == "/etc/machine-id"]
[file where host.os.type == "linux" and auditd.data.syscall == "open" and auditd.data.a2 == "1b6" and file.path == "/etc/passwd"]
[file where host.os.type == "linux" and auditd.data.syscall == "open" and auditd.data.a2 == "1b6" and file.path == "/proc/net/route"]
[file where host.os.type == "linux" and auditd.data.syscall == "open" and auditd.data.a2 == "1b6" and file.path == "/proc/net/ipv6_route"]
[file where host.os.type == "linux" and auditd.data.syscall == "open" and auditd.data.a2 == "1b6" and file.path == "/proc/net/if_inet6"]
미터프리터가 스폰되면 특정 시스템 파일을 읽어 머신, 사용자, IP 라우팅 정보와 같은 기본 시스템 정보를 수집합니다. 경로가 바이너리에 하드코딩되어 있기 때문에 Meterpreter 페이로드를 디컴파일할 때 이 동작을 확인할 수 있습니다.
저희의 탐지 로직은 auditd.data.a2 == “1b6” 을 활용하는데, 이는 미터프리터의 동작과 일치하기 때문입니다. 미터프리터가 파일 핸들러를 여는 방식을 살펴보면 미터프리터가 이 특정 시스템 호출 조합을 활용하여 파일을 읽는 것을 확인할 수 있습니다.
정보 제공을 위해 미터프리터가 읽어들이는 다른 경로를 아래 스크린샷에서 확인할 수 있습니다.
ES|QL을 활용하여 일련의 Meterpreter 리버스 셸을 분석하고 모든 셸이 액세스하는 파일 경로를 쉽게 찾을 수 있습니다.
FROM logs-*, auditbeat-*
| WHERE host.os.type == "linux" and event.action == "opened-file" and process.name in ("shell-x64.elf", "JBNhk", "reverse.elf", "shell.elf", "elf") and auditd.data.a2 == "1b6"
| STATS file_access = COUNT_DISTINCT(process.name) by file.path
| SORT file_access desc
| LIMIT 100
이 예제에서는 5 Meterpreter 셸만 분석하고 있지만 ES|QL을 사용하면 이 분석을 더 큰 숫자로 쉽게 확장할 수 있습니다. 위의 정보를 바탕으로 탐지 규칙에 선택된 경로가 5개의 샘플 모두에 존재한다는 것을 알 수 있습니다.
위의 논리를 결합하면 잠재적으로 Linux Meterpreter 페이로드를 발견할 수 있습니다.
Linux FTP/RDP 무차별 대입 공격이 탐지되었습니다.
Linux에서 사용할 수 있는 FTP/RDP 클라이언트가 매우 다양하고 인증 로그가 완전히 유사하게 구현되어 있지 않다는 점을 고려할 때 Auditd의 auditd.data.terminal 필드를 활용하여 다양한 FTP/RDP 구현을 감지할 수 있습니다. FTP 감지 로직은 다음과 같습니다:
sequence by host.id, auditd.data.addr, related.user with maxspan=3s
[authentication where host.os.type == "linux" and event.action == "authenticated" and
auditd.data.terminal == "ftp" and event.outcome == "failure" and auditd.data.addr != null and
auditd.data.addr != "0.0.0.0" and auditd.data.addr != "::"] with runs=5
[authentication where host.os.type == "linux" and event.action == "authenticated" and
auditd.data.terminal == "ftp" and event.outcome == "success" and auditd.data.addr != null and
auditd.data.addr != "0.0.0.0" and auditd.data.addr != "::"] | tail 1
여기서는 동일한 호스트, 동일한 IP, 동일한 사용자에 대해 5 로그인 시도 실패와 1 로그인 시도 성공의 순서를 정합니다. 유닉스에서 꼬리표와 유사한 방식으로 작동하는 꼬리표 기능을 활용하여 기간 내에 모든 알림을 선택하지 않고 마지막 X개의 알림을 선택합니다. 이는 SIEM 탐지 규칙 인터페이스에는 영향을 미치지 않으며, 무차별 대입 공격이 많은 경고를 빠르게 유발할 수 있으므로 가독성을 높이기 위한 용도로만 사용됩니다.
vsftpd 와 같은 다양한 FTP 도구를 활용하고 있지만, auditd.data.terminal 항목은 모든 도구에서 유사하게 유지되므로 광범위한 FTP 무차별 대입 공격을 포착할 수 있습니다. RDP 탐지 규칙도 유사한 로직을 활용합니다:
sequence by host.id, related.user with maxspan=5s
[authentication where host.os.type == "linux" and event.action == "authenticated" and
auditd.data.terminal : "*rdp*" and event.outcome == "failure"] with runs=10
[authentication where host.os.type == "linux" and event.action == "authenticated" and
auditd.data.terminal : "*rdp*" and event.outcome == "success"] | tail 1
서로 다른 RDP 클라이언트의 auditd.data.terminal 필드가 일치하지 않는 경우 와일드카드를 활용하여 해당 인증 이벤트를 캡처할 수 있습니다.
RWX 메모리 영역으로 바이너리에서 네트워크 연결
시스템 호출은 mprotect() 시스템 호출은 이미 할당된 메모리 영역의 액세스 보호 기능을 변경하는 데 사용됩니다. 이 시스템 호출을 통해 프로세스는 가상 주소 공간에 있는 페이지의 권한을 수정하여 해당 페이지에 대한 읽기, 쓰기, 실행 등의 권한을 활성화 또는 비활성화할 수 있습니다. 이 탐지 규칙의 목표는 메모리 영역 읽기, 쓰기 및 실행 권한이 설정된 바이너리에서 네트워크 연결을 탐지하는 것입니다. 시스템 호출을 살펴보겠습니다.
탐지 규칙 로직의 경우 prot 값이 가장 중요합니다. prot 에 다음과 같은 액세스 플래그를 가질 수 있음을 알 수 있습니다:
앞서 설명한 대로 prot 는 목록에 있는 값의 비트 단위 OR입니다. 따라서 읽기, 쓰기, 실행 권한의 경우 다음과 같은 int를 찾고 있습니다:
int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
이는 비트 와이징 후 0x7 값으로 변환되므로 auditd.data.a2 == “7”. 이 로직을 활용하는 두 가지 탐지 규칙, 즉 RWX 메모리 영역이 있는 바이너리의 알 수 없는 실행과 RWX 메모리 영역이 있는 바이너리의 네트워크 연결을 만들었습니다. 특정 Auditd 구성을 활용하여 작동하는 탐지 규칙은 해당 설정 가이드에 추가할 규칙에 대한 참고 사항이 있습니다:
이전에는 지정된 기간 내에 이전에 알려지지 않은 용어를 감지할 수 있는 new_terms 규칙 유형을 활용했습니다. 이를 통해 특정 호스트에서 처음으로 보이는 RWX 권한이 있는 바이너리를 탐지하는 한편, 지나치게 허용되지만 정기적으로 사용되는 바이너리에 대한 오탐지를 줄일 수 있습니다.
후자는 다음과 같은 탐지 로직을 활용합니다:
sample by host.id, process.pid, process.name
[process where host.os.type == "linux" and auditd.data.syscall == "mprotect" and auditd.data.a2 == "7"]
[network where host.os.type == "linux" and event.type == "start" and event.action == "connection_attempted" and
not cidrmatch(destination.ip, "127.0.0.0/8", "169.254.0.0/16", "224.0.0.0/4", "::1")
]
이러한 RWX 권한으로 실행되는 프로세스를 샘플링한 후 네트워크 연결(루프백, 멀티캐스트 및 링크-로컬 주소 제외)이 시작됩니다.
흥미롭게도 메타스플로잇은 생성된 페이로드의 특정 영역에 이러한 RWX 권한을 할당하는 경우가 많습니다. 예를 들어, 테스트 스택에서 이 탐지 로직을 트리거하는 이벤트 중 하나는 Linux용 메타스플로잇의 Postgres 페이로드 실행과 관련이 있습니다. 이 페이로드의 소스 코드를 분석해 보면 payload_so 함수가 PROT_READ, PROT_WRITE 및 PROT_EXEC 플래그를 정의하는 것을 확인할 수 있습니다.
그 후 특정 페이지 크기 0x1000 의 특정 메모리 영역에 앞서 설명한 것과 유사한 방식으로 RWX 액세스 플래그가 지정됩니다.
페이로드를 실행하고 스택을 쿼리하면 여러 개의 히트가 반환되는 것을 볼 수 있으며, 모두 Metasploit Meterpreter 페이로드와 관련이 있습니다.
앞서 분석했던 Postgres 페이로드를 중심으로 시각적 이벤트 분석기를 통해 정확한 페이로드 실행 경로를 확인할 수 있습니다. Elastic Security는 프로세스 기반 시각적 분석기를 사용해 Elastic Endpoint에서 탐지된 모든 이벤트를 분석할 수 있으며, 경보로 이어진 프로세스와 그 직후에 발생한 이벤트의 그래픽 타임라인을 보여줍니다. 시각적 이벤트 분석기에서 이벤트를 검사하면 잠재적으로 악의적인 활동의 출처와 손상될 수 있는 환경의 다른 영역을 파악하는 데 유용합니다. 또한 보안 분석가는 모든 관련 호스트, 프로세스 및 기타 이벤트를 드릴다운하여 조사에 도움을 받을 수 있습니다.
분석기에서 perl을 사용하여 /tmp 디렉터리에서 jBNhk 페이로드를 생성 및 채우고(RWX 권한으로) 역방향 Meterpreter 셸을 생성하는 것을 볼 수 있습니다.
결론
이 게시물에서는 Auditd의 정의와 목적에 대해 설명하면서 Auditd의 세계에 대해 알아봤습니다. Auditd를 설정하고 실행하는 방법과 이러한 로그를 Elasticsearch로 전송하여 Unix/Linux 가시성을 높이고 Linux 탐지 엔지니어링 기술을 향상시키는 방법을 보여드렸습니다. 특정 활동을 주시하기 위해 Auditd 규칙을 만드는 방법과 생성되는 이벤트를 이해하는 방법에 대해 논의했습니다. 사용자의 관리 부담을 덜어드리기 위해 Elastic에서 만든 통합 기능인 Auditd Manager를 도입했습니다. 마지막으로, 이 데이터 소스를 최대한 활용할 수 있도록 다양한 탐지 규칙과 이를 만드는 데 사용된 몇 가지 연구를 살펴보면서 마무리했습니다.
이 가이드가 도움이 되셨기를 바랍니다! 보안 가시성을 높이기 위해 Audited를 Unix 시스템에 통합하는 것은 현명한 조치입니다. 미리 빌드된 탐지 규칙을 사용하든, 직접 탐지 규칙을 만들든 Auditd를 사용하면 유닉스 보안을 강화할 수 있습니다.
