기사

Solodit 체크리스트 분석 : 서비스 거부 공격 파트 2

2025-04-15

Solodit 체크리스트 분석 (2) : 서비스 거부 공격 파트 2

스마트 계약에서 서비스 거부 (DOS) 공격을 방지하는 방법에 대해 대기열이 안전하고 소수점이 낮은 토큰을 처리하며 외부 통화를 안전하게 관리합니다.

Solodit 체크리스트 해상도 시리즈에 다시 오신 것을 환영합니다. 우리는 안전하고 탄력적 인 스마트 계약을 작성하기위한 실질적인 전략에 중점을 둔 Solodit Smart Contract Audit Checklist를 계속 탐색 할 것입니다.

이 체크리스트는 잠재적 인 취약점을 식별하고 사전 보안 조치를 구현하는 데 도움이됩니다. 이전 섹션 " Solodit 체크리스트 해상도 (1) "에서는 서비스 거부 (DOS) 공격과 관련된 3 개의 체크리스트 ( 추출 패턴, 최소 거래 금액 및 블랙리스트 )를 검사하고 개발자에게 솔루션을 제공했습니다. 아직 읽지 않았다면 계속하기 전에 기사를 확인하는 것이 좋습니다.

이 기사에서는 체크리스트에서 다른 세 가지 항목에 대해 논의하여 DOS 공격에 다시 집중합니다. 우리는 대기열 취급 취약점 , 소수점이 낮은 토큰으로 제기 된 문제 , 외부 계약 전화를 안전하게 처리하는 것의 중요성 으로 뛰어들 것입니다.

최상의 경험을 보려면 참조를 위해 Solodit 체크리스트 태그를 엽니 다.

간단한 개요

오늘 우리가 논의 할 내용은 다음과 같습니다.

  • SOL-AM-DOSA-4 : 차단 대기열 처리 :이 문제는 공격자가 대기열을 조작하여 작업을 일시 중지하거나 방해하여 DOS를 초래할 때 발생합니다. 우리는 공격자가 처리 대기열을 파괴 할 수있는 방법을 살펴볼 것입니다.

  • Sol-Am-Dosa-5 : 낮은 소수점 토큰 : 소수점이 낮은 자리가있는 토큰을 다룰 때 발생하는 문제. 계산, 특히 분할은 0으로 잘라서 예상치 못한 해로운 행동을 초래할 수 있습니다. 이러한 저지금 토큰은 정수 부서에 문제를 일으킬 수 있으므로 주요 기능을 방해 할 수 있습니다.

  • Sol-Am-Dosa-6 : 안전하지 않은 외부 통화 : 취약점을 만들기 위해 적절한 오류 처리없이 외부 계약에 의존하는 방법을 살펴 봅니다. 외부 통화 실패가 올바르게 처리되지 않으면 전체 계약이 롤백 될 수 있습니다.

실제 공격은 이러한 취약점이 발생할 수있는 잠재적 손상을 입증합니다. 이 프로젝트는 사소한 태만으로 인해 큰 손실을 입었습니다.

Solodit 체크리스트는 감사 결과, 취약점 현상금 보고서 및 실제 이벤트를 기반으로합니다. 이러한 점검 목록을 연구하면 과거의 실수로부터 배우고 코드의 보안을 향상시킬 수 있습니다.

이제 샘플 코드를 통해 각 체크 항목을 하나씩 살펴 보겠습니다. 이러한 예제는 핵심 취약점을 강조하기 위해 단순화되었습니다.

Sol-Am-Dosa-4 : 공격자가 서비스 중단을 일으키기 위해 대기열 처리를 차단하거나 방지 할 수 있습니까?

문제 : 스마트 계약이 작업 처리를위한 대기열에 의존하는 경우, 공격자는 큐의 특정 상태를 조작하여 올바른 처리를 방지 할 수 있습니다.

체크리스트 질문 : "공격자가 서비스 중단을 유발하기 위해 대기열 처리를 차단하거나 방지 할 수 있습니까?"

