주요 기사 요약
OWASP는 2021년에 발표한 웹 애플리케이션 보안 위협 Top 10을 통해 접근 제어 파괴, 암호화 실패, 인젝션 공격, 부적절한 설계, 보안 설정 오류 등 가장 위험한 10가지 취약점을 정의했다. 2025년에는 AI 에이전트 및 API 기반 시스템의 증가로 인해 새로운 위협들이 부상하고 있으며, 특히 소프트웨어 공급망 공격이 급증하고 있다. 가트너는 2025년까지 전 세계 조직의 45%가 소프트웨어 공급망 공격에 직면할 것으로 예측했으며, 2024년에는 전체 소프트웨어 공급망의 75%가 공격을 보고했다. 개발자가 OWASP Top 10을 이해하고 적용하는 것은 이제 선택이 아닌 필수가 되었다.
그 전화 한 통, “웹사이트가 해킹됐어요”
처음 그 전화를 받았을 때 손이 떨렸다. 3개월 전에 완성한 쇼핑몰 프로젝트였다. 평소대로 좋아하던 클라이언트가 갑자기 “고객들이 로그인이 안 된대요”, “다른 사람 주문 내역이 보여요”라며 신고했다.
나는 긴급히 관리자 패널에 접속했다. 뭔가 이상했다. 고객 데이터가 다 보였다. 주소, 전화번호, 구매 기록까지. 관리자 계정도 평문(순수 텍스트)으로 저장되어 있었다. 그리고 더 끔찍한 건, 공격자의 흔적도 남아 있었다. 로그를 확인해보니 누군가 평범한 사용자 ID(user1, user2…)로 다른 고객의 정보에 접근하고 있었다.
그때부터 비로소 깨달았다. 보안은 “나중에 생각해도 되는 것”이 아니었다. 그리고 그건 단순한 기술 문제가 아니었다. 클라이언트와의 관계, 평판, 그리고 내 사업 자체가 위험에 처했다. 그 사건 이후로 나는 OWASP Top 10을 깊게 공부했다. 그리고 깨달았다. 내가 범한 실수들이 거기 다 있었다.
OWASP Top 10이 뭔데, 왜 중요한가
OWASP는 Open Web Application Security Project의 줄임말로, 웹 애플리케이션 보안을 개선하려는 국제적 비영리 단체다. 이들이 매 3~4년마다 발표하는 Top 10은 전 세계 보안 전문가와 개발자들의 데이터를 모아 “지금 가장 위험한 웹 보안 취약점 10가지”를 정리한 것이다.
쉽게 말해, Top 10은 “가장 흔하고, 가장 위험하고, 가장 많이 악용되는 취약점들”이다. 이걸 알면 내가 만드는 웹사이트를 보호할 수 있다. 거꾸로 말하면, 이걸 모르면 클라이언트의 데이터를 지키지 못한다는 뜻이다.
나 같은 프리랜서 개발자들이 특히 중요하게 봐야 하는 이유는 간단하다. 우리는 혼자 일한다. 보안 팀도 없고, 감시자도 없고, 견제자도 없다. 모든 책임이 우리에게 있다. 그래서 OWASP Top 10은 우리의 “체크리스트”가 되어야 한다.
가장 흔한 공격 1위: 접근 제어 파괴
내 쇼핑몰 사건의 핵심 원인이었다. Broken Access Control이라고 부르는데, 쉽게 말해 “권한 확인을 제대로 안 한다”는 뜻이다.
당시 내 코드를 보면, 사용자가 로그인하면 user_id를 세션에 저장했다. 그리고 주문 조회할 때 뭘 했는가? 단순히 URL에 “order_id”를 파라미터로 넘겼다. “order.php?id=123″처럼.
공격자는 이걸 봤을 때 “아, 숫자만 바꾸면 다른 사람 주문도 볼 수 있겠네?”라고 생각했고, 실제로 했다. 나는 “누가 접근했는가”는 확인했지만, “이 사람이 이 주문을 조회할 권리가 있는가”는 확인하지 않았다.
이제 내 코드는 이렇게 됐다. 주문을 조회하기 전에, 그 주문이 현재 로그인한 사용자의 주문인지 확인한다. 아니라면 에러를 반환한다. 이게 “제대로 된 접근 제어”다.
2위: 암호화 실패
다음은 암호화 문제였다. 내가 고객 비밀번호를 평문(순수 텍스트)으로 저장하고 있었다. “1234567”이라는 비밀번호를 그대로 데이터베이스에 넣었다.
해킹을 당한 후에 깨달았는데, 만약 공격자가 내 데이터베이스 전체를 탈취했다면, 고객들의 비밀번호가 모두 노출됐을 거였다. 그리고 사람들은 같은 비밀번호를 여러 사이트에서 쓰니까, 그들의 다른 계정들도 모두 위험했을 거다.
지금 내가 하는 방식은 다르다. 비밀번호는 저장하지 않는다. 대신 bcrypt 같은 해시 함수로 변환해서 저장한다. 그러면 해킹을 당해도 원래 비밀번호가 뭔지 알 수 없다. 로그인할 때는 사용자가 입력한 비밀번호를 다시 해시로 변환해서, 저장된 값과 비교한다.
그리고 데이터베이스 연결도, API 통신도, 모두 SSL/TLS(HTTPS)로 암호화한다. 평문으로 날아가는 데이터는 없다.
3위: 인젝션 공격
인젝션 공격은 내 코드에 “코드를 주입”하는 거다. 가장 흔한 게 SQL 인젝션이다.
예를 들어, 검색 기능이 있다고 하자. 사용자가 “신발”을 검색하면 내 코드는 이렇게 쿼리를 만든다: “SELECT * FROM products WHERE name = ‘신발'”
그런데 만약 사용자가 “신발’ OR ‘1’=’1″이라고 입력하면? 쿼리가 “SELECT * FROM products WHERE name = ‘신발’ OR ‘1’=’1′”이 되고, ‘1’=’1’은 항상 참이니까 모든 상품이 조회된다.
심하면 “‘; DROP TABLE products; –” 같은 걸 입력해서 테이블을 삭제하는 공격도 가능하다.
해결책은 “Prepared Statement”나 “Parameterized Query”를 사용하는 것이다. 쿼리와 데이터를 분리해서 처리하니까, 아무리 특수 문자를 입력해도 코드로 실행되지 않는다. 그냥 데이터로 취급된다.
4위: 부적절한 설계
이건 코드 자체의 문제라기보다, 처음부터 설계를 잘못한 경우다. 예를 들어 “관리자 기능을 일반 사용자도 접근할 수 있게 설계”한다던지, “삭제 기능에 확인 절차가 없어서 실수로 데이터를 날릴 수 있다”던지.
내 경우 처음엔 환불 기능이 없었다. 그러다 나중에 급하게 추가했는데, 환불 로직을 제대로 설계하지 않아서 같은 상품을 여러 번 환불할 수 있는 버그가 생겼다. 고객이 한 번만 구매했는데 환불을 3번 받은 거다.
이건 처음 설계 단계에서 “어떤 사람이, 어떤 상황에서, 뭘 할 수 있어야 하고, 못해야 하는가”를 명확히 정의했으면 피할 수 있었다. 보안은 나중에 덧붙이는 게 아니라, 처음부터 고려해야 한다.
5위: 보안 설정 오류
서버를 배포할 때 기본값 그대로 두는 것. 예를 들어 데이터베이스 관리자 기본 비밀번호를 안 바꿨다던지, 필요 없는 포트가 열려 있다던지, 디버그 모드를 켜둔 상태로 배포한다던지.
내가 한 실수는 에러 메시지를 너무 자세하게 노출한 거였다. 어떤 쿼리에서 에러가 났는지, 테이블 이름이 뭔지, 심지어 데이터베이스 경로까지 사용자에게 보여줬다. 공격자는 이 정보로 데이터베이스 구조를 파악하고, 더 정교한 공격을 할 수 있었다.
이제는 사용자에게는 일반적인 “문제가 발생했습니다” 메시지만 보여주고, 실제 에러는 관리자 로그에만 기록한다.
6~10위도 중요하지만
취약하고 오래된 라이브러리(6위), 인증 실패(7위), 데이터 무결성 문제(8위), 로깅 부족(9위), SSRF 공격(10위)도 모두 중요하다. 하지만 프리랜서 개발자가 최우선으로 신경 써야 할 건 1~5위다. 이 5가지만 제대로 막아도 대부분의 흔한 공격을 피할 수 있다.
특히 8위인 로깅이 중요한 이유는, 공격을 당했을 때 “뭐가 됐는지” 알아야 배상이나 복구를 할 수 있기 때문이다. 내가 해킹을 당했을 때 로그가 없어서 정확히 언제부터 누가 뭘 했는지 알 수 없었다. 클라이언트에게 설명할 수도 없었고, 배상 범위도 정할 수 없었다.
1인 개발자, 이렇게 시작해라
OWASP Top 10 전체를 다 구현하는 건 시간이 걸린다. 하지만 처음부터 다 할 필요는 없다. 나는 이렇게 순차적으로 적용했다.
먼저 접근 제어부터 점검했다. 모든 기능에서 “현재 사용자가 이걸 할 권리가 있나”를 확인하는 로직을 추가했다. 1주일 정도 걸렸다.
다음은 인증 정보 암호화다. 비밀번호를 해시로 변환했고, 모든 통신을 HTTPS로 전환했다. 이건 3~4일 정도.
그 다음은 인젝션 공방지. 모든 데이터베이스 쿼리를 Prepared Statement로 수정했다. 이건 좀 오래 걸렸다. 2주 정도.
마지막으로 로깅을 추가했다. 모든 중요 기능(로그인, 로그아웃, 주문, 환불 등)을 기록하도록 했다.
이렇게 하니까 클라이언트들의 신뢰도 다시 높아졌다. 오히려 “우리 사이트 보안이 좋다”고 마케팅도 할 수 있게 됐다. 새로운 클라이언트들이 “보안이 중요한데, 너는 OWASP Top 10을 본다고 했지?”라며 물어보기도 한다.
비용인가, 투자인가
OWASP Top 10을 구현하는 데 시간이 걸린다. 그래서 일부 개발자들은 “이건 비용이 드니까 나중에 해야지”라고 생각한다.
잘못된 생각이다. 보안은 비용이 아니라 투자다. 지금 2주를 투자해서 Top 10을 구현하면, 나중에 해킹을 당했을 때 벌어질 일들을 피할 수 있다. 클라이언트의 신뢰 상실, 배상 청구, 평판 손상, 그리고 다시 문제를 고칠 때 드는 더 큰 시간 비용.
내 경우, 첫 번째 해킹 사건 이후로는 보안을 제일 처음 생각한다. 초기 개발 단계에서부터 OWASP Top 10을 고려해서 설계한다. 그러니까 이제는 추가로 보안 작업을 거의 안 해도 된다. 처음부터 제대로 했으니까.
더 좋은 건, 이제 보안이 마케팅이 된다는 거다. “우리 개발자는 OWASP Top 10을 완벽히 구현합니다”라고 말할 수 있다. 클라이언트들은 더 비싼 가격도 기꺼이 낸다. 왜냐하면 자기 고객 데이터가 안전하다는 보장이 있으니까.
지금이 변할 때
OWASP Top 10은 단순한 기술 표준이 아니다. 이건 프로페셔널 개발자로서의 최소 기본이다. 의사가 의료 윤리를 아는 것처럼, 변호사가 법을 아는 것처럼, 웹 개발자는 OWASP를 알아야 한다.
클라이언트는 점점 보안을 더 중시하고 있다. 특히 금융, 쇼핑, 의료 쪽 사이트를 만든다면 필수다. 그리고 법규도 점점 강해지고 있다. 개인정보보호법, GDPR 등에서 개발자들이 기본적인 보안 조치를 했는지 확인하기 시작했다.
지금이 우리가 변할 때다. OWASP Top 10을 읽고, 내 코드를 검토하고, 하나씩 개선해나가자. 그러면 더 좋은 개발자가 되고, 더 많은 클라이언트를 얻고, 더 비싼 프로젝트를 받을 수 있다.
내가 그랬으니까.