Frida 메모리 점검: 개인정보 노출 점검하기 2026
iOS 앱에서 로그인이나 결제 기능을 개발하다 보면 한 번쯤 이런 의문이 생깁니다. 사용자가 입력한 비밀번호, 서버에서 내려온 토큰, 휴대폰번호나 계좌번호가 화면에서 사라진 뒤에도 앱 메모리에 평문으로 남아 있지 않을까 하는 의문입니다.
저도 결제 관련 iOS 앱의 보안 점검을 진행하면서 이 부분이 궁금해졌습니다. 탈옥 감지나 앱 변조 대응도 중요하지만, 그보다 먼저 앱 내부에서 다루는 민감정보가 불필요하게 남아 있지는 않은지 확인할 필요가 있었습니다.
그래서 이번에는 탈옥한 iPhone과 Frida를 이용해 Frida 메모리 점검을 직접 진행했습니다. 처음에는 Frida attach조차 되지 않았고, SSH 접속 주소도 잘못 이해해 시간을 꽤 썼습니다. 하지만 연결 문제를 해결한 뒤에는 로그인 전후와 로그아웃 이후에 비밀번호, 토큰, 개인정보가 메모리에 남는지 확인할 수 있었습니다.
이 글은 제가 직접 진행한 Frida 메모리 점검 경험을 바탕으로, iOS 앱에서 민감정보 노출을 어떻게 확인했는지 정리한 기록입니다. 본인이 개발했거나 테스트 권한이 있는 앱과 테스트 계정에서만 진행해야 합니다.