솔루션 : 큐 취급 메커니즘에는 강력한 오류 처리 및 폴백 메커니즘이 필요하여 문제가 발생하더라도 문제를 계속 처리 할 수 ​​있도록해야합니다.

:

대기열 추출의 예를 고려하십시오.

  1. 사용자는 추출을 요청하고 일부 플래그는 요청이 활성화되어 있음을 나타냅니다.

  2. 공격자는 추출이 발생한 후 resetUserStatus 기능을 사용하여 다른 사용자의 동일한 작동을 방지 할 수 있습니다.

 // 易受攻击的函数:可以被利用function resetUserStatus() external { // 任何人在仍然处于队列中的情况下都可以重置他们的状态withdrawalRequested[msg.sender] = false; // 注意:用户没有被移出队列! } // 处理队列中的下一次提取function processNextWithdrawal() external { require(withdrawalQueue.length > currentIndex, "没有可处理的提取"); // 获取下一次提取Withdrawal memory withdrawal = withdrawalQueue[currentIndex]; // 可被攻击者利用:此检查可能会被重置状态所攻击require(withdrawalRequested[withdrawal.user], "提取请求不再有效"); // 处理提取uint256 amount = withdrawal.amount; require(balances[withdrawal.user] >= amount, "余额不足"); // 更新余额balances[withdrawal.user] -= amount; // 重置提取请求withdrawalRequested[withdrawal.user] = false; // 发送资金(bool success, ) = payable(withdrawal.user).call{value:amount}(""); require(success, "资金发送失败"); // 移动到队列中的下一个currentIndex++; }

이를 활용하기 위해 공격자는 다음을 수행 할 수 있습니다.

  1. 페치 요청을 시작하십시오.
  2. resetUserStatus 기능을 호출하십시오.
  3. processNextWithdrawal 함수가 롤백되어 연속 DOS 공격이 발생합니다.

구제책 :

  • 제한 권한은 관리자에게 withdrawalRequested 상태를 수정하는 것을 제한합니다.
  • 값이없는 거래를 피하려면 점검을 확인하십시오.
  • 예상치 못한 오류를 처리하기 위해 폴백 기능을 구현하십시오.

Sol-Am-Dosa-5 : 소수점이 낮은 토큰이 DOS로 이어질까요?

문제 : 소수점 이외의 장소가있는 토큰은 정수 분열 문제를 일으켜 0으로 반올림 할 수 있습니다.

일정 기간 동안 토큰을 할당하는 토큰 스트리밍 계약을 상상해보십시오. 소수점이 낮은 정수 구분으로 인해 tokensPerSecond 0으로 반올림되면 할당 함수가 차단됩니다. 체크리스트 질문 : "낮은 소수점 토큰이 DOS로 이어 집니까?" 솔루션 : 반올림 오류로 인한 거래 프로세스의 중단을 방지하기 위해 소수점 이하 점수를 처리하는 논리를 구현하십시오. :

