메뉴
HN
Hacker News 21일 전

AI가 찾아낸 암호학 라이브러리의 보안 취약점 7종

IMP
7/10
핵심 요약

zkSecurity의 AI 보안 감사 에이전트(zkao)가 Cloudflare의 실험적 암호학 라이브러리(CIRCL)를 분석해 7개의 실제 보안 버그를 발견했습니다. 이 사례는 AI가 오픈소스 보안 취약점 탐지에 얼마나 효과적으로 활용될 수 있는지를 보여줍니다. 발견된 모든 취약점은 현재 상류 저장소(upstream)에서 수정되었으며 해커원(HackerOne)을 통해 포상금도 지급받았습니다.

번역된 본문

우리는 AI 감사 파이프라인을 Cloudflare의 실험적인 암호학 라이브러리인 CIRCL에 투입하여, 임계값 RSA(threshold RSA)에서 발생하는 치명적인 float64 정밀도 손실 문제부터 속성 기반 암호화(ABE)의 접근 제어가 완전히 우회되는 문제까지 총 7개의 실제 버그를 확인했습니다. 현재 이 7개의 버그는 모두 상류 저장소(upstream)에서 수정되었습니다. 이 글은 우리의 AI 에이전트가 오픈소스 암호학 전반에서 발견한 버그에 대한 시리즈의 첫 번째 게시물입니다.

zkSecurity에서 우리는 AI 감사 에이전트인 zkao를 구축하고 있습니다. 목표는 설명하기는 간단하지만 실행하기는 어렵습니다. 바로 다른 AI 도구들이 찾을 수 있는 버그가 남아있지 않을 때까지 AI가 코드를 지속적으로 들여다보게 하는 것입니다. 우리는 이러한 접근 방식이 중요한 이유에 대해 'zkao: 보안의 복리 효과(Security That Compounds)'라는 글에서 다룬 바 있습니다. zkao 구축은 AI가 탐지할 수 있는 모든 버그를 찾아낼 수 있는 자동화된 감사자를 만드는 것을 최종 목표로 하는 반복적인 과정이었습니다. 이를 위해서는 새로운 아이디어와 기술에 대한 브레인스토밍, zkSecurity 보안 연구원들의 전문 지식을 zkao에 체계적으로 인코딩하여 벤치마크에 편향되지 않고 최신의 가장 심각한 취약점을 탐지하도록 만드는 작업이 포함되었습니다. 그리고 무엇보다도 모델이 어떻게 진화하는지, 무엇이 작동하고 무엇이 작동하지 않는지 이해하고 AI를 활용한 버그 탐지에 대한 이해를 높이기 위해 지속적으로 실험을 수행했습니다.

이러한 실험 중 일부는 제품과 무관하게 그 자체로 공유할 가치가 있는 결과물을 만들어냈으며, 이것이 이 시리즈의 주제입니다. 두 번째 동기도 있습니다. 이 실험들은 우리가 zkao를 위한 벤치마크 제품군을 구축하는 방식이며, 그 과정에서 대규모 언어 모델(LLM)이 실제로 암호학을 어떻게 추론하는지에 대한 통찰력을 끊임없이 제공합니다. AI가 날카로운 부분은 어디이고 맹점은 어디인지, 전자를 어떻게 증폭하고 후자를 어떻게 통제할 수 있는지 말입니다. 버그가 눈에 보이는 결과물이지만, 우리가 가장 관심을 두는 부분은 AI의 추론 패턴입니다.

몇 달 전, 우리는 선별된 코드베이스에 대한 실험을 시작했습니다. 우리는 두 가지 구성으로 오픈소스 암호학 프로젝트 몇 개를 스캔하기 위해 LLM을 사용했습니다. 첫 번째는 단순한 프롬프트를 사용하는 'LLM 전용'이고, 두 번째는 우리 팀 전문가가 관리하는 기술을 제공한 '기술이 탑재된 LLM'입니다. 그런 다음 LLM이 실제 취약점을 발견한 중요 프로젝트의 경우, zkao가 동일한 문제를 자체적으로 감지할 수 있는지 확인하기 위해 실행했습니다. 대부분의 경우 zkao는 이 모든 문제를 찾았을 뿐만 아니라 더 복잡하고 심각한 문제도 식별했습니다. 결과가 충분히 좋았기 때문에 이를 글로 작성하기로 결정했습니다.

우리는 고급 및 양자 내성 암호학 라이브러리인 Cloudflare의 CIRCL로 이 시리즈를 시작합니다. CIRCL에서 우리의 파이프라인은 수많은 잠재적 취약점을 도출했으며, 그중 7개는 보고할 가치가 있습니다. 이 7개는 현재 모두 상류 저장소에서 수정되었습니다. 이 중 대부분은 HackerOne의 Cloudflare 프로그램을 통해 확인되었으며 포상금도 받았습니다.

