위험 경고: '가상화폐', '블록체인'이라는 이름으로 불법 자금 모집 위험에 주의하세요. — 은행보험감독관리위원회 등 5개 부처
검색
로그인
简中
繁中
English
日本語
한국어
ภาษาไทย
Tiếng Việt
BTC
ETH
HTX
SOL
BNB
시장 동향 보기
zkSNARK 계약 "가명 입력" 허점으로 인해 많은 코인 혼합 프로젝트가 폭발했습니다.
安比(SECBIT)实验室
特邀专栏作者
2019-07-29 07:41
이 기사는 약 4349자로, 전체를 읽는 데 약 7분이 소요됩니다
이 새로운 기술의 물결 속에서 커뮤니티가 과거의 고통스러운 교훈을 충분히 흡수하고 보안 문제에 주의를 기울일 수 있기를 바랍니다.

편집자 주: 이 기사의 출처는 편집자 주: 이 기사의 출처는(ID:secbitlabs)앰비 연구소

다수의 영지식 증명 프로젝트에서 특정 zkSNARKs 계약 라이브러리의 잘못된 사용으로 인해 "입력 별칭" 취약점이 도입되어 인증서 위조, 이중 지출, 재생 및 기타 공격, 공격 비용으로 이어질 수 있습니다. 매우 낮습니다. 가장 일반적으로 사용되는 세 가지 zkSNARKs 영지식 개발 라이브러리 snarkjs, ethsnarks 및 ZoKrates와 최근 인기 있는 세 가지 통화 혼합(익명 송금) 애플리케이션 hopper, Heiswap 및 Miximus를 포함하여 Ethereum 커뮤니티의 많은 오픈 소스 프로젝트가 영향을 받습니다. 솔리디티(Solidity) 언어의 아버지인 크리스가 2년 전 게시한 코드 조각으로 인한 살인 사건이다.

보조 제목

이중 지출 취약점: 초기 노출

Semaphore는 유명한 개발자인 barryWhiteHat의 이전 코인 믹싱 프로젝트에서 진화한 영지식 증명 기술을 사용하는 익명의 세마포어 시스템입니다.

러시아 개발자 Poma는 먼저 프로젝트에 이중 지출 취약점이 있을 수 있다고 지적했습니다[1].

문제는 라인 83 코드 [2]에 있습니다. 자세히 살펴보십시오.

이 함수는 호출자가 계약에서 돈을 인출할 수 있다는 영지식 증명을 구성하도록 요구합니다. "이중 지출"이 발생하지 않도록 함수는 인증서의 지정된 요소가 표시되었는지 여부를 확인하기 위해 "삭제 목록"도 읽습니다. 인증서가 폐기 목록에 있는 경우 계약은 확인이 실패하고 호출자가 돈을 인출할 수 없다고 결정합니다. 개발자는 이러한 방식으로 동일한 인증서를 반복적으로 제출하여 이익을 얻을 수 없으며 이중 지출 또는 재생 공격을 효과적으로 방지할 수 있다고 생각합니다.

이 문제는 2017년으로 거슬러 올라갑니다. Solidity 언어의 발명가인 Christian Reitwiessner는 zkSNARKs 계약 암호화 구현의 예를 제공했습니다[3]. 그 이후로 이더리움에서 zkSNARKs 기술을 사용하는 거의 모든 계약이 이 구현을 따랐습니다. 따라서 다음과 같은 프로세스에 의해 공격을 받을 수 있습니다.

보조 제목

Currency Mixing Application: 이 보안 문제의 가장 큰 타격을 받은 영역

Ethereum에서 영지식 증명 기술의 가장 초기에 널리 퍼진 응용 시나리오는 통화 혼합 계약 또는 익명 전송 및 개인 거래입니다. 이더리움 자체가 익명 거래를 지원하지 않고, 개인정보 보호에 대한 커뮤니티의 요구가 점점 강해지면서 많은 인기 프로젝트가 등장했습니다. 여기서는 혼합 통화 계약의 적용 시나리오를 예로 들어 영지식 프로젝트에 대한 "가명 입력" 취약점의 보안 위협을 소개합니다.

혼합 계약 또는 익명 전송에는 두 가지 주요 사항이 포함됩니다.

1. 돈이 있다는 것을 증명하라

2. 돈이 사용되지 않았음을 증명

이해의 편의를 위해 프로세스에 대한 간략한 설명은 다음과 같습니다.

1. A는 돈을 쓸 것이다.

2. A는 자신이 돈을 소유하고 있음을 증명해야 합니다. A는 해시(HashA)의 사전 이미지를 알고 있음을 증명하기 위해 zkproof를 제시하고 이 해시는 루트로 표시된 트리의 잎에 있으며 이 사전 이미지의 또 다른 해시가 HashB임을 증명합니다. 그 중 HashA는 증인이고 HashB는 공개 진술입니다. A는 HashA를 노출할 필요가 없으므로 익명입니다.