Frida 메모리 점검을 시작한 이유
처음 보안 점검을 시작했을 때는 탈옥 단말에서 앱이 정상적으로 차단되는지만 확인하려고 했습니다. 그런데 테스트를 진행하다 보니 더 근본적인 문제가 눈에 들어왔습니다.
앱에서는 다음과 같은 정보를 다룰 수 있습니다.
- 로그인 아이디와 비밀번호
- Access Token, Refresh Token 같은 인증 정보
- 휴대폰번호와 이메일
- 계좌번호와 카드번호
- 결제 과정에서 사용하는 인증값
- 사용자정보 API 응답에 포함된 개인정보
이 값들은 API를 호출하거나 화면을 표시하는 과정에서 한 번은 메모리에 올라갈 수밖에 없습니다. 문제는 사용이 끝난 뒤에도 계속 남아 있거나, UserDefaults, 클립보드, 파일 같은 위치에 불필요하게 기록되는 경우입니다.
특히 결제 앱이나 사내 서비스처럼 개인정보와 인증 정보를 다루는 앱이라면, 단순히 기능이 정상 동작하는지만 볼 것이 아니라 다음을 함께 확인해야 합니다.
- 비밀번호가 로그인 완료 후에도 메모리에 남아 있는가?
- 인증 토큰이 보호되지 않은 저장소에 기록되는가?
- 사용자정보 API 호출 후 휴대폰번호나 계좌정보가 평문으로 검색되는가?
- 로그아웃 이후에도 민감정보가 제거되지 않는가?
저는 이 질문에 직접 답을 얻기 위해 Frida 메모리 점검을 진행했습니다.
테스트 환경과 준비 사항
이번 점검은 실제 사용자 데이터가 아닌 테스트 계정과 테스트 값을 사용했습니다. 메모리 검사 결과나 터미널 화면을 캡처할 수 있기 때문에, 운영 데이터로 테스트하면 점검 과정 자체가 새로운 노출 경로가 될 수 있습니다.
| 항목 | 내용 |
|---|---|
| 테스트 대상 | 직접 개발·테스트 권한이 있는 iOS 결제 샘플 앱 |
| 테스트 기기 | 탈옥한 iPhone |
| 탈옥 환경 | Dopamine |
| 연결 방식 | Mac과 iPhone USB 연결 |
| 분석 도구 | Frida, Frida CLI |
| 점검 데이터 | 테스트 아이디, 테스트 비밀번호, 테스트 토큰, 테스트 개인정보 |
| 점검 목적 | 메모리와 저장 과정에서 민감정보 평문 노출 여부 확인 |
테스트 전에 확인한 원칙
- 실제 사용자 계정과 개인정보는 사용하지 않습니다.
- 결과 화면을 캡처할 때는 값을 마스킹합니다.
- 본인이 개발했거나 보안 테스트 권한이 있는 앱에서만 수행합니다.
- 계좌번호처럼 규칙만으로 확정하기 어려운 값은 테스트 데이터와 일치할 때만 결과로 판단합니다.
Frida 메모리 점검 전, Frida attach가 되지 않았던 경험
처음에는 Mac에 Frida CLI를 설치한 뒤 바로 앱 프로세스에 연결할 수 있을 것이라고 생각했습니다.
먼저 실행 중인 앱을 확인했습니다.
frida-ps -Uai | grep -i "결제샘플앱"
앱의 PID와 번들 ID는 정상적으로 조회되었습니다.
837 결제샘플앱(Dev) com.sample.app
그래서 조회된 PID로 바로 attach를 시도했습니다.
frida -U -p 837
하지만 결과는 실패였습니다.
Connected to iPhone
Failed to attach: unable to attach to the specified process
여기서 처음에는 USB 연결 문제라고 생각했습니다. 그러나 frida-ps -U에서 앱 목록이 보인다는 것은 Mac이 iPhone 자체는 인식하고 있다는 의미였습니다. 이후 확인해 보니 탈옥한 iPhone 안에도 Frida 패키지가 설치되어 있고 정상적으로 동작하는지 살펴봐야 했습니다.
iPhone SSH 접속에서 가장 헷갈렸던 부분
iPhone 내부에서 Frida 실행 상태를 확인하려면 SSH 접속이 필요했습니다. 이 과정에서 제가 가장 헷갈렸던 부분은 접속 주소였습니다.
처음에는 다음처럼 접속하려고 했습니다.
ssh -p 2222 mobile@192.0.0.2
하지만 iproxy를 사용한 USB 포트포워딩 방식에서는 이 주소로 접속하는 것이 아니었습니다.
Mac에서 다음 명령을 실행하면:
iproxy 2222 22
Mac의 로컬 포트 2222가 USB로 연결된 iPhone의 SSH 포트 22로 전달됩니다. 따라서 다른 터미널에서 접속할 주소는 iPhone의 네트워크 IP가 아니라 Mac 자신의 로컬 주소입니다.
ssh -p 2222 mobile@127.0.0.1
이 부분을 이해하고 나서야 SSH 접속 흐름이 정리되었습니다. 사내 Wi-Fi나 핫스팟 환경에서 기기 IP로 접속하려고 하면서 발생했던 타임아웃 문제를 USB 연결 방식으로 피할 수 있었습니다.
Mac에서 SSH 연결 준비하기
먼저 iproxy를 사용할 수 있도록 설치합니다.
brew install libimobiledevice
첫 번째 터미널에서 포트포워딩을 실행합니다.
iproxy 2222 22
이 터미널은 계속 열어둡니다. 이후 새 터미널을 열어 다음 명령으로 iPhone에 접속합니다.
ssh -p 2222 mobile@127.0.0.1

