kintex/docs/security/mobile-security-audit.md
zio 214b6df1ef feat(public,security,data): visitor public site + AI guide, security hardening, V42-V45 migrations
- frontend: visitor public home (AiAssistant, AiPlanningBriefing, VisitorTrackPage),
  3-track public routing (PublicShell/App), i18n ko/en/zh/ja, favicon
- backend: public AI visitor-assistant + event calendar API (publicsite/*),
  profile avatar API (auth/profile/*), SecurityConfig CORS whitelist,
  SecretStartupValidator (B12 fail-fast, prod only), application-prod.yml,
  AppIntegrity, /api/auth/me expansion (MeResponse)
- db: V42 bulk demo seed, V43 visitor_guide/transport + event calendar view,
  V44 performance indexes, V45 app_user profile photo columns (all idempotent)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 19:05:00 +09:00

13 KiB

KINTEX AI 모바일 앱 + 백엔드 보안 감사 결과

감사일: 2026-07-12 · 감사자: 통합 QA(reviewer) · 방식: 정적 소스 감사(코드 미수정, 읽기전용) 체크리스트: mobile-security-checklist.md · 개선 백로그: 본 문서 §하단 증거는 파일:라인 표기. mobile/는 다른 에이전트 편집 중이라 스냅샷 기준.

종합 판정

영역 PASS FAIL N-A 총평
1. 위변조 방지 1 5 0 최대 약점 — 루트/디버거/무결성 탐지·난독화 선언 부재
2. 데이터 보호 5 2 0 SecureStore·로그 청결 우수 / FLAG_SECURE·백그라운드 마스킹 부재
3. 통신 보안 2 2 0 HTTPS 강제 / cleartext 차단 선언·피닝 부재
4. 인증·세션 4 1 0 2FA·잠금·RBAC 견고 / 생체 로컬잠금 부재
5. 시큐어 코딩 7 0 0 모범 — SQLi 가드·CSPRNG·스택트레이스 차단 완비
6. 빌드·배포 4 2 0 env 시크릿·오류응답 청결 / 권한 최소화·CORS 명시 보강

전반: 백엔드·시큐어코딩은 공공 기준 대비 견고. 모바일 클라이언트 측 위변조 방지(anti-tampering)와 화면보호가 최대 갭 — 공공 대민 앱 기준(KISA 위변조 항목군)에서 필수 보강 대상.


1. 앱 위변조 방지

ID 판정 위험도 증거 / 근거
AT-1 루트/탈옥 탐지 FAIL High package.json 의존성에 jail-monkey·freerasp·root 탐지 라이브러리 없음(mobile/package.json 13~33). 코드 내 탐지 로직 0건.
AT-2 서명/무결성 FAIL High Play Integrity/App Attest·서명 지문 검증 코드 없음. 리패키징 탐지 부재.
AT-3 코드 난독화 FAIL Med app.json에 jsEngine: "hermes" 미선언(mobile/app.json 2~53) — RN 0.74 기본 Hermes지만 명시·R8 설정 없음. expo-build-properties(R8/ProGuard) 미설치.
AT-4 디버거/에뮬레이터 FAIL Med Frida/디버거/에뮬레이터 탐지 없음.
AT-5 디버그 비활성 부분 PASS Low eas.json production=app-bundle(비디버그 기본, eas.json 18~22). 단 android:debuggable=false 명시·__DEV__ 스트립 확인 필요.
AT-6 개발자모드/USB FAIL Med 개발자옵션·USB 디버깅 감지 없음.

2. 데이터 보호

ID 판정 위험도 증거 / 근거
DP-1 토큰 안전저장 PASS JWT를 expo-secure-store(Keychain/Keystore)에 저장(mobile/lib/secureStore.ts 10~25, mobile/context/AuthContext.tsx 62~66). web만 AsyncStorage 폴백(비네이티브).
DP-2 하드코딩 비밀 0 PASS 시크릿/키/토큰 grep 0건(mobile 전체). config.ts는 base URL만(공개, mobile/lib/config.ts 10~11).
DP-3 비밀번호 미저장 PASS 비밀번호는 요청 body로만 전송, 저장 로직 없음(mobile/lib/auth.ts 26~33, login.tsx 주석 4).
DP-4 화면캡처/오버레이 FAIL Med 2FA/티켓QR 등 민감화면에 FLAG_SECURE 미적용(grep 0건). expo-screen-capture 미설치.
DP-5 백그라운드 스냅샷 FAIL Med 앱 전환 시 민감화면 마스킹 로직 없음.
DP-6 클립보드 보호 PASS(경미) Low 클립보드 강제복사 코드 없음. 티켓/개인정보 필드 클립보드 제어는 별도 검토 권장.
DP-7 로그 민감정보 0 PASS console.log/warn/error grep 0건(mobile 전체). 토큰·비밀번호 로깅 없음.

3. 통신 보안

ID 판정 위험도 증거 / 근거
NW-1 TLS 강제 부분 PASS Med base URL https://kintex.zioinfo.co.kr(mobile/app.json 45, config.ts 11). cleartext http:// grep 0건. 단 Android usesCleartextTraffic=false·networkSecurityConfig 미선언(기본 SDK34 false지만 명시 권장).
NW-2 인증서 검증 PASS 표준 fetch(트러스트스토어 검증), 검증 우회 코드 없음(mobile/lib/api.ts 56~61).
NW-3 인증서 피닝 FAIL Med 인증서/공개키 피닝 미적용. 공공 대민 앱 권고사항.
NW-4 API 키 미노출 PASS 통신에 클라이언트 API 키 없음. Authorization은 런타임 발급 JWT만(mobile/lib/api.ts 52).

4. 인증·세션

ID 판정 위험도 증거 / 근거
AU-1 2FA(TOTP) PASS OTP_REQUIRED→재제출 흐름(mobile/lib/auth.ts 26~38, login.tsx 62~84). 서버 TotpService(HS 라이브러리 codeVerifier, backend security/TotpService.java 46~57).
AU-2 생체·로컬잠금 FAIL Med expo-local-authentication 미설치, 로컬 재잠금 없음(진행 중 내정보 트랙과 연계).
AU-3 세션 만료·재발급 PASS 401 시 메모리 토큰 정리·재로그인 유도(mobile/lib/api.ts 67~70). 서버 TTL env(backend application.yml 67, JwtService 만료 66).
AU-4 로그인 실패 잠금 PASS 임계 초과 시 locked_until 설정, 계정열거 방지 일반화 메시지(backend security/LoginAttemptService.java 34~57). 클라 ACCOUNT_LOCKED 처리(login.tsx 74~75).
AU-5 서버측 RBAC PASS 행사 단위 RBAC를 JWT roles 클레임+컨트롤러 가드로 서버 강제(backend JwtService.java 47~69, SecurityConfig.java 48).

5. 시큐어 코딩

ID 판정 위험도 증거 / 근거
SC-1 입력검증 PASS 클라 검증(login.tsx 53~60, register.tsx 27~30) + 서버 @Valid(GlobalExceptionHandler MethodArgumentNotValid 39~47).
SC-2 SQLi 방지 PASS MyBatis 동적 ${}는 NlQueryReadMapper.xml ${sql} 단 1곳, 결정론적 화이트리스트 가드 통과분만 실행(backend NlQuerySqlGuard.java: 단일SELECT·테이블 화이트리스트·주석/다중문/PII/LIMIT 검증 56~130). 그 외 전부 #{} 바인딩.
SC-3 안전한 난수 PASS OTP IV SecureRandom(backend SecretCipher.java 31,44), OTP secret은 totp SecretGenerator(CSPRNG), 웹훅 HmacSHA256.
SC-4 웹뷰 안전설정 N-A→PASS WebView 미사용(mobile grep 0건). 공격면 없음.
SC-5 딥링크 검증 부분 PASS Low scheme kintex(app.json 6). expo-router 라우팅. 딥링크 파라미터 명시 검증 로직 추가 권장(현재 인증가드로 보호).
SC-6 스택트레이스 미노출 PASS 서버 include-stacktrace/message: never(application.yml 13~14), GlobalExceptionHandler 요약만 반환·스택 미저장(51~62), 401 봉투(SecurityConfig 49~57). 클라 요약 메시지만 노출(api.ts 82~89).
SC-7 암호화 저장 PASS OTP secret AES-256-GCM 봉인(backend SecretCipher.java seal/open 39~77, enc:v1: 포맷).

6. 빌드·배포

ID 판정 위험도 증거 / 근거
BD-1 릴리스 로그/소스맵 PASS(경미) Low console 로그 0건. 소스맵 배포 제외·__DEV__ 스트립은 빌드시 확인 권장.
BD-2 최소 권한 부분 PASS Med app.json에 명시 권한 선언 없음(기본 Expo 권한만). expo-image-picker 사용(package.json 19) → 카메라/사진 권한 발생. blockedPermissions로 불필요 권한 제거 권장.
BD-3 서드파티 취약점 미검증 Med npm audit 미실행(감사 범위상 코드 실행 배제). 의존성 버전은 SDK51 정렬 최신(package.json). CI에 audit 게이트 권장.
BD-4 서버 오류응답 PASS IP/SSH/비밀번호/스택트레이스 응답 미노출(GlobalExceptionHandler, ServerOut 스키마 규칙 준수). error_log 요약 1줄만(51~59).
BD-5 CORS/헤더 부분 PASS Med .cors(cors -> {})에 CorsConfigurationSource 빈 미정의(backend SecurityConfig.java 35) → 명시 허용출처 없음(와일드카드 *도 없음). 운영 도메인 명시 권장.
BD-6 시크릿 주입 PASS(주의) Med JWT_SECRET·KINTEX_OTP_ENC_KEY·DB/SMTP/ADMIN 비번 전부 env 주입(application.yml 27,43,66,76,83). 주의: JWT_SECRET 개발 폴백 CHANGE_ME_DEV_ONLY...(66), OTP 키 미주입 시 개발 파생키 경고(SecretCipher 88) → 운영 env 주입 필수. GEMINI_API_KEY는 워커 전용, 백엔드 미사용(9).

추가 관찰(비차단, 운영 하드닝)

  • 로그 레벨: logging.level.com.zioinfo.kintex: DEBUG(application.yml 106) — 운영 프로파일에서 INFO로 하향 권장(민감 파라미터 verbose 노출 위험).
  • JWT 저장 위치: 웹 타깃만 AsyncStorage 폴백(secureStore.ts 10) — 관람객 B2C 웹뷰/PWA 배포 시 XSS 토큰 탈취면 존재. 네이티브 앱은 무관.
  • 웹훅 인증: /api/webhooks/in/** permitAll이나 토큰+HMAC-SHA256 이중검증·상수시간 비교(WebhookSignature.java MessageDigest.isEqual 58) — 양호.

개선 백로그 (FAIL/취약 → 구현 작업 전환)

담당: 위변조·SecureStore·화면보호·network config = kintex-mobile-dev / 백엔드 = kintex-backend-dev / EAS·빌드설정 = kintex-devops-dev 코드 편집은 각 담당 에이전트가 수행(본 QA는 문서·감사만). SDK51 호환 주의 병기.

P0 (High · 공공 대민 필수)

# 항목 담당 권장 구현 SDK51 주의
B1 AT-1 루트/탈옥 탐지 mobile-dev jail-monkey(isJailBroken/canMockLocation) 또는 freerasp-react-native 도입 → 루팅 단말 경고·민감기능 제한. config plugin으로 prebuild 반영 jail-monkey는 config plugin 필요(bare/prebuild). Expo 관리형은 expo prebuild 또는 dev-client 필요 — devops와 협의
B2 AT-2 앱 무결성 검증 mobile-dev + backend-dev Android Play Integrity API·iOS App Attest 토큰을 로그인/민감 API에 첨부 → backend에서 검증. 서명 지문 확인 Expo 관리형은 네이티브 모듈 → dev-client/prebuild. 서버 검증 엔드포인트 신설
B3 AT-3 난독화 선언 devops-dev app.json android.jsEngine:"hermes"(또는 최상위) 명시 + expo-build-propertiesandroid.enableProguardInReleaseBuilds:true·enableShrinkResources:true expo-build-properties 플러그인 추가·prebuild 필요. Hermes는 RN0.74 기본이나 명시로 회귀 방지
B4 DP-4 화면캡처 방지 mobile-dev expo-screen-capture preventScreenCaptureAsync()를 2FA·티켓QR·개인정보 화면 focus 시 적용 expo-screen-capture SDK51 호환. iOS는 캡처 감지만·Android는 FLAG_SECURE 차단

P1 (Med)

# 항목 담당 권장 구현 SDK51 주의
B5 NW-1 cleartext 차단 명시 devops-dev expo-build-propertiesandroid.usesCleartextTraffic:false 명시 + iOS ATS 유지 확인 prebuild 반영
B6 NW-3 인증서 피닝 mobile-dev + devops-dev react-native-ssl-pinning 또는 build-properties networkSecurityConfig pin-set(SPKI 해시). 백엔드 인증서 갱신 로테이션 절차 병행 피닝 만료/로테이션 운영 리스크 — 백업 핀 2개 이상
B7 DP-5 백그라운드 마스킹 mobile-dev AppState 'inactive/background' 시 오버레이 블러/스플래시 표시(민감 화면) RN AppState + 조건부 렌더
B8 AU-2 생체 로컬잠금 mobile-dev expo-local-authentication으로 앱 재진입·민감작업 시 생체 재인증(내정보 트랙과 통합) SDK51 호환. 폴백(PIN) 설계
B9 AT-4/AT-6 디버거·개발자모드 탐지 mobile-dev freerasp의 debugger/emulator/hooking 탐지 콜백 활용(B1과 통합) B1과 동일 도입 경로
B10 BD-2 권한 최소화 devops-dev app.json android.permissions 명시 + blockedPermissions로 불필요 권한 제거. image-picker 권한 문자열(카메라/사진) 최소화 image-picker는 권한 필요 — 사용처만 요청
B11 BD-5 CORS 명시 backend-dev CorsConfigurationSource 빈으로 운영 도메인(kintex.zioinfo.co.kr·kintex.wise.ai.kr)만 allowedOrigins 명시, 와일드카드 금지 Spring Security 6 lambda DSL
B12 BD-6 운영 시크릿 강제 devops-dev + backend-dev 운영 배포 시 JWT_SECRET·KINTEX_OTP_ENC_KEY env 주입 검증(부재 시 기동 실패 fail-fast 검토), DEBUG 로그 INFO 하향 개발 폴백 값 운영 유입 차단
B13 BD-3 의존성 CVE devops-dev CI에 npm audit --audit-level=high(mobile) + gradle 의존성 스캔 게이트 추가 정기 스캔

P2 (Low · 하드닝)

# 항목 담당 권장 구현
B14 AT-5 debuggable 검증 devops-dev 릴리스 빌드 android:debuggable=false·소스맵 미배포·__DEV__ 스트립 CI 검증
B15 SC-5 딥링크 검증 mobile-dev kintex:// 딥링크 진입 파라미터 스키마 검증·화이트리스트 라우팅
B16 DP-6 클립보드 정책 mobile-dev 티켓QR·개인정보 필드 contextMenuHidden·민감 복사 자동클리어

재검증 게이트(구현 후)

  1. mobile/: jail-monkey/freerasp 도입·screen-capture 적용·build-properties(hermes/R8/cleartext) 반영 → 본 문서 AT-*/DP-4/NW-1 재판정.
  2. backend: CorsConfigurationSource 빈·운영 로그레벨·시크릿 fail-fast → BD-5/6 재판정.
  3. 빌드 회귀: mobile tsc --noEmit EXIT 0, ./gradlew build 통과 확인.