특정 수의 토큰을 사용자에게 정기적으로 스트리밍하는 TokenStream 계약을 고려하십시오.

  1. total_tokens 계약으로 이체해야합니다
  2. token_per_second 소수점이 1의 토큰을 사용하고 있기 때문에 0으로 반올림 될 수 있습니다.
  3. distributeTokens 기능이 롤백됩니다
 contract TokenStream { IERC20 public token; uint256 public streamDuration; uint256 public tokensPerSecond; constructor(IERC20 _token, uint256 _streamDuration, uint256 _tokensPerSecond) { token = _token; streamDuration = _streamDuration; tokensPerSecond = _tokensPerSecond; } function distributeTokens(address recipient) external { uint256 balance = token.balanceOf(address(this)); uint256 amount = tokensPerSecond * streamDuration; uint256 tokensToSend = amount > balance ? balance : amount; require(tokensToSend > 0, "没有足够的代币进行流送"); token.transfer(recipient, tokensToSend); } } contract LowDecimalToken is ERC20 { constructor() ERC20("LowDecimalToken", "LDT") { _mint(msg.sender, 100000 * (10 ** decimals())); } function decimals() public view virtual override returns (uint8) { return 1; // 模拟小数点为低的代币} }

이 경우 TokenStreamTesttestDOSWithLowDecimalTokens 테스트가 롤백됩니다.

해결책 : 계약이 낮은 소수점 토큰을 올바르게 처리하고 수학 공식을 확장하여 계산 프로세스 중 정수를 반올림하여 발생하는 문제를 완화하십시오 .

Sol-Am-Dosa-6 : 프로토콜이 외부 계약 상호 작용을 안전하게 처리합니까?

문제 : 많은 스마트 계약은 외부 계약에 의존하여 상호 작용합니다. 외부 계약의 예기치 않은 동작으로 인해 전체 시스템이 롤백 될 수 있습니다 . 이러한 외부 오류를 처리하지 않으면 DOS 취약점이 발생할 수 있습니다.

체크리스트 질문 : "프로토콜이 외부 계약 상호 작용을 안전하게 처리합니까?"

솔루션 : 외부 계약의 성능에 관계없이 프로토콜 무결성을 보호하기 위해 외부 계약 상호 작용에 대한 강력한 오류 처리를 보장하십시오.

: 외부 체인 링크 가격 데이터 소스와 상호 작용하는 계약을 고려하십시오. 적절한 오류 처리를 위해 Try/Catch를 사용하지 않으면 외부 데이터 소스의 롤백이 우수한 것으로 전파되어 계약이 롤백으로 발생합니다.

  1. getPrice 기능은 가격 데이터를 검색합니다.
  2. 외부 체인 링크 Oracle이 실패하면 전체 코드가 롤백됩니다.
  3. calculateSomethingImportant 함수는 getPrice 에 따라 달라지며 롤백됩니다.
 contract PriceDependentContract { AggregatorV3Interface public priceFeed; constructor(address _priceFeed) { priceFeed = AggregatorV3Interface(_priceFeed); } // 易受攻击的函数,在没有处理可能的Chainlink 回滚的情况下获取价格function getPrice() public view returns (uint256) { (, int256 price, , , ) = priceFeed.latestRoundData(); // 易受攻击的行:没有错误处理require(price > 0, "价格必须为正"); return uint256(price); } function calculateSomethingImportant() public view returns (uint256) { uint256 price = getPrice(); // ... 使用价格的一些重要计算return price * 2; }

해결 방법 : 롤백 오류를 처리하고 롤백 또는 캐시 값을 구현하기 위해 외부 계약 전화를 시도/캐치 블록으로 랩합니다 .

참고 : 외부 계약이 의도적으로 가스를 소비하는 에지 케이스가 있으며, 이는 캐치 블록을 실패시킬 수 있습니다! 나중에 이것에 대해 논의하겠습니다.

결론적으로

우리는 스마트 계약의 DOS 공격에 저항하는 능력을 향상시키기 위해 설계된 세 가지 주요 점검을 탐구합니다. 대기열 취급 취약점 , 소수점이 낮은 토큰과 관련된 문제 , 외부 계약 상호 작용을 안전하게 처리하는 것의 중요성 .

제공된 예는 핵심 취약점을 설명하기위한 것임을 기억하십시오. 기본 원칙을 이해 하고 이러한 개념을 특정 사용 사례에 조정하는 것이 매우 중요합니다.

이러한 제안을 구현함으로써 스마트 계약의 보안 및 탄력성을 크게 향상시킬 수 있습니다.

Solodit 체크리스트 해상도 시리즈의 다음 부분을 계속 지켜봐 주시기 바랍니다.

  • 원본 링크 : cyfrin.io/blog/solodit-c ...
  • Denglian Community AI Assistant는 모든 사람을위한 훌륭한 영어 기사를 번역합니다. 번역이 이해할 수없는 영역이 있다면 용서 해주세요 ~

최신 업데이트

인기 기사

게임 추천

소프트웨어 추천