Showing Posts From
보안테스트
- 05 Dec, 2025
모의해킹 중 실수로 서비스를 터뜨린 날 - 그 후 어떻게 했나?
모의해킹 중 실수로 서비스를 터뜨린 날 - 그 후 어떻게 했나? 화요일 오후 3시 42분 모의해킹 중이었다. 결제 API 침투 테스트. OWASP Top 10 체크리스트 따라가는 중. SQL Injection 테스트 페이로드 날렸다. ' OR '1'='1 같은 거. 기본 중의 기본. 근데 응답이 이상했다. 500 에러. 한 번 더. 또 500.슬랙에 알림 떴다. "결제 시스템 장애 발생" "고객 결제 불가" "긴급 점검 중" 심장이 멈췄다. 15초 후 손이 떨렸다. 진짜로. 내가 터뜨린 거다. 확신했다. 타임스탬프 확인했다. 내 테스트: 15:42:38 장애 시작: 15:42:39 1초 차이. 로그 봤다. 내 IP 주소. 내 테스트 페이로드. 데이터베이스 커넥션 풀이 다 죽어있었다. "씨발." 입 밖으로 나왔다. 즉시 보고 팀장한테 슬랙 날렸다. "제가 터뜨린 것 같습니다" "지금 즉시 복구 지원하겠습니다" 전화 왔다. 떨리는 목소리로 받았다. "뭐 했어?" "SQL Injection 테스트요. 근데..." "스테이징이야 프로덕션이야?" "..." 침묵. VPN 설정 확인했다. 프로덕션 DB 접속되어 있었다. "프로덕션입니다." 팀장 한숨 소리. 길게.상황 파악 10분 CTO 포함 긴급 회의. 개발팀장, 인프라팀장, 보안팀장, 나. 내가 설명했다. "SQL Injection 페이로드 날렸고요" "데이터베이스 커넥션이 과부하 걸렸습니다" "제가 스테이징인 줄 알고..." 변명 아니다. 사실 그대로. CTO가 물었다. "데이터 유실은?" "없습니다. 확인했습니다." "개인정보 유출은?" "없습니다. Read 쿼리만 실행됐습니다." 로그 파일 공유했다. 다 떨렸다. 인프라팀장이 DB 재시작 중. 커넥션 풀 리셋. 5분 뒤 복구 완료. 15:57. 15분간 장애. 피해 규모 고객 278명 결제 실패. 예상 매출 손실 약 1200만원. CS 문의 83건. 장애 공지 올라갔다. "일시적 시스템 점검" "불편을 드려 죄송합니다" 고객들은 몰랐다. 보안 테스터가 터뜨렸다는 걸. 근데 회사는 안다. 내가 터뜨렸다는 걸. 즉시 수습 작업 오후 4시부터 밤 11시까지. 내가 한 일:전체 로그 분석 리포트 작성 영향받은 트랜잭션 리스트 추출 재시도 필요 건 식별 (개발팀 전달) 근본 원인 분석 문서화 재발방지 대책 수립왜 터졌나. DB 커넥션 풀 설정이 약했다. 맞다. 근데 그건 핑계다. 진짜 문제는 내가 프로덕션에 접속했다는 것. 스테이징인 줄 착각했다. VPN 설정 확인 안 했다. 기본 중의 기본을 안 지켰다.보고서 작성 11시 반. 최종 보고서 완성. 사고 경위15:42 보안 테스터가 프로덕션 환경에서 침투 테스트 실시 SQL Injection 페이로드로 DB 커넥션 풀 소진 15분간 결제 서비스 장애직접 원인프로덕션/스테이징 환경 미확인 테스트 전 체크리스트 미준수근본 원인VPN 프로파일 네이밍이 불명확 프로덕션 접근 권한 통제 미흡 모의해킹 가이드라인 부재재발방지 대책프로덕션 DB 접근 시 2단계 승인 필요 VPN 프로파일명 명확화 (PROD-빨간색 표시) 침투 테스트 체크리스트 의무화 프로덕션 테스트 시 Read-Only 계정만 사용 부하 테스트 전 Rate Limiting 확인솔직하게 썼다. 내 실수 숨기지 않았다. 수요일 오전 회의 임원 회의실. 긴장됐다. CTO가 먼저 말했다. "보고서 봤어요. 솔직하네요." "네." "처벌은 당연히 있습니다." 각오했다. "이번 달 성과급 50% 삭감" "그리고..." 잘렸나 싶었다. "재발방지 대책 실행 책임자 맡으세요" "네?" "당신이 제일 잘 알잖아요. 어떻게 터지는지." 의외였다. 팀장이 말했다. "실수는 누구나 해. 근데 수습을 어떻게 하느냐가 중요해." "15분 만에 보고했고" "7시간 동안 수습했고" "솔직한 보고서 썼어" "이게 프로야" 눈물 날 뻔했다. 참았다. 그 후 2주 재발방지 대책 실행했다.프로덕션 DB 접근 권한 재설계보안팀도 기본은 Read-Only Write 권한은 Jira 티켓 + 팀장 승인VPN 프로파일 UI 개선PROD는 빨간색, 경고 팝업 STAGING은 노란색 DEV는 초록색침투 테스트 체크리스트 제작 [ ] 환경 확인 (STAGING임을 3번 체크) [ ] Read-Only 계정 사용 [ ] 테스트 범위 문서화 [ ] 부하 영향도 사전 검토 [ ] 팀장 승인모의해킹 가이드라인 문서화전사 공유 신규 입사자 필독주간 보안팀 회의에서 Near-Miss 공유"나 이번 주에 이런 실수 뻔했어" 서로 배우는 문화한 달 후 성과급 50% 깎였다. 150만원. 아팠다. 근데 마땅했다. 대신 얻은 것. 개발팀이 보안팀 보는 눈이 달라졌다. "보안팀도 실수하네. 우리만 그런 게 아니구나" "근데 수습 진짜 빠르더라" 예전엔 보안 이슈 리포트하면 "나중에요~" 했는데 이제는 "언제까지 고칠게요" 한다. 왜? 내가 터뜨렸을 때를 봤으니까. 수습하는 모습도 봤으니까. 신뢰가 생겼다. 3개월 후 회고 분기 회고 때 발표했다. "제가 3개월 전에 프로덕션 터뜨렸습니다" 웃음 나왔다. 다들 알던 사실. "그 후 바뀐 것들"프로덕션 장애 0건 (보안 테스트 관련) 침투 테스트 체크리스트 준수율 100% 타팀에서도 우리 가이드라인 참고 Near-Miss 공유 문화 정착"배운 것"실수는 시스템으로 막아야 한다 솔직한 보고가 신뢰를 만든다 수습 속도가 전문성이다CTO가 말했다. "이게 성숙한 조직이에요" "실수를 숨기는 게 아니라" "실수에서 배우는 거" 박수 나왔다. 부끄러웠다. 지금 여전히 모의해킹한다. 침투 테스트한다. 근데 체크리스트는 무조건 본다. 환경 확인. 세 번. STAGING 맞나. 또 확인. VPN 프로파일 색상. 노란색 맞나. 강박이 생겼다. 좋은 의미로. 후배가 입사했다. 보안 QA 신입. 첫날 내가 말했다. "내가 3개월 전에 프로덕션 터뜨렸어" "어떻게요?" "체크리스트 안 봐서" 그리고 가이드라인 줬다. "이거 만든 사람이 나야" "왜냐면 터뜨려봐서 알거든" 후배가 웃었다. "선배, 솔직하시네요" "보안 일 하려면 솔직해야 해" "취약점 찾는 것도" "내 실수 인정하는 것도" 교훈이랄 것도 없지만 실수는 한다. 보안 전문가도 사람이니까. 중요한 건 그 다음이다. 15초 만에 인정할 건가. 15분 만에 보고할 건가. 15시간 동안 수습할 건가. 아니면 숨길 건가. 나는 15초 만에 알았다. "내가 터뜨렸다" 그게 시작이었다.프로덕션 터뜨린 날. 최악의 날이었다. 근데 최고의 배움이었다. 체크리스트는 생명이다.
- 03 Dec, 2025
취약점을 못 찾으면 '없는 건지, 못 찾은 건지' 자책하는 밤
취약점을 못 찾으면 '없는 건지, 못 찾은 건지' 자책하는 밤 오후 3시, 스캔 시작 신규 결제 API 테스트 들어갔다. 개발팀이 자신 있다고 했다. "이번엔 보안 완벽하게 했습니다." 그 말 들으면 더 의심스럽다. Burp Suite 켰다. Proxy 설정하고 트래픽 캡처 시작. 일단 자동 스캔 돌려놨다. 커피 한 잔 마시러 갔다. 돌아와서 결과 확인. Low 몇 개. Medium 하나. 다 거짓 양성이다. 수동 테스트 시작했다. Authorization 헤더 빼봤다. 정상 처리됐다. 이상하다. 토큰 변조해봤다. 401 에러 떴다. 정상이다. SQL Injection 시도. Single quote, double quote, comment. 다 필터링됐다.XSS 테스트 들어갔다. Script 태그, event handler, encoded payload. 전부 sanitize됐다. 깔끔하다. 너무 깔끔하다. 이게 맞나. 오후 5시 됐다. 취약점 없다. 하나도. 6시, 퇴근 시간 동료들 하나씩 퇴근한다. "오늘 뭐 찾았어?" 물어본다. "아직요." 대답했다. "괜찮아, 없으면 없는 거지." 웃으면서 말한다. 없으면 없는 거. 그게 그렇게 간단하지 않다. 보안 QA 6년 차다. 취약점 못 찾는 날이 제일 불안하다. 찾으면 보람 있다. 회사 지켰다는 기분. 못 찾으면 모르겠다. 정말 안전한 건지, 내가 못 찾은 건지. 개발자들은 취약점 없으면 좋아한다. 당연하다. 수정할 거 없으니까. 나는 불안하다. 뭔가 놓친 것 같다. 리포트에 뭐라고 쓸까. "취약점이 발견되지 않았습니다." 이 한 줄. 허전하다. 믿을 수 있을까. 나도 확신 없는데. 여자친구한테 문자 왔다. "저녁 먹자." 답장 보냈다. "조금만 더." 남았다. 혼자. 8시, 다시 시작 처음부터 다시 봤다. 놓친 엔드포인트 있을 수 있다. API 문서 다시 읽었다. 15개 엔드포인트. 다 테스트했다. Rate limiting 확인했다. 잘 걸려 있다. 1분에 100 요청. Brute force 막힌다. IDOR 테스트했다. user_id 변조. 403 에러. 정상이다.SSRF 시도했다. 내부 IP 호출. 막혔다. XXE 테스트. XML 파싱 안 쓴다. GraphQL injection. GraphQL 안 쓴다. NoSQL injection. MongoDB 쿼리 검증 됐다. 2시간 더 지났다. 여전히 없다. 동료한테 물어볼까 생각했다. "내가 놓친 거 있을까요?" 부끄럽다. 6년 차가 이런 질문. 10시, 자책 시작 컴퓨터 앞에 앉아 있다. 화면만 본다. 뭘 더 해야 할까. OWASP Top 10 다시 확인했다. Injection. 확인했다. Broken Authentication. 확인했다. Sensitive Data Exposure. 암호화 됐다. XML External Entities. 안 쓴다. Broken Access Control. 확인했다. Security Misconfiguration. 기본 설정 변경됐다. XSS. 확인했다. Insecure Deserialization. 안 쓴다. Using Components with Known Vulnerabilities. 버전 다 최신이다. Insufficient Logging. 로깅 잘 된다. 다 확인했다. 그래도 불안하다. 작년 생각났다. 3일 동안 못 찾았던 API. "안전합니다" 리포트 올렸다. 2주 후에 버그바운티 해커가 찾았다. JWT 알고리즘 혼동 취약점. 'none' 알고리즘 허용했었다. 나는 못 봤다. 팀장 불렀다. "이거 왜 못 찾았어?" 할 말 없었다. "죄송합니다." 그것뿐이었다. 기본적인 건데. 6년 차가 놓쳤다. 그 이후로 더 신경 쓴다. 그래도 여전히 놓칠까 봐 무섭다. 11시, 마지막 시도 JWT 다시 봤다. 알고리즘 확인. RS256. 고정됐다. 'none' 안 된다. 서명 검증 잘 된다. Expiration 확인. 1시간. 적절하다. Refresh token 로직. 정상이다. Race condition 테스트했다. 동시에 100개 요청. 처리 잘 된다. 중복 안 생긴다. Business logic 봤다. 포인트 적립 로직. 음수 입력. 거부됐다. 환불 로직. 금액 확인 잘 된다. 쿠폰 중복 사용. 막혔다.File upload 기능 없다. CSRF 토큰 잘 된다. Clickjacking X-Frame-Options 설정됐다. CORS 정책 엄격하다. 자정 됐다. 9시간 봤다. 없다. 진짜 없는 건가. 아니면 내가 못 보는 건가. 자정, 집으로 퇴근했다. 사무실 나왔다. 차가운 바람. 12월이다. 택시 탔다. 창밖 본다. 불 켜진 건물들. 저기도 누군가 일한다. 보안 QA만 이럴까. 아니겠지. 여자친구한테 전화 왔다. "아직도 일해?" 목소리 졸리다. "퇴근했어. 미안." 걱정한다. "너무 늦게까지 하지 마." 설명 못 한다. 이 불안감. 취약점 찾으면 일 잘했다는 거다. 못 찾으면 모른다. 일을 잘한 건지, 못한 건지. 개발자는 다르다. 기능 만들면 된다. 동작하면 성공이다. 보안 QA는 애매하다. 안전하다는 걸 어떻게 증명하나. '취약점이 없다'는 증명은 없다. '찾지 못했다'는 것뿐이다. 새벽 1시, 침대에서 누웠다. 잠 안 온다. 핸드폰 켰다. 보안 뉴스 본다. 새로운 CVE 나왔다. npm 패키지 취약점. 우리 프로젝트에 있나 확인해야겠다. 생각이 꼬리를 문다. 오늘 테스트한 API. 진짜 안전할까. JWT 서명 검증 로직 직접 봤나. 소스 코드 확인 안 했다. 블랙박스로만 봤다. 내일 개발팀한테 물어봐야겠다. "JWT 라이브러리 뭐 쓰세요?" 혹시 오래된 버전. 알려진 취약점 있을 수 있다. 근데 그것도 찾으면 찾는 거고. 못 찾으면 모른다. 버그바운티 해커들 생각난다. 걔네는 어떻게 찾을까. 나보다 잘 찾는다. 돈도 번다. 나는 월급 받으면서 못 찾는다. 작년 그 해커. LinkedIn 찾아봤다. 19살이었다. 나보다 어리다. 실력은 훨씬 좋다. 질투 나는 건 아니다. 그냥 자괴감. 이 일 6년 했는데. 19살한테 진다. 새벽 2시, 검색 일어나서 노트북 켰다. JWT 취약점 검색했다. Algorithm confusion, Key confusion, KID injection, JKU/X5U claim abuse. 다 아는 거다. 다 테스트했다. 그래도 뭔가 놓친 것 같다. Stack Overflow 봤다. "How to test JWT properly." 답변 읽었다. 내가 하는 거랑 똑같다. YouTube 켰다. "Advanced JWT attacks." 40분짜리 영상. 봤다. 새로운 거 없다. 다 아는 내용이다. 그래도 불안하다. 문제는 이거다. 내가 아는 방법으로만 테스트한다. 모르는 취약점은 못 찾는다. 당연한 거다. 근데 받아들이기 힘들다. 보안팀장이 말했다. "완벽한 보안은 없어. 최선을 다하면 돼." 위로가 안 된다. 최선이 뭔데. 어디까지가 최선인가. 9시간 테스트했다. 최선이다. 근데 충분한가. 새벽 3시, 포기 노트북 껐다. 누웠다. 천장 본다. 어둡다. 내일 리포트 써야 한다. "신규 결제 API 보안 테스트 결과, 주요 취약점이 발견되지 않았습니다. 인증, 인가, 입력 검증, 에러 처리 등 전반적인 보안 구현이 양호합니다." 이렇게 쓸 거다. 사실이다. 발견되지 않았다. 없다고 안 했다. 발견되지 않았다. 개발팀은 좋아할 거다. "보안 테스트 통과했습니다!" 뿌듯해할 거다. 나는 불안할 거다. 배포되고 나서도. 실 서비스 올라가고 나서도. 해커가 찾을까 봐. 뉴스 뜰까 봐. "○○ 핀테크 결제 API 해킹." 댓글 달릴까 봐. "보안팀 뭐했냐." 팀장 부를까 봐. "이거 테스트 안 했어?" 했다. 9시간 했다. 최선을 다했다. 근데 못 찾았다. 이게 제일 무섭다. 열심히 했는데 결과가 없는 것. 아니다. 결과가 있는데 믿을 수 없는 것. 새벽 4시, 마음 정리 생각을 바꿔야 한다. 이건 알고 있다. 취약점을 못 찾는 게 실패가 아니다. 찾을 수 있는 걸 놓친 게 실패다. 찾을 수 없는 건 어쩔 수 없다. 내가 할 수 있는 건 했다. OWASP Top 10 확인했다. 알려진 공격 다 시도했다. Business logic 검토했다. 소스 코드 리뷰 요청할 거다. 9시간 집중했다. 더 할 수 있는 게 있나. 있다. 항상 있다. 무한정 시간 쓸 수는 없다. 선을 그어야 한다. 여기까지가 내 책임이다. 나머지는 운이다. 아니다. 나머지는 배포 후 모니터링이다. 침입 탐지 시스템이다. 버그바운티 프로그램이다. 혼자 다 막을 수 없다. 팀으로 한다. 회사 전체가 한다. 조금 마음이 편해진다. 조금. 새벽 5시, 잠 눈 감는다. 여전히 불안하다. 근데 받아들인다. 내일 출근하면 리포트 쓸 거다. "취약점 발견되지 않음." 자신 있게 쓸 거다. 최선을 다했으니까. 그리고 다음 테스트 들어갈 거다. 또 찾을 거다. 또 못 찾을 수도 있다. 또 불안할 거다. 이게 보안 QA다. 찾으면 보람 있고, 못 찾으면 불안하다. 끝이 없다. 근데 누군가는 해야 한다. 회사 지키는 일. 사용자 지키는 일. 내일도 한다. 모레도 한다. 잠든다.9시간 테스트하고 못 찾았다. 내일 또 한다.