3. 계약은 zkproof를 확인하고 HashB가 폐기 목록에 있는지 확인합니다. 그렇지 않은 경우 돈이 사용되지 않았으며 사용할 수 있음을 의미합니다(이 A 호출은 허용됨).

4. 사용할 수 있는 경우 계약은 HashB를 폐기 목록에 넣어야 합니다. 이는 HashB로 표시된 돈이 사용되었으며 다시 사용할 수 없음을 나타냅니다.

많은 zkSNARKs 계약, 특히 혼합 통화 계약의 핵심 로직은 82행과 83행과 유사하므로 모두 동일한 보안 문제가 있으며 "가명 입력" 취약점을 악용하여 공격받을 수 있습니다.

보조 제목

취약점 분석: 돈의 5배를 익명으로 쓰는 방법은?

위의 verifyProof(a, b, c, input) 함수의 기능은 입력 값에 따라 타원 곡선에 대한 계산 및 검증을 수행하는 것입니다. 코어는 scalar_mul()이라는 함수를 사용하여 타원 곡선에 스칼라 곱셈을 구현합니다. [4].

우리는 이더리움이 타원 곡선에서 암호화 작업을 수행하고 체인에서 zkSNARKs 검증의 가스 소비를 줄이기 위해 사전 컴파일된 여러 계약을 내장하고 있음을 알고 있습니다. 함수 scalar_mul()의 구현은 이더리움 사전 컴파일된 7번 계약을 호출하고 EIP 196[5]에 따라 타원 곡선 alt_bn128에서 스칼라 곱셈을 실현합니다. 아래 그림은 우리가 종종 ECMUL 또는 ecc_mul이라고 부르는 Yellow Paper에서 이 작업의 정의를 보여줍니다.

암호학에서 타원 곡선의 {x, y} 값 영역은 mod p를 기반으로 하는 유한체이며, 이 유한체를 Zp 또는 Fp라고 합니다. 즉, x,y가 Fp의 값인 타원 곡선 위의 점 {x,y}입니다. 타원 곡선의 일부 점은 더 큰 순환 그룹을 형성하고 이러한 점의 수는 그룹의 차수라고 하며 q로 표시됩니다. 타원 곡선 기반의 암호화는 이 순환 그룹에서 수행됩니다. 이 순환 그룹의 차수(q)가 소수이면 Fq로 표시되는 유한 필드 mod q에서 암호화가 수행될 수 있습니다.

일반적으로 더 큰 순환 그룹이 암호화 계산의 기준으로 선택됩니다. 순환 그룹에서 생성자 G로 무한대가 아닌 점을 임의로 선택하고(보통 이 그룹의 차수 q는 큰 소수이므로 0이 아닌 점은 모두 동일함) 다른 모든 점은 G+ G+를 통과할 수 있습니다. .. 생성됨. 이 그룹의 요소 수는 q입니다. 즉, 총 q개의 점이 있으면 0,1,2,3,....q-1을 사용하여 각 점에 번호를 매길 수 있습니다. 여기서 0번째 지점은 무한대에 있는 지점이고, 1번째 지점은 방금 언급한 G이며 기준점이라고도 합니다. 포인트 2는 G+G이고 포인트 3은 G+G+G입니다.

따라서 점을 표현하려는 경우 두 가지 방법이 있습니다. 첫 번째는 이 점의 좌표 {x,y}를 제공하는 것입니다. 여기서 x,y는 Fp에 속합니다. 두 번째 방법은 n*G의 형태로 주는 것이고, G는 public이므로 n만 주면 된다. n은 Fq에 속합니다.

scalar_mul(G1Point point, uint s) 함수 시그니처를 살펴보고 point를 생성기로 사용하고 point+point+.....+point를 계산하고 총 n포인트를 추가합니다. 이것은 위의 두 번째 방법을 사용하여 순환 그룹의 지점을 나타내는 것에 속합니다.

Solidity 스마트 계약 구현에서 uint256 유형을 사용하여 Fq를 인코딩해야 하지만 uint256 유형의 최대값이 q 값보다 크면 다음과 같은 상황이 발생합니다. uint256의 여러 숫자는 에서 mod 연산 값 이후에 동일한 Fq. 예를 들어, s와 s+q는 같은 점, 즉 s번째 점을 나타냅니다. 포인트 q는 실제로 순환 그룹의 포인트 0과 동일하기 때문입니다(각 포인트는 0, 1, 2, 3, ... q-1에 해당함). 마찬가지로 s + 2q 등은 모두 점 s에 해당합니다. 동일한 Fq의 값에 해당하는 큰 정수가 여러 개 입력될 수 있는 현상을 "입력 가명", 즉 이 숫자들이 서로 가명이라고 합니다.

Ethereum 7 계약에 의해 구현된 타원 곡선은 y^2 = ax^3+bx+c입니다. p와 q는 각각 다음과 같다.

여기서 q 값은 위에서 언급한 그룹의 순서입니다. 그런 다음 uint256 유형의 범위에는 총 uint256_max / q가 있습니다. 즉, 동일한 지점을 나타내는 최대 5개의 정수(5개의 "입력 별칭")가 있음을 의미합니다.