Dopamine 탈옥 기기에서 SSH와 Frida 준비하기
제가 사용한 기기는 Dopamine으로 탈옥한 iPhone이었습니다. SSH 접속과 Frida 사용을 위해 다음 과정을 진행했습니다.
iPhone에서 준비한 항목
- Dopamine 앱 설정에서 개발자 쉘 관련 기능을 활성화했습니다.
- 테스트 중 사용할
mobile계정 비밀번호를 설정했습니다. - Sileo에서
OpenSSH Server패키지를 설치했습니다. - Frida 저장소를 추가하고 Frida 패키지를 설치했습니다.
Frida 저장소 주소는 다음과 같습니다.
https://build.frida.re/
SSH 접속 후 Frida 상태 확인
SSH 접속에 성공한 뒤에는 iPhone 내부에서 Frida 관련 프로세스가 보이는지 확인했습니다.
ps -ax | grep -i "[f]rida"
처음 실행했을 때는 아무 결과가 나오지 않았습니다. 이때 Mac에 Frida CLI만 설치해서는 부족하다는 것을 알았습니다. Sileo에서 Frida 패키지를 설치한 뒤 다시 확인하니 관련 프로세스를 확인할 수 있었습니다.
이후 Mac에서 다시 앱 프로세스를 조회했습니다.
frida-ps -U
frida-ps -U | grep -i "결제샘플앱"
조회된 PID를 사용해 attach를 시도했습니다.
frida -U -p 2629
이번에는 정상적으로 연결되었습니다. 이제 본격적으로 Frida 메모리 점검을 시작할 수 있었습니다.
먼저 테스트 비밀번호가 메모리에 남는지 확인했다
민감정보 노출을 확인하는 가장 쉬운 방법은 내가 정확히 알고 있는 테스트 값을 검색하는 것입니다.
저는 테스트 로그인 과정에서 사용하는 아이디와 비밀번호를 대상으로 먼저 확인했습니다. 예시는 다음과 같이 운영 데이터와 무관한 값으로 작성했습니다.
LOGIN_ID: test002
PASSWORD: TEST_SECRET_1234
이 값이 앱 메모리에 평문으로 존재하는지 확인하기 위해 Frida 스크립트에서 UTF-8과 UTF-16LE 형태를 모두 검색하도록 구성했습니다. iOS 앱에서는 문자열이 상황에 따라 서로 다른 형태로 남을 수 있으므로, 한 가지 인코딩만 검사하면 놓치는 값이 생길 수 있다고 판단했습니다.
실행 흐름
먼저 앱의 PID를 조회합니다.
frida-ps -U | grep -i "결제샘플앱"
그다음 메모리 검색 스크립트를 실행합니다.
frida -U -p 2629 -l scan_sensitive_memory.js
결과는 다음처럼 표시하도록 구성했습니다.
[FOUND] PASSWORD UTF-8 count=1
[NOT FOUND] LOGIN_ID
이 결과만 보고 바로 취약점이라고 결론 내리지는 않았습니다. 사용자가 비밀번호를 입력하고 로그인 요청을 수행하는 순간에는 비밀번호 문자열이 일시적으로 메모리에 존재할 수 있기 때문입니다.
Frida 메모리 점검에서 중요한 것은 발견 시점이었다
처음 비밀번호가 메모리에서 검색됐을 때는 문제가 크다고 생각했습니다. 하지만 실제 보안 판단에서는 값이 언제 발견되는지가 더 중요했습니다.
| 확인 시점 | 비밀번호 또는 토큰 검색 결과 | 판단 |
|---|---|---|
| 로그인 입력 중 | FOUND | 입력 처리 중 일시적으로 존재할 수 있음 |
| 로그인 요청 직후 | FOUND | 요청 처리 이후 정리 여부 확인 필요 |
| 메인 화면 이동 후 | FOUND | 상태 객체나 캐시 잔존 가능성 확인 필요 |
| 로그아웃 후 | FOUND | 개선 우선순위가 높음 |
| 앱 재실행 후 | FOUND | 로컬 저장소나 자동로그인 구조 확인 필요 |
그래서 저는 단순히 한 번 검색하는 방식 대신 다음과 같은 시나리오로 여러 번 확인했습니다.
앱 실행
→ 로그인 값 입력
→ 로그인 완료
→ 사용자정보 화면 진입
→ 결제정보 화면 진입
→ 로그아웃
→ 각 시점에서 메모리 상태 확인
이 방식으로 검사하니 “사용 중 잠깐 필요한 값”과 “사용이 끝난 뒤에도 불필요하게 남은 값”을 구분할 수 있었습니다.
API 응답에 포함된 휴대폰번호와 계좌정보도 확인하고 싶었다
비밀번호처럼 직접 입력한 값은 검색 대상에 미리 추가하면 됩니다. 하지만 앱에서 API를 호출한 뒤 내려오는 사용자정보는 매번 검색 값을 직접 입력하기가 불편했습니다.
예를 들어 사용자정보 API 응답 객체에는 다음과 같은 값이 포함될 수 있습니다.
struct BasicMerchantInfo: Codable {
let mid: String?
let compNm: String?
let bossNm: String?
let bankNm: String?
let acctNm: String?
let acctNo: String?
let notiURL: String?
}
이 구조에서 acctNo처럼 계좌번호가 포함된 값이 앱 모델에 들어오면, 화면에서 사용한 뒤에도 메모리에 남아 있을 가능성을 확인해 보고 싶었습니다.
그래서 두 가지 방식을 함께 사용했습니다.
- 테스트 응답에서 미리 알고 있는 계좌번호나 휴대폰번호를 직접 추적값으로 추가합니다.
- 값을 미리 등록하지 않았더라도, 휴대폰번호·JWT·카드번호·계좌번호 후보 같은 형식을 검색합니다.
주요 민감정보 후보 탐지 기준
| 정보 종류 | 확인 방식 | 결과 신뢰도 |
|---|---|---|
| 휴대폰번호 | 국내 휴대폰번호 형식 검사 | 비교적 높음 |
| 이메일 | 이메일 형식 검사 | 오탐 가능 |
| JWT | 점 세 구간으로 나뉜 토큰 문자열 검사 | 비교적 높음 |
| Bearer Token | Bearer 접두어 포함 여부 검사 | 비교적 높음 |
| 카드번호 | 숫자 형식과 Luhn 검증 | 높음 |
| 주민등록번호 후보 | 형식과 체크섬 검사 | 높음 |
| 계좌번호 후보 | 숫자 또는 하이픈 조합 검사 | 반드시 실제 테스트값과 대조 필요 |
특히 계좌번호는 공통으로 적용할 수 있는 체크섬 규칙이 명확하지 않아, 단순히 숫자 패턴이 발견됐다는 사실만으로는 확정할 수 없었습니다. 앱에서 사용한 테스트 계좌번호와 일치하는지 확인한 뒤에야 유효한 결과로 기록했습니다.
전체 메모리 검색보다 저장 이벤트 감시가 더 실용적이었다
처음에는 프로세스의 읽기·쓰기 가능 메모리 전체를 훑으면 민감정보를 빠르게 찾을 수 있을 것이라고 생각했습니다. 하지만 실제로는 검색 범위가 넓을수록 결과 해석이 어려웠습니다.
전체 검색 방식에서 겪은 문제는 다음과 같습니다.
- 검색해야 하는 메모리 영역이 커서 시간이 오래 걸렸습니다.
- 단순 숫자 문자열이 많이 잡혀 계좌번호 후보 오탐이 많았습니다.
- SDK 내부 문자열이나 테스트와 관련 없는 데이터가 함께 검색됐습니다.
- 해당 값이 어떤 기능에서 생성된 것인지 추적하기 어려웠습니다.
결국 Frida 메모리 점검 방식도 조금 바꾸게 되었습니다.
- 비밀번호처럼 정확히 아는 값은 직접 검색합니다.
- API 호출 직후에는 형식이 명확한 민감정보 후보만 확인합니다.
- 저장되는 순간을 잡기 위해
UserDefaults, Keychain, Pasteboard, 파일 저장 동작을 감시합니다. - 발견된 실제 값만 로그아웃 이후까지 잔존 여부를 추적합니다.
이렇게 바꾸고 나니 “어떤 값이 있다”는 결과보다 “어떤 동작으로 값이 저장되었고, 이후에도 남아 있는가”를 판단하기 쉬워졌습니다.
Frida 메모리 점검으로 UserDefaults 저장을 확인했다
메모리 잔존과 함께 가장 먼저 확인하고 싶었던 것은 UserDefaults 저장 여부였습니다.
예를 들어 앱에서 다음처럼 인증 토큰을 저장하고 있다면:
UserDefaults.standard.set(accessToken, forKey: "accessToken")
토큰은 앱 종료 이후에도 복원 가능한 위치에 남습니다. 사용자 설정값을 저장하는 목적에는 적절할 수 있지만, 비밀번호나 토큰 같은 민감정보의 저장 장소로는 개선 검토가 필요합니다.
Frida 스크립트에서 NSUserDefaults 저장 메서드를 후킹하면 저장되는 순간의 key와 value를 확인할 수 있습니다.
[UNSAFE USERDEFAULTS][WRITE][HIGH]
path="$.accessToken"
value="eyJh************aBcD"
reason=KEY_TOKEN_OR_SESSION
UserDefaults에서 우선 확인할 값
| 저장된 값 | 점검 판단 |
|---|---|
| 테마 설정, 화면 옵션 | 일반적인 설정 데이터 |
| 로그인 비밀번호 | 저장되지 않도록 개선 필요 |
| Access Token, Refresh Token | Keychain 저장 구조 검토 |
| 휴대폰번호, 이메일 | 저장 필요성과 보호 방식 검토 |
| 카드번호, 계좌번호 | 저장 최소화 또는 제거 우선 검토 |
| OTP, 인증번호 | 저장하지 않는 방향 검토 |
메모리에서 토큰이 잠깐 발견되는 것보다, 보호되지 않은 저장소에 계속 남는 것이 훨씬 명확한 개선 대상이라고 판단했습니다.
Keychain 저장 결과는 취약점으로 바로 판단하지 않았다
인증 정보가 Keychain에 저장되는 경우에는 해석이 달랐습니다.
[PROTECTED KEYCHAIN][ADD]
service="loginToken"
account="accessToken"
비밀번호나 토큰을 Keychain에 저장하는 것은 UserDefaults에 저장하는 것과 같은 의미가 아닙니다. 보호가 필요한 인증 데이터를 저장해야 한다면 Keychain을 우선 검토할 수 있습니다.
다만 Keychain을 사용한다는 사실만으로 검사가 끝나는 것은 아니었습니다. 다음 항목도 함께 확인했습니다.
- 로그아웃 시 토큰이 삭제되는가?
- 자동로그인을 사용하지 않는데 토큰이 계속 남아 있지는 않은가?
- 다른 계정으로 로그인했을 때 이전 계정의 정보가 남아 있지 않은가?
- 로그나 화면 캡처에 토큰 평문이 출력되지 않는가?
결국 저장 위치뿐 아니라, 토큰의 수명과 삭제 정책까지 확인해야 의미 있는 점검 결과가 됩니다.
Pasteboard와 파일 저장도 놓치면 안 됐다
결제 앱이나 사내 주문 앱에서는 계좌번호, 전화번호, 주문 정보 등을 복사하는 기능이 있을 수 있습니다. 사용자가 직접 복사 버튼을 눌렀다고 하더라도, 민감정보가 Pasteboard에 전달된 사실은 확인할 필요가 있었습니다.
예를 들어 계좌정보가 복사되는 순간 다음과 같은 로그를 확인할 수 있습니다.
[PASTEBOARD][WRITE][HIGH]
path="$.string"
value="123-***-******"
reason=VALUE_ACCOUNT_NUMBER
클립보드 기능 자체를 무조건 제거해야 한다는 의미는 아닙니다. 다만 전체 카드번호나 인증번호처럼 재사용 위험이 큰 정보라면 복사 기능이 필요한지 다시 검토해야 합니다.
파일 저장도 마찬가지였습니다. 디버깅 편의를 위해 API 응답 전체를 파일로 저장하거나, 사용자정보 객체를 캐시 파일로 기록한다면 토큰이나 계좌정보가 앱 내부 파일에 남을 수 있습니다.
파일 쓰기 감시는 로그가 많아질 수 있으므로, 저는 필요한 구간에서만 활성화하도록 했습니다.
watchFiles(true)
그 뒤 앱에서 아래 동작을 수행했습니다.
로그인
→ 사용자정보 조회
→ 결제정보 조회
→ 결제 완료 또는 취소
검사가 끝난 뒤에는 파일 저장 감시를 껐습니다.
watchFiles(false)
실제로 사용한 Frida 메모리 점검 순서
몇 차례 시행착오를 겪은 뒤에는 다음 순서가 가장 확인하기 쉬웠습니다.
1. 대상 앱 프로세스 확인
frida-ps -U | grep -i "결제샘플앱"
앱이 조회되지 않는다면 먼저 앱 실행 여부, USB 연결 상태, iPhone의 Frida 설치 상태를 확인합니다.
2. 앱 시작부터 저장 동작을 확인해야 할 때
로그인 초기화 과정이나 자동로그인 토큰 저장처럼 앱 실행 직후에 일어나는 작업은 앱이 실행된 뒤 attach하면 놓칠 수 있습니다.
이때는 번들 ID를 기준으로 앱 실행 시점부터 연결합니다.
frida -U -f com.sample.app -l storage_watch.js
3. 앱에서 테스트 시나리오 수행
로그인 화면 진입
→ 테스트 계정으로 로그인
→ 자동로그인 설정 변경
→ 사용자정보 화면 진입
→ 결제정보 화면 진입
→ 필요한 경우 복사 기능 실행
→ 로그아웃
4. 저장 이벤트 이력 확인
history()
이 단계에서는 다음 로그를 우선적으로 확인했습니다.
[UNSAFE USERDEFAULTS] password / token / cardNo
[PASTEBOARD] accountNo / cardNo / OTP
[FILE WRITE] token / 개인정보 / 결제정보
[PROTECTED KEYCHAIN] token 저장 여부
5. 로그아웃 이후 메모리 잔존 확인
memoryStatus()
로그아웃 이후에도 비밀번호나 Access Token이 발견된다면, 해당 값을 보유하고 있는 객체나 캐시 정책을 코드에서 다시 확인해야 합니다.
민감정보 노출이 확인되었을 때 검토한 개선 방향
Frida 메모리 점검은 결과를 확인하는 것에서 끝나면 의미가 없습니다. 실제 개선 작업으로 연결되어야 합니다.
로그인 후에도 비밀번호가 남아 있는 경우
로그인 요청이 끝났는데도 비밀번호가 메모리에 남아 있다면 다음 부분을 먼저 확인할 수 있습니다.
- ViewModel이나 상태 객체가 비밀번호를 계속 가지고 있는지 확인합니다.
- 로그인 성공 후 입력 필드와 관련 프로퍼티를 초기화합니다.
- Singleton이나 전역 객체에 인증 입력값을 담지 않습니다.
- 디버그 로그에 비밀번호를 출력하지 않습니다.
- 자동로그인은 비밀번호 저장이 아니라 토큰 기반으로 설계합니다.
토큰이 UserDefaults에 저장되는 경우
인증 토큰이 일반 설정 저장소에 기록되고 있다면 보호 저장소 사용을 검토합니다.
// 개선 검토 대상
UserDefaults.standard.set(accessToken, forKey: "accessToken")
// 개선 방향
// Keychain 기반 토큰 저장 모듈 사용 검토
로그아웃 시 저장된 토큰이 제거되는지, 만료 토큰이 계속 재사용되지 않는지도 함께 확인해야 합니다.
API 응답 개인정보가 오래 남아 있는 경우
사용자정보 API 응답 전체를 앱 전역 상태로 계속 유지하고 있다면 화면에 필요하지 않은 계좌번호나 연락처도 오래 남을 수 있습니다.
다음과 같은 방향을 검토할 수 있습니다.
- 화면 표시에 필요한 값만 별도 모델로 전달합니다.
- 계좌번호나 인증값은 사용 후 참조를 빠르게 해제합니다.
- 전체 API 응답 객체를 불필요하게 캐시하지 않습니다.
- 로그에는 개인정보를 마스킹하여 출력합니다.
- 파일에 API 응답 전체를 저장하는 디버그 코드를 제거합니다.
클립보드에 결제정보가 기록되는 경우
사용자 요청에 의한 복사 기능이 필요한 경우라도 민감정보 종류에 따라 정책을 달리할 필요가 있습니다.
- 인증번호나 전체 카드번호는 복사 기능 자체를 최소화합니다.
- 계좌번호 복사가 필요한 경우 사용자 동작에 의해서만 실행합니다.
- 화면 캡처나 테스트 로그에는 반드시 마스킹합니다.
- 필요한 경우 일정 시간 뒤 클립보드를 비우는 정책을 검토합니다.
로그와 캡처 화면에서도 민감정보를 노출하지 않기
이번 테스트에서 가장 쉽게 놓칠 수 있는 부분은 점검 결과 로그였습니다. 메모리에서 값이 잘 검색되는지 확인하려고 평문 출력을 사용하면, 테스트 결과를 문서나 블로그에 첨부하는 순간 다시 개인정보 노출 문제가 생길 수 있습니다.
테스트 중에는 확인 편의를 위해 평문 출력을 사용하더라도, 캡처나 보고서를 작성하기 전에는 반드시 마스킹하도록 했습니다.
setPlaintext(false)
출력 예시는 다음과 같습니다.
value="TEST********1234"
value="eyJh************aBcD"
value="010-****-5678"
value="123-***-******"
블로그 글에 실제 로그 이미지를 넣을 경우에는 다음 항목을 추가로 가려야 합니다.
- 실제 앱 이름이 공개되면 곤란한 경우 앱명
- 번들 ID
- 사용자 아이디
- 전화번호, 계좌번호, 카드번호
- 토큰 전체 문자열
- 사내 네트워크 주소
- 기기 식별자
Frida 메모리 점검 결과를 해석할 때의 한계
이번 방식으로 민감정보가 발견되지 않았다고 해서 앱에 문제가 전혀 없다고 단정할 수는 없습니다.
- 검색하기 전에 이미 메모리에서 제거된 값은 발견하지 못할 수 있습니다.
- 암호화되거나 다른 형태로 변환된 값은 단순 문자열 검색에서 보이지 않을 수 있습니다.
- Swift 객체나 네이티브 라이브러리 내부에서 문자열 표현이 다르게 관리될 수 있습니다.
- 계좌번호처럼 형식만으로 확정하기 어려운 정보는 오탐 가능성이 있습니다.
- 탈옥 환경에서 수행한 테스트는 일반 사용자 단말의 모든 상황을 그대로 대표하지는 않습니다.
따라서 Frida 메모리 점검은 앱 보안을 완전히 판정하는 단일 기준이라기보다, 민감정보의 처리와 잔존 여부를 실제 동작 기준으로 확인하는 방법 중 하나로 보는 것이 적절합니다.
저는 다음 점검과 함께 활용하는 것이 좋다고 판단했습니다.
- Keychain 저장 정책 확인
- 로그 마스킹 적용 여부 확인
- 네트워크 통신 보안 확인
- 탈옥 및 후킹 환경 대응 점검
- 서버 기반 앱 무결성 검증 검토
- 개인정보 최소 수집·최소 보관 설계 확인
마무리: 직접 확인해 보니 저장 위치와 제거 시점이 더 중요했다
처음 Frida 메모리 점검을 시작했을 때는 “메모리에서 문자열을 찾으면 된다” 정도로 생각했습니다. 하지만 실제로 진행해 보니 Frida 연결, SSH 접속, 저장 이벤트 확인, 로그아웃 이후 재검사까지 연결되어야 의미 있는 결과가 나왔습니다.
특히 다음 세 가지가 가장 중요했습니다.
- 민감정보가
UserDefaults나 파일처럼 불필요한 위치에 저장되지 않는지 확인합니다. - 로그인이나 결제 처리가 끝난 뒤에도 비밀번호와 토큰이 메모리에 계속 남아 있지 않은지 확인합니다.
- 보안 점검 결과를 남기는 로그와 이미지에서도 실제 테스트 값은 마스킹합니다.
앱은 기능 구현만으로 끝나지 않습니다. 인증 정보와 개인정보를 다루는 순간부터는 해당 값이 어디에 저장되고, 언제 제거되며, 어떤 경로로 노출될 수 있는지도 함께 확인해야 합니다.
저에게 이번 Frida 메모리 점검은 코드만 보고는 놓칠 수 있는 민감정보의 흐름을 직접 확인하는 과정이었습니다. 앞으로 로그인, 결제, 사용자정보 조회 기능을 개발할 때는 정상 동작 여부뿐 아니라 사용이 끝난 민감정보가 앱 안에 불필요하게 남아 있지 않은지도 함께 점검하려고 합니다.
관련 자료
- iOS 앱 변조를 App Attest로 막을 수 있을까? 직접 구조를 정리하며 이해한 것 2026
- iOS 앱 무결성 검증 자세히 살펴보기 2026 (대처방법 까지)
- iOS 탈옥 감지 구현 경험: Swift로 Jailbreak Detection 적용하기