이 기사는 Sanket Kanjalkar ( sanket1729 , [email protected] ), Yunqi Li, Yuguang Chen, Joseph Kuo 및 Advisory Andrew Miller ( socrates1024 ) 로 구성된 학생 팀이 조사한 일련의 리소스 고갈 취약점에 대한 공개 내용입니다. Decentralized Systems Lab @ UIUC에서. 이 취약성은 총 26 개 이상의 Proof-of-Stake 암호 화에 영향을 미치고 매우 적은 분량의 네트워크 공격자가 해당 소프트웨어를 실행하는 네트워크 노드를 충돌시킬 수 있습니다. 우리는 2018 년 10 월에 공개 된 자료에 앞서 개발 팀에게 영향을받는 크립토크 (cryptocur)를 알리기 위해 조정 된 공개를 시작했습니다. 대부분 (시가 격별로 가중 됨) 이미 완화가 전개되었습니다.
스테이크 증명 (PoS) cryptocurrencies는 특히 체인 기반 PoSv3 ( Proof-of-Stake 버전 3 )에 기반을 둔 것으로 , UTXO 모델과 가장 긴 체인 합의 규칙을 사용한다는 점에서 Bitcoin과 유사합니다. 주요 차이점은 Proof-of-Work를 동전 소유권 증명으로 대체한다는 것입니다. PoS 접근법의 잠재적 이점은 환경 영향 감소에서부터 51 %의 공격에 대한 향상된 보안에 이릅니다. 사실 많은 cryptocurrencies는 Bitcoin 코드베이스의 포크 (또는 적어도 자손)에 접목되어 있습니다. 그러나 일부 설계 아이디어는 안전하지 않은 채 복사되어 상위 코드베이스에는없는 새로운 취약점이 발생합니다.
우리는 "가짜 스테이크"공격을 발견했습니다. 기본적으로 PoSv3 구현은 귀중한 리소스 (디스크 및 RAM)를 커밋하기 전에 네트워크 데이터의 유효성을 적절히 검사하지 않기 때문에 작동합니다. 결과적으로 많은 지분이없는 (어떤 경우에는 전혀없는) 공격자가 디스크 나 RAM에 가짜 데이터를 채워 피해자 노드가 손상 될 수 있습니다. 우리는 UTXO 및 가장 긴 사슬 증명 스테이크 모델을 기반으로하는 모든 통화가 이러한 "가짜 지분"공격에 취약하다고 믿습니다. 우리가 조사하고 영향을받는 것으로 믿는 cryptocurrencies의 목록은 기사의 끝 부분에 표시됩니다.
이 게시물의 나머지 부분에서는 취약성과 공격에 약간의 미묘한 결과가 있기 때문에 자세히 설명합니다. 뒤늦은 견해에서 결함 자체는 간단하지만 문제를 완전히 해결하는 것은 까다 롭고 지금까지 사용 된 완화 방법은 체인 분할 위험을 야기합니다 (자세한 내용은 나중에 설명).
배경:
취약점에 대한 세부 사항을 설명하기 전에, 우리는 체인 기반의 증거 증명이 어떻게 작동하는지에 대한 관련 부분에 대한 배경 지식을 제공합니다.
지분 증명 (Stake-of-Stake Mining)
Proof-of-Work 마이닝과 마찬가지로 PoS의 마이닝은 블록 헤더의 해시를 난이도 대상과 비교하는 것으로 구성됩니다. PoS의 고차원 목표는 다음 블록을 채굴 할 수있는 각 이해 관계자의 기회가 그들이 통제하는 동전의 수에 비례한다는 것을 보증하는 것입니다. 이를 달성하기 위해, 체인 기반 PoS에서 해시는 블록 헤더뿐만 아니라 이해 관계자가 블록에 삽입 한 특수한 "coinstake"트랜잭션에 포함 된 동전의 양에도 의존합니다. PoS 마이닝의 세부 사항은 다소 복잡 할 수 있으며 earlz의 블로그 게시물 에서 철저한 설명을 볼 수 있습니다 . 이 게시물에서 중요한 것은 PoS를 확인하는 것은 1) coinstake 트랜잭션과 2) coinstake 트랜잭션에 의해 소비 된 UTXO에 달려 있다는 것입니다.
블록 유효성 검사 자원 보호에 대한 Proof-of-Work의 역할 :
Bitcoin 합의에서 Proof-of-Work (PoW)가 중요한 역할을한다는 것은 잘 알려져 있습니다. 그러나 Proof-of-Work는 디스크, 대역폭, 메모리 및 CPU와 같은 노드의 제한된 리소스에 대한 액세스를 지키는 두 번째 다소 덜 감사 된 역할을 수행합니다. 무의미한 암호 해독 네트워크에서 피어는 신뢰할 수 없어야합니다. 따라서 리소스 고갈 공격을 방지하기 위해 Bitcoin 노드는 블록을 RAM 또는 디스크에 저장하는 등 더 많은 리소스를 커밋하기 전에 먼저 수신 된 블록에 대해 PoW를 확인합니다. 그러나, Proof-of-Stake를 검사하는 것은 Proof-of-Work를 검증하는 것보다 훨씬 복잡하고 상황에 민감합니다. 결과적으로, 많은 체인 기반 PoS 구현은 적절한 유효성 검사를 생략했습니다.
이것이 리소스 고갈 취약점을 초래하는 방법을 이해하려면 유효성을 검사하기 전에 블록을 저장하는 방법에 대한 세부 정보를 제공해야합니다. 노드는 현재 순간에서 가장 긴 체인뿐만 아니라 포크 체인 트리를 추적해야합니다 (노드 중 하나가 가장 긴 체인으로 판명 될 수 있습니다.이 경우 노드는 노드로 전환하기 위해 "재구성"해야 함) ). 예를 들어 업그레이드가 불량하거나 이중 지출 공격 ( ETC 51 % 미만 공격 ) 또는 임시 네트워크 파티션에서 발생할 수 있습니다 .
이러한 주요 체인 블록을 검증하는 것은 어렵습니다. 블록의 유효성을 완전히 확인하려면 이전 블록 당시 미사용 동전 (UTXO) 세트가 필요합니다. 비트 코인 (Bitcoin)은 UTXO가 최선의 체인의 현재 팁을 유지하도록 설정하지만 포크를 시작할 수있는 다른 모든 과거 블록에 대해서는 설정하지 않습니다. 포크에서 블록을 완전하게 검증하는 데는 크게 두 가지 방법이 있습니다.
포크가 시작되기 전에 현재 뷰 (UTXO 세트)를 "롤백"하거나
모든 이전 블록에 대해 설정된 UTXO 복사본을 저장합니다.
Bitcoin의 코드베이스는 옵션 2를 지원하지 않으며 추가 스토리지 비용을 부과합니다 (Bitcoin 노드 성능은 불필요한 데이터를 적극적으로 정리하는 방식을 사용합니다). 옵션 1은 Bitcoin 코드베이스가 현재 reorg를 처리하는 방법입니다. 그러나 이것은 매우 비쌀 수 있으므로 롤백 및 전체 유효성 검사는 포크의 작업 증명이 이미 현재 주 체인보다 큰 마지막 순간으로 연기됩니다. 따라서 피어가 처음으로 가장 긴 체인의 일부가 아닌 블록이나 헤더를 수신하면 전체 유효성 검사가 생략되고 블록이 로컬 스토리지에 저장됩니다.
Bitcoin 코드베이스는 블록을 디스크에 저장하기 전에 PoW (트랜잭션 무시)를 기반으로 사전 검증을 수행합니다. 이 예비 검사는 이전 블록 헤더 및 현재 헤더에만 의존하기 때문에 노드가이를 신속하게 수행 할 수 있습니다. 그리고 그것을 통과하는 유효한 PoW를 생성하는 것이 매우 비싸기 때문에 효과적인 방어입니다. 예를 들어, Bitcoin 노드를 사용하여 디스크에 잘못된 블록을 저장하도록 유도 할 수는 있지만 이렇게하면 자원 고갈 공격을 탑재하는 데 엄청난 비용이 듭니다.
PoS의 유사한 사전 점검은 coinstake 트랜잭션의 유효성을 검사하고 이전 블록의 커널에 해시 할 때 난이도 목표를 통과하는지 확인하는 것입니다. coinstake 트랜잭션의 해시를 계산하는 것은 쉽지만, 어려운 부분은 앞에서 언급했듯이 과거 블록에 사용할 수없는 UTXO 집합을 확인해야하므로 coinstake 트랜잭션에 대한 입력 UTXO가 유효하고 사용되지 않았는지 확인하는 것입니다. coinstake 트랜잭션을 완벽하게 검증하는 것이 어렵 기 때문에 대부분의 체인 기반 PoS 구현은 경험적 또는 근사적인 검사를 제공합니다. 이러한 근사값은 종종 부적절하고 악용 될 수 있습니다.
취약성 # 1 : "나는 스테이크가 아니라고 믿을 수 없다"
이 문제를 처음 조사했을 때 Qtum, Particl, Navcoin, HTMLcoin 및 Emercoin과 같은 5 개의 크립토크 통화가이 취약점에 대해 매우 사소한 것으로 나타났습니다. 즉, RAM으로 블록을 보내기 전에 coinstake 트랜잭션을 전혀 확인하지 못했습니다 또는 디스크. 이 다섯 가지 cryptocurrencies가 공통적으로 가지고있는 것은 Bitcoin의 "헤더 우선"기능을 채택한 것입니다.이 기능에서는 블록 전파가 두 개의 별도 메시지 인 블록 및 헤더로 분리되었습니다. 노드는 헤더가 PoW 검사를 통과하고 가장 긴 (또는 더 긴) 체인 인 후에 만 블록을 요청합니다. coinstake 트랜잭션은 Header가 아니라 Block에만 있기 때문에 노드는 Header를 자체적으로 유효성을 검사 할 수 없습니다. 대신 헤더를 메모리 내 데이터 구조 (mapBlockIndex)에 직접 저장합니다.결과적으로 모든 네트워크 침입자는 아무런 지분이 없더라도 피해자 노드의 RAM을 채울 수 있습니다.
이 공격의 두 번째 변형은 약간 다른 방식으로 작동하고 RAM이 아닌 희생자의 디스크라는 다른 리소스를 대상으로하기는하지만 동일한 코드베이스에 대해 수행 할 수 있습니다. 의심 할 여지없이 디스크 관련 공격이 피해자에게 더 해롭다. RAM이 가득 차고 노드가 충돌하면 간단히 다시 시작할 수있다. 그러나 디스크가 꽉 찬 경우 수동 개입이 필요합니다 (예 : 디스크에서 오래된 블록을 정리하기 위해 외부 스크립트 를 실행하는 경우 ).
헤더를 수신하기보다는 블록을 수신 할 때 다른 예비 검사가 수행됩니다. 이상적으로는 블록 에 coinstake 트랜잭션 이 포함되어 있기 때문에 노드 소프트웨어는 블록을 디스크에 커밋하기 전에 coinstake 트랜잭션을 확인해야합니다. 그러나 언급 한 바와 같이 블록이 포크 상에있는 경우 노드가 coinstake 트랜잭션에 소비 한 UTXO에 액세스하는 쉬운 방법이 없습니다. 아마도 이러한 이유 때문에 이러한 코드베이스는 coinstake 트랜잭션의 유효성을 검사하지 않습니다.
이 취약점 중 하나를 악용하는 것은 영향을받는 암호 해독에 아무런 지분을 갖지 않고 수행 될 수 있습니다. 공격의 RAM 버전은 특히 사소한, 그러나 기술적 인 이유로, 공격의 디스크 버전 (약간 더주의를 필요로 여전히 이해 관계가 필요하지 않습니다하지만) . 자세한 내용은 Financial Cryptography 2019 에서 제공되는 간단한 보고서에 설명되어 있습니다 .
취약성 # 2와 소비 스테이크 공격
이러한 코드베이스의 계보를 추적하면 Bitcoin의 "머리글 우선"기능을 PoSv3 코드베이스에 병합 할 때 취약점 # 1이 원래 도입 된 것으로 나타났습니다. 디스크에 블록을 저장하기 전에 두 가지 예비 검사가 추가되기 때문에 이전 버전 (예 : Peercoin)에서는 공격이 작동하지 않습니다.
쓰이는 출력이 주 체인에 있는지 확인하십시오.
PoS 커널 해시가 난이도 목표를 충족하는지 확인하십시오.
확인 1은 현재 주 체인에있는 모든 트랜잭션을 지금까지 추적하는 트랜잭션 데이터베이스 (TxDB)의 조회를 통해 수행됩니다. 즉, 예비 유효성 검사는 유효성 검사보다 우수하지만 유효성 검사의 발견 적 및 불완전한 근사값입니다. 지금까지 설명을 따르고 있다면 두 가지 우려가 곧 풀릴 수 있습니다.
우려 사항 A : 확인 1은 동전이 있음을 보장하지만 사용하지 않은 것은 아닙니다. 이 통찰력은 곧 우리가 다음에 토론 할 취약점에 이르게합니다.
우려 B : 주 체인 포크에있는 블록의 유효성을 검사한다고해도 coinstake 트랜잭션은 주 체인 자체의 TxDB에 대해 유효성이 검사됩니다.
Concern A를 기반으로, 우리는 " 지출 한 지분 공격 "이라고 부르는 더 미묘한 공격을 사용하여 이러한 점검을 속이는 방법을 발견 했습니다 . Check 1을 해결하기 위해 노드에서 보았지만 이미 소비 된 결과를 사용합니다 . 일반적으로 Check 2를 해결하기 위해 난이도 목표를 통과하는 유효한 블록을 채굴해야하며, 많은 양의 지분이 필요할 것입니다. 그러나 우리는 불확실한 검증을 남용하여 " 스테이크 증폭 "이라고하는 기법을 사용하여 임의의 양의 명백한 스테이크를 생성 할 수 있습니다 .
스테이크 증폭
소액의 스테이크에서 시작하여 공격을 수행하려면 공격자가 명백한 스테이크의 양을 증폭시켜야합니다. 명백한 스테이크 란 이미 후보자 스테이크 산출물 전체를 의미하며 이미 소비 된 스테이크 산출물도 포함됩니다. 공격자가 양 k 의 UTXO로 시작 하면 공격자는 아래 그림과 같이 공격자에게 동전을 소비하는 여러 트랜잭션을 생성 할 수 있습니다. 위킹에는 UTXO (n + 1 ) 만 허용되어야하지만 위의 체크 2로 인해 1 에서 n + 1 까지의 모든 UTXO와 관련 지을 수 있으므로 명백한 지분을 n * k 만큼 증가시킬 수 있습니다. 이것은 PoS 블록을 찾는 기회를 증가시킵니다. 왜냐하면 공격자는 자신의 명백한 스테이크를 늘리기 위해 이것을 계속할 수 있기 때문입니다. 이것은 아래 그림의 왼쪽에 " 스테이크 증폭 단계 "로 설명되어 있습니다.
예를 들어 시스템의 지분이 0.01 % 인 경우에도 공격자는 지주력이 50 % 인 블록을 채광하는 데 5000 건의 트랜잭션 만 필요합니다. 공격자가 많은 양의 명백한 스테이크를 수집 한 후 그는 새로 수집 된 명백한 스테이크 아웃풋을 사용하여 과거에 PoS 블록을 채취 합니다. 마지막으로, 공격자는 위 그림의 오른쪽에 표시된대로 유효하지 않은 블록으로 피해 피어의 디스크를 채 웁니다. 공격자는 예를 들어 교환기에서 동전을 몇 개 사 고 설명 된대로 자체 지출을 통해 지분을 증폭 한 다음 해당 동전을 교환기에 다시 판매하여 나중에 언제든지 공격을 수행 할 수 있습니다. 공격자에게 발생하는 유일한 비용은 거래 비용입니다.
조정 된 취약점 공개
우리는 먼저 Particl 및 Qtum cryptocurrencies의 맥락에서 취약점 # 1을 조사했습니다 .¹이 취약점의 범위를 확인하기 위해 시만텍별로 coinmarketcap.com (2018 년 8 월 9 일)에서 알려진 cryptocurrencies 목록을 수집했습니다. 체인 기반 PoS 컨센서스 유형으로 필터링. 우리는 코드베이스가 Bitcoin (즉, C의 자손)에서 분기 된 cryptocurrencies만을 보았습니다. 전체적으로 우리는 26 개의 크립토 통화를 조사한 결과 5 개의 크립토크 통화 (Qtum, Navcoin, HTMLcoin, Emercoin 및 Particl) 만 영향을 받았다는 사실을 발견했으나 나머지 공격에는 영향을 미치지 않았습니다. 취약점을 확인하기 위해 영향을받는 5 개의 코드베이스 각각 에 대해 공격을 구현했습니다 . Bitcoin 소프트웨어의 기존 테스트 스위트, 특히 regtest를 사용했습니다.모드는 시뮬레이션 된 타임 스탬프와 생성하기 쉬운 블록을 가능하게하며, 파이썬 기반 테스트 노드 ( 비트 코인 TestFramework 기반 )는 공격자의 행동으로 확장 될 수 있습니다. Docker 컨테이너를 사용하여 이러한 테스트, 종속성 및 특정 커밋 해시가 영향을받는 5 개 개발자 팀과 쉽게 공유 할 수있는 재사용 키트의 영향을 받아 취약성 공개의 일환으로 패키지되었습니다.
그런 다음 영향을받지 않은 크립토크 통화가 첫 번째 공격에 취약하지 않은 이유를 더 깊이 파고 취약성 # 2가 거의 심각하다는 사실을 알았지 만 (최소 금액의 지분 필요), 훨씬 더 보급되었습니다. 조정 된 책임 공개를 계획 할 때, 우리는 경제 활동이 낮은 크립토크 통화 및 비활성 개발자 팀에 공개하는 것이 비생산적인 것으로 간주했습니다. 예를 들어, 취약점이 누출되면 다른 사람에게 영향을 줄 수 있습니다. 완화 배치 시간). 궁극적으로 우리는 공격받을 가능성이 가장 높은 cryptocurrencies (상위 200 개의 cryptocurrencies 중)와 관련된 15 개 개발자 팀과의 의사 소통에 중점을두고 대응할 수 있도록 결정했습니다 (2018 년 일부 커밋 활동).
하나의 복잡한 요소는 이러한 코드베이스의 대부분이 regtest 모드와 함께 제공되지 않았기 때문에 공격을 쉽게 입증 할 수 없거나 각각의 코드에 대해 재현성 키트를 제공 할 수 없다는 것입니다. 따라서 우리는 stratisX의 C ++ 코드베이스에 대한 데모만을 제공했습니다. 코드베이스의 유사성을 기반으로, 우리는 영향을받을 것으로 믿는 15 개 팀 모두에게 알렸다. 5 개 팀이 취약점을 인정했으며 3 명은 여전히 조사 중이며 3 명은이를 반박하고 (완화 효과가있는 구현 변경을 지적 함) 4 팀은 응답을 제공하지 않았습니다. 응답하지 않은 4 개 팀의 경우 해당 웹 사이트에서 찾을 수있는 채널을 통해 해당 팀에 연락했습니다 .5 두 가지 취약점에 대한 Github 재현성 키트는 여기 에서 찾을 수 있으며 취약성 # 1에 대한 간단한 보고서는 여기 에서 찾을 수 있습니다. 우리는 또한 곧 공개되어야하는 취약점에 대한 CVE를 예약했습니다.
완화 방법
우리는 공개에 대한 응답으로 팀이 구현 한 다양한 완화 조치를 보았습니다. 일부 cryptocurrencies는 공격을 탐지하고 위반하는 피어와의 연결을 끊는 완화 방법을 구현했습니다 .² 간단히 말해 노드는 피어에게 비정상적인 동작 (예 : 포크에서 많은 헤더 전송)을 모니터링합니다. 그러한 경험적 방법의 문제점은 합법적 인 reorg를 경험 한 정직한 노드에서 실제 공격을 구별하는 것이 어렵다는 것입니다. 정직한 노드를 실수로 금지 할 위험이 있습니다. 지금까지 살펴본 완화 조치는 합리적인 것처럼 보이지만 추가 조사가 필요한 분야입니다.
일부 다른 cryptocurrencies는 고정 길이까지 부분 유효성 검사를 추가했습니다. ¡ 피어가 그 길이를 지나서 주 체인에서 분기 한 블록을 수신하면 블록이 단순히 삭제됩니다. 이 접근법은 예를 들어 10 블록 롤링 체크 포인트를 사용하는 BCH (Bitcoin Cash)의 ABC 코드베이스에서도 사용됩니다. 이 방법의 단점은 "체인 분할"의 가능성을 소개한다는 것입니다. 체인 분할은 정직한 노드가 블록 체인의 서로 다른 분기 포크로 끝날 때 발생합니다. 예를 들어 네트워크 연결 상태가 좋지 않아서 충돌하는 체크 포인트를 만들 충분한 시간 동안 노드가 서로 동기화되지 않으면이 문제가 발생할 수 있습니다. 노드가 다시 연결 되더라도 체인의 공통보기에 도달 할 수 없습니다. 이 완화 조치 없이도 체인 분할 위험이 있음을 알 수 있습니다.
체인 분할 위험은 또한 적대적인 광부에 대한 새로운 공격 경로를 도입합니다. 공격자는 긴 체인을 비밀리에 채굴하여 체인 분할을 일으키기 위해 노드의 하위 집합에 게시하려고 시도 할 수 있습니다. IBD (초기 차단 다운로드)의 노드 또는 오랜 오프라인 기간 후에 방금 재시작 한 노드는이 공격에 특히 취약합니다. 이러한 공격은 일식 공격 과 결합하여 정직한 노드를 공격자가 제어하는 사슬로 유도 할 수 있습니다 .
이러한 모든 완화 방법으로 인해 공격을 수행하기가 어려워 지지만 전체 유효성 검사를 대신 할 수는 없습니다. Qtum과 같은 일부 cryptocurrencies는 향후 릴리스에서 오프 - 체인 체인 블록의 전체 유효성 검사로 이동할 계획입니다.
다음 영향을받는 크립토 통화의 사용자는 노드를 최신 패치 소프트웨어로 업데이트하고 패치되지 않은 노드에서는이 취약점을 악용하여 RAM 또는 디스크 사용량이 증가하고 충돌이 발생할 수 있음을 알아야합니다.
아래 표는 위의 두 가지 취약점 중 하나가 영향을받는 것으로 판단되는 통화를 보여줍니다. 우리는 아직 모든 통화에 대한 취약성을 검증하지 않았으며 우리가 청구를 반박 한 통화가 영향을받지 않는 이유를 아직 검토하지 않았습니다.
마지막 생각들
"가짜 스테이크"공격은 원칙적으로 간단하지만 어려운 작업이라는 어려운 점을 강조합니다. 작업 현장에서 의미가있는 일부 아이디어는 스테이크를 안전하게 해석하지 못합니다. Bitcoin Core에서 PoSv3 cryptocurrencies 중 "업스트림"으로 높은 수준의 코드 공유를 감안할 때, 우리는 이것이 더 엄격한 조사가 필요하다고 생각합니다. 이러한 취약점을 조사하는 동안 다양한 완화 및 특별 방어를 목표로하는 진행중인 작업 코드 모음 (또는 주석 코드)에 따라 여러 가지 코드 예제를 찾아 냈습니다. 우리에게 이것은 PoS 개발자들 사이에서이 디자인 공간의 트레이드 오프와 요구 사항이 아직 완전히 이해되지 않았 음을 알리는 것입니다. 문제는 한편으로는 가능한 한 빨리 유효하지 않은 블록을 거부하려고하지만 다른 한편으로는, 우리는 체인 분할에 집착하거나 실제로 주 체인을 처리하는 데 지연되기를 원하지 않습니다. 이것에 대처하는 체계적인 방법은 미래의 일을위한 열린 문제로 남아 있습니다.
가장 최근의 사례 (예 : BTC의 CVE 2018-17144 )가 적어도 두 개의 코드베이스에 영향을 미쳤지 만이 사실은 많은 수의 (20 개 이상의) 독립 크립토 통화에서 처음으로 조정 된 보안 취약점 공개입니다. cryptocurrencies 전반에 걸친 아이디어와 코드 재사용의 교차 수분량을 감안할 때 앞으로는 이와 같은 취약점이 더 많이 발생할 것으로 예상됩니다. 우리는 이러한 코드베이스간에 보안 프로세스의 일관성이 거의 없다는 것을 발견했습니다. 예를 들어, 대부분의 경우 전용 보안 연락처가 없었습니다. 조정 된 공시를위한 모범 사례를 수립하는 것은 전반적인 생태계에 도움이 될 수 있습니다.
[1]이 취약점에 대한 아이디어는 Andrew Miller가 Unit-E 개발자와 함께 작업하는 동안 2018 년 여름에 시작되었습니다. 우리는 Matteo Sumberaz와 Gil Danziger에게 도움이되는 토론과 DTR Foundation ( https://dtr.org/ ) 연구 보조금에 감사드립니다 .