참고로, AI는 최종 보고서가 아닌 잠재적 취약점 결과물을 생성했습니다. 우리 팀의 인간 전문가가 여전히 각 문제를 검증하고, 악용 가능성을 확인하며, 필요한 경우 개념 증명(POC)을 최소화하고 취약점 제보를 처리했습니다. AI가 도출한 잠재적 결과는 얻기 쉽지만 신뢰할 수 있는 보고서는 그렇지 않기 때문에 이러한 인간의 개입(Human-in-the-loop) 과정은 여전히 매우 중요합니다. 이 단계를 최소화하는 것이 zkao를 구축한 주요 목표 중 하나이며, 여전히 작업 중이지만 현재 버전은 이미 이 검증 작업의 상당 부분을 스스로 수행하고 있습니다.

심각도 및 수정 사항 한눈에 보기

세부 내용을 설명하기 전에 짚고 넘어갈 점이 있습니다. AI가 자신이 발견한 취약점에 부여하는 심각도는 다소 들쭉날쭉할 수 있습니다. 다음은 AI가 평가한 각 버그의 심각도와 수정 후 Cloudflare가 확인한 심각도를 보여줍니다. 또한 현재 버전의 zkao가 이 7가지 모두를 일관되게 재현할 수 있는지 확인했습니다.