따라서 사용자가 철회를 위해 컨트랙트에 영지식 증명을 제시하면 컨트랙트는 input[1](즉, 특정 s)을 무효화 목록에 넣습니다. 사용자(또는 다른 공격자)는 다른 4개의 값을 사용하여 증명을 다시 제출할 수도 있습니다. 이 4개의 값은 이전에 "포기 목록"에 포함되지 않았기 때문에 "위조" 증명이 원활하게 검증을 통과할 수 있으며, 5개의 "입력 가명"을 사용하여 5번의 금액을 사용할 수 있으며, 공격 비용 매우 낮습니다!

보조 제목

영향을 받는 더 많은 프로젝트

그중 snarkjs, ethsnarks, ZoKrates 등을 포함하여 잘 알려진 zkSNARKs 라이브러리 또는 프레임워크 프로젝트가 가장 큰 영향을 미칩니다. 많은 응용 프로그램 프로젝트는 개발을 위해 코드를 직접 인용하거나 참조하여 보안 위험을 묻습니다. 그 결과 앞서 언급한 세 가지 항목이 보안 수정으로 빠르게 업데이트되었습니다. 또한 hopper, Heiswap 및 Miximus와 같이 zkSNARKs 기술을 사용하는 여러 잘 알려진 통화 혼합 프로젝트도 즉시 동기식 수리를 수행했습니다. 이러한 프로젝트는 커뮤니티에서 매우 인기가 있으며 그 중 Heiswap은 "Vitalik이 가장 좋아하는 프로젝트"라고 합니다.

보조 제목

"가명 입력" 취약점에 대한 솔루션

다행히 수정은 간단합니다. 유효성 검사 함수에서 입력 매개변수의 크기에 대한 검사를 추가하기만 하면 입력 값이 위에서 언급한 q 값보다 작아집니다. 즉, "가명을 입력"하는 것은 엄격히 금지되며, 동일한 지점을 나타내기 위해 여러 숫자를 사용하는 것을 방지합니다.

보조 제목

노출된 뿌리 깊은 문제는 반성할 가치가 있습니다.

이 "가명 입력"으로 인한 보안 허점은 커뮤니티에서 진지하게 반성할 가치가 있습니다. 전체 이야기를 다시 검토해 보겠습니다. 2017년에 Christian은 Gist 웹 사이트에 자신의 zkSNARKs 계약 계산 구현을 게시했습니다. 컴퓨팅 라이브러리로서 우리는 그 구현이 보안 문제가 없고 암호학의 상식을 위반하지 않으며 계약에서 증명 검증 작업을 완벽하게 완료한다고 생각할 수 있습니다. 사실, 솔리디티 언어의 창시자로서 크리스천은 분명히 여기에서 낮은 수준의 실수를 범하지 않을 것입니다. 2년이 지난 오늘, 이 코드는 이러한 보안 폭풍을 일으켰습니다. 2년이 넘도록 수많은 동료들과 전문가들이 200줄이 넘는 이 코드를 보거나 사용했을지 모르지만 그들은 아무런 문제를 발견하지 못했습니다.

핵심 문제는 어디에 있습니까? 기본 라이브러리의 구현자와 라이브러리 사용자 간의 프로그램 인터페이스에 대한 이해에 편차가 있을 수 있습니다. 즉, 기본 라이브러리의 구현자는 응용 프로그램 개발자의 부적절한 사용에 대한 고려가 부족하고, 상위 응용 프로그램 개발자는 기본 구현 원칙과 사용 중 주의 사항에 대해 깊이 이해하지 못하고 잘못된 보안 가정을 ​​합니다.

"Input Pseudonym" 취약점은 이전에 자주 노출되었던 "Integer Overflow" 취약점을 떠올리게 하지 않을 수 없습니다. 둘 사이에는 꽤 많은 유사점이 있습니다: 둘 다 많은 개발자의 잘못된 가정에서 비롯됨, 둘 다 Solidity의 uint256 유형과 관련됨, 둘 다 광범위한 영향을 가짐, 숨겨진 튜토리얼 코드 또는 라이브러리 계약도 많이 있음 인터넷에 떠도는. 그러나 "입력 가명" 취약성은 분명히 탐지하기 더 어렵고 대기 시간이 더 길며 더 많은 배경 지식이 필요합니다(복잡한 타원 곡선 및 암호화 이론 포함). SECBIT Lab은 zkSNARK, 영지식 증명 애플리케이션 및 개인정보 보호 기술의 등장으로 커뮤니티에 더 많은 새로운 애플리케이션이 등장하고 숨겨진 보안 위협이 더 많이 노출될 수 있다고 믿습니다. 이 새로운 기술의 물결 속에서 커뮤니티가 과거의 고통스러운 교훈을 충분히 흡수하고 보안 문제에 주의를 기울일 수 있기를 바랍니다.

참조

[1]https://github.com/

[2]https://github.com/

[3]https://gist.github.com/

[4]https://github.com/

[5]https://github.com/

开发者
Odaily 공식 커뮤니티에 가입하세요