읽기만 하는 것이니 안전하다고 보고 확인 없이 넘어간 일들이 있었는데 그중 몇 개가 실제로 문제가 됐다.
Table of contents
Open Table of contents
목록 조회와 데이터 요금
윈도우의 연결된 기기 폴더를 조회했는데 목록만 보는 명령이었는데도 연결된 휴대폰에서 데이터 요금이 발생했다.
그 폴더의 항목은 로컬에 실체가 없고 자리만 잡혀 있다가 열어 볼 때 기기에서 실제로 끌어온다. 목록을 훑는 것만으로도 네트워크가 도는 구조였다. 읽기 전용이라는 표면적 성격과 그 조회가 실제로 유발하는 동작이 달랐다.
조회 하나가 만든 대기
수억 행짜리 테이블에 조건을 걸어 개수를 셌다. 조회니까 안전하다고 생각했는데 인덱스를 못 타서 전체를 훑기 시작했고 그 뒤로 들어온 요청이 전부 대기에 걸려 다른 사람의 가벼운 조회까지 멈췄다.
더 곤란한 것은 그다음이었는데 진단하려고 지금 무엇이 돌고 있는지를 조회했더니 그것도 막혔다. 무엇이 문제인지 볼 수 있는 경로 자체가 함께 막힌 상태가 된 것이다.
도구 호출을 취소해도 소용없었다. 이미 서버로 간 요청은 그대로 계속 돈다. 취소는 내가 기다리기를 그만둔 것이지 서버에 전달되는 신호가 아니다. 그래서 지금은 큰 테이블을 조회하기 전에 실행 계획을 먼저 보고 전체를 훑을 것 같으면 조건을 바꾼다.
결과에 섞여 나온 값
환경변수를 모아 정리하는 스크립트를 돌렸다. 민감한 이름은 걸러 내게 해 뒀는데 그 목록에 일부 이름만 들어 있었다. 비밀번호나 토큰처럼 명백한 것은 있고 세션이나 해시 같은 것은 빠져 있었다.
결과 파일에 계정 접근이 가능한 값이 평문으로 남았고 그 파일을 읽는 과정에서 대화에도 그대로 나왔다. 조회 자체는 아무것도 바꾸지 않았지만 값이 밖으로 나온 것은 되돌릴 수 없다. 상태를 바꾸지 않는다는 성질과 되돌릴 수 있다는 성질은 별개다.
가림 조치의 범위
비슷한 일이 하나 더 있었는데 설정 파일 두 개를 비교하면서 바로 앞에서는 같은 파일을 값을 가리고 조회했으면서 비교할 때는 그 조치를 이어 가지 않았다. 비교는 차이를 그대로 출력하므로 예시에 없는 실제 값 자리가 곧 전문 노출이 됐다.
가림 조치를 그 호출 하나에만 걸었던 것이 문제였다. 가림은 명령 단위가 아니라 그 파일을 다루는 연속된 작업 전체에 걸어야 한다. 지금은 자격증명이 들어갈 수 있는 파일은 값을 출력하는 경로 자체를 만들지 않고, 같은지 확인해야 하면 해시 앞자리를 비교한다.
조회 전 확인 항목
읽기 작업을 시작하기 전에 네 가지를 본다. 몇 행짜리 테이블이고 인덱스를 타는지 실행 계획으로 확인하고, 배치가 도는 시간과 겹치는지 시점을 보고, 결과에 민감한 값이 담기는 컬럼이 있는지 확인하고, 마지막으로 그것이 실제로 읽기인지를 따진다.
마지막이 특히 그렇다. 밖으로 나가는 요청은 조회의 형태를 하고 있어도 발신이다. 외부 검색은 질의문 자체가 그쪽 서버로 가므로 비공개 정보를 검색어에 넣으면 결과를 받기 전에 이미 나간 것이 된다.
정리
- 읽기 전용이 표면적 성격일 뿐인 경우가 있다
- 가상 폴더는 목록만 훑어도 실제로 끌어온다
- 큰 테이블 조회가 DB를 멈추므로 실행 계획을 먼저 본다
- 취소해도 이미 간 요청은 계속 돈다
- 조회 결과에 민감한 값이 섞이면 되돌릴 수 없다
- 상태를 바꾸지 않는 것과 되돌릴 수 있는 것은 별개다
- 가림 조치는 호출 하나가 아니라 작업 전체에 건다
- 외부로 나가는 조회는 읽기가 아니라 발신이다