번호 버그 (취약점) AI 심각도 Cloudflare 심각도 수정 커밋 발견 주체
1 TSS/RSA 다항식 평가에서의 float64 정밀도 손실 치명적(Critical) 낮음(Low) f7d2180 Opus 4.6 + 기술
2 증명자가 제어하는 SecParam을 통한 qndleq 위조 높음(High) 낮음(Low) 757dde4 Opus 4.6 + 기술
3 BLS 집계 시 메시지 고유성 누락 중간(Medium) 높음(High) 9798df7 Opus 4.6 + 기술
4 FillBytes 부호 충돌을 통한 DLEQ 건전성 파괴 높음(High) 낮음(Low) 19848a5 Opus 4.6 + 기술
5 비트별 OR 스위치를 통한 HPKE PSK 검증 우회 중간(Medium) 중간(Medium) (중복) a3b4fa3 GPT-5.3 + 기술
6 TSS/RSA Lagrang...
원문 보기
원문 보기 (영어)
We pointed our AI audit pipeline at Cloudflare's CIRCL experimental cryptography library and confirmed seven real bugs, from a critical float64 precision loss in threshold RSA to a complete access-control break in attribute-based encryption. All seven are now fixed upstream. This is the first post in a series on bugs our agents found across open source cryptography. At zkSecurity we are building zkao , an AI audit agent. The goal is simple to state and hard to do: keep an AI looking at your code, continuously, until no bugs remain that other AI tools can find. We wrote about why that approach matters in zkao: Security That Compounds . Building zkao has been an iterative process, with the end goal of creating an automated auditor capable of finding all bugs that can be detected by AI. This has involved brainstorming new ideas and techniques, systematically encoding the expertise of zkSecurity's security researchers into zkao, ensuring that it detects the latest and most severe vulnerabilities without being biased toward benchmarks, and, importantly, continuously conducting experiments to understand what works, what does not, how models evolve, and to deepen our understanding of bug finding with AI. Some of those experiments produce things worth sharing on their own, independent of the product, and that is what this post series is about. There is also a second motivation. These experiments are how we build a benchmark suite for zkao, and along the way they keep surfacing insights into how LLMs actually reason about cryptography: where they are sharp, where they are blind, and how to amplify the former and contain the latter. While the bugs are the visible output, the reasoning patterns are the part we care about most. A few months ago, we started running experiments on selected codebases. We used LLMs to scan a few open source cryptography projects, in two configurations: LLM only, with a simple prompt. LLM with skills, where the skills were maintained by experts on our team. Then, for the important projects where the LLMs found real vulnerabilities, we also ran zkao to see whether it could have detected the same issues on its own. In most cases, zkao not only found all of them but also identified more complex and more severe ones. The results were good enough that we decided to write them up. We are starting this series with Cloudflare's CIRCL , a library of advanced and post-quantum cryptography. On CIRCL, our pipeline produced many candidate findings, and seven of them are worth reporting here. All seven are now fixed upstream. Most of them were confirmed and awarded bounties under Cloudflare's program on HackerOne . Clarification : the AI produced candidate findings, not final reports. Humans on our team still validated each issue, checked exploitability, minimized the POC where needed, and handled disclosure. That human-in-the-loop step still matters a lot, because AI candidate findings are cheap while trustworthy reports are not. Minimizing that step is one of the main things zkao is built to do, and while it is still a work in progress, the current version already takes on much of this validation work itself. Severities and fixes at a glance One thing worth flagging before the details: the severity an AI assigns to its own finding is noisy. Here is each bug as the AI rated it and as Cloudflare confirmed it once fixed. We also checked that all seven are consistently reproducible by the current version of zkao . # Bug AI severity Cloudflare severity Fix commit Found by 1 float64 precision loss in TSS/RSA polynomial eval Critical Low f7d2180 Opus 4.6 + skills 2 qndleq forgery via prover-controlled SecParam High Low 757dde4 Opus 4.6 + skills 3 BLS aggregate missing message distinctness Medium High 9798df7 Opus 4.6 + skills 4 DLEQ soundness break via FillBytes sign collision High Low 19848a5 Opus 4.6 + skills 5 HPKE PSK validation bypass via bitwise-OR switch Medium Medium (Duplicate) a3b4fa3 GPT-5.3 + skills 6 TSS/RSA Lagrange coefficients in int64 High Medium 751e372 Opus 4.6 + skills 7 CP-ABE access-control break via AND-share bug Critical Critical def2fd3 zkao The gap between the AI severity and the confirmed severity is itself an interesting insight, and we come back to it at the end. Now the seven bugs, one at a time. Bug 1: polynomial evaluation in float64 This one lives in CIRCL's threshold RSA implementation ( tss/rsa ). Threshold signing splits a secret across n players using Shamir-style secret sharing. Deal() evaluates a secret polynomial at each player's index. The coefficients are big.Int , as they should be, but the term x^i was computed like this: // tss/rsa/rsa_threshold.go xi := int64 ( math . Pow ( float64 ( x ), float64 ( i ))) float64 has a 53-bit mantissa. The moment $x^i$ exceeds $2^{53}$ (roughly $9 \times 10^{15}$), the result is silently rounded before it is ever cast back to an integer. For example, with 100 players and a threshold of 27, evaluating at $x = 100$ with $i = 26$ asks for $100^{26} = 10^{52}$, which overshoots $2^{53}$ by 36 orders of magnitude. Even $x = 20$, $i = 16$ already breaks it. The consequence is that the polynomial is evaluated incorrectly, so the key shares handed to players are wrong. Depending on the parameters, signature combination either fails outright or produces shares that look fine but do not reconstruct the intended key. Our agent flagged this as critical , since it results in the generation of incorrect key shares, compromising the correctness of the protocol. Cloudflare ultimately assessed the issue as Low severity, based on the low likelihood of the affected conditions occurring in practice. The fix replaces the floating-point exponentiation with the Horner's-method evaluation the code's own TODO comment had been suggesting all along, keeping everything in big.Int . Commit f7d2180 . Bug 2: a DLEQ proof forgery via a prover-controlled security parameter This one is in zk/qndleq , CIRCL's DLEQ (discrete-log-equality) proof for the subgroup of squares in $(\mathbb{Z}/n\mathbb{Z})^*$. A DLEQ proof attests that two pairs share the same discrete log; if an attacker can make the verifier accept a proof for a false statement, the proof system is broken. The challenge in this proof is derived Fiat-Shamir style, and its bit-length is governed by a SecParam . The problem was that SecParam lived inside the Proof struct itself: type Proof struct { Z , C * big . Int SecParam uint } During verification, the code recomputed the challenge using the proof's own SecParam . That field is attacker-controlled. Set SecParam = 1 and the challenge collapses to a single bit, value $0$ or $1$: a coin flip per forgery attempt. Set SecParam = 8 and brute force is about $2^8 = 256$ attempts. Either way, soundness is gone. This is a clean instance of a recurring pattern: a security parameter that must be fixed by the verifier instead being read out of prover-supplied data. The fix removes SecParam from the proof and makes Verify take it as an explicit argument, so the verifier sets it. Commit 757dde4 . Bug 3: BLS aggregate verification without message distinctness This is the one bug in the batch the AI underrated . The agent labeled it medium. It is in fact a textbook rogue key attack, a widely known critical-class flaw; we reported it as critical, and Cloudflare confirmed it as high. VerifyAggregate in sign/bls implements the BLS BASIC aggregation mode. That mode is only secure if all messages in the batch are distinct, which is its defense against rogue key attacks. The function checked the aggregate pairing equation but never checked that the messages were distinct, leaving that critical requirement to the caller. Without it, the standard rogue key attack applies. An adversary who sees a victim's public key $\mathsf{pk}_v$ and a message $m$ can register $\mathsf{pk}_a = g^{\mathsf{sk}_a} - \mathsf{pk}_v$ and forge an aggregate signature over $(\mathsf{pk}_v, m)$ and $(\mathsf{pk}_a, m)$ without ever knowing the