ACN
dAppOffice
문서 목차 (9 / 16)

09. 보안 고려 사항

원칙

  • 키를 만지지 않는다. 서버 코드 어디에도 개인키·니모닉·서명 로직이 없다. 서명은 100% 지갑 앱에서 일어난다.
  • 클라이언트 입력을 신뢰하지 않는다. 거래 기록 API는 tx hash만 받고 나머지는 체인에서 읽는다.
  • 읽기 전용 백엔드. 백엔드는 체인에 트랜잭션을 보내지 않는다(eth_call, eth_getLogs, 영수증 조회만).

위협과 대응

위협대응
가짜 거래 내역 주입POST는 hash만 수용, 영수증·컨트랙트 주소·Transfer 토픽 검증, status==1 확인
잘못된 컨트랙트로 전송 유도(피싱)토큰 주소는 env로 고정, UI에 전체 주소와 BscScan 링크 표시
잘못된 네트워크에서 서명chainId !== 56이면 전송 비활성 + 전환 버튼
데스크톱 접근서버 UA 게이트(403) + 클라이언트 터치/포인터 게이트
CORS 남용허용 오리진 화이트리스트, 메서드 GET/POST만
RPC 남용/DoSPOST per-IP 레이트리밋(429), ACN 로그가 없는 tx는 블록 조회 생략, 인덱서 배치 제한, 프로덕션은 전용 RPC + 리버스 프록시 레이트리밋
정수 정밀도 손실wei는 문자열(JSON)/bigint(TS)/int(Py)로만 처리
주소 입력 오류isAddress 체크섬 검증, 자기 자신 전송 차단, 단축 주소 + 전체 주소 링크 표시

알려진 한계

  • UA 기반 게이트는 위조 가능하다. "모바일 전용"은 UX 정책이지 보안 경계가 아니다. 자산 안전은 지갑 서명 모델이 보장한다.
  • 인덱서는 head - 15 블록까지만 색인해 일반적인 reorg를 회피하지만, 블록 해시를 검증하지는 않는다. 15블록을 넘는 비정상 reorg가 발생하면 indexer_state를 되감아 재색인해야 한다.
  • POST /api/transfersINDEXER_CONFIRMATIONS 이상 확정된 영수증만 저장한다. 그래도 내역은 표시용이며 자산 상태의 근거로 쓰지 않는다.
  • 데스크톱 UA를 보내는 iPadOS Safari는 서버 게이트에서 차단된다. 이는 "절대 모바일 전용" 정책에 따른 의도된 동작이다.
  • POST /api/transfers에는 프로세스 내 per-IP 레이트리밋(분당 10회)이 있다. 단일 프로세스 기준이므로 다중 워커/다중 인스턴스 운영 시에는 리버스 프록시(Nginx limit_req) 제한을 추가한다. GET 엔드포인트는 프록시 제한에 의존한다.
  • 공용 RPC 장애 시 잔액 조회(지갑 provider 경유)는 되지만 내역 API는 실패한다. UI는 이를 분리해 표시한다.

운영 체크리스트

  • HTTPS 강제, HSTS
  • 백엔드에 레이트리밋(Nginx limit_req 또는 slowapi)
  • 의존성 취약점 점검: npm audit, pip-audit
  • .env, *.db 가 저장소에 없는지 확인 (.envDATABASE_URL에 DB 비밀번호가 들어 있다)
  • pg_dump 백업(/var/lib/acn/backup/)이 root 전용인지 확인 — 덤프에 비밀번호 해시와 TOTP 비밀키가 들어 있다
  • 컨트랙트 소스 검증 여부와 owner 권한(mint/pause/blacklist) 문서화
  • 소액 실전 전송 테스트 후 오픈