IT/기초 지식

웹 서비스를 공개하기 전 체크 리스트 (엔지니어용)

개발자 두더지 2024. 7. 9. 22:25
728x90

일본의 한 블로그 글을 번역한 포스트입니다. 오역 및 의역, 직역이 있을 수 있으며 틀린 내용은 지적해주시면 감사하겠습니다.

 

 

보안


인증과 관련된 Cookie 설정

  • HttpOnly 속성이 설정되어 있을 것
    • XSS의 완화책
  • SameStie 속성이 Lax 혹은 Strict로 되어 있을 것
    • 주된 목적은 CSRF 대책, Lax의 경우 Get 리퀘스트를 갱신 처리를 하고 있는 엔드토인트가 없는지를 함께 확인
  • Secure 속성이 설정되어 있을 것
    • HTTPS통신만 Cookie가 보내지도록 설정
  • Domain 속성이 적절히 설정되어 있을 것
    • 서브도메인에도 Cookie가 보내지도록 설정할 경우, 다른 서브 도메인의 사이트에 취약성이 있으면 사고로 연결되는 리스크를 이해해둘 것
      • 예를 들면 example.com의 Cookie가 채용 사이트의 jobs.exmaple.com에도 보내지게 되어, 그 서버에 취약성이 발생
    • Cookie명의 접두사를 __Hoist-로 하면 Domain 속성이 비어있지 않은 Cookie의 지정을 무시해준다.

 

유저의 입력 값 검증

  • 검증은 클라이언트쪽뿐만 아니라, 서버쪽에서도 행해질 것
  • 유저 입력 URL 검증이 적절하게 이뤄 질 것 
    • protocol의 제한도 잊지 말고 할 것. javascript: 와 같은 URL을 지정하지 못 하도록.
    • 정규표현을 사용할 경우, 우회로가 차단되어 있음을 체크할 것
  • 받은 HTML을 그대로 출력하는 부분에 있어서 위험한 문자열이 전달될 가능성이 배제되어 있을 것
    • element.innerHtml = input이나 React의 dangerousllySetInnerHtml과 같은 부분
    • 유저의 입력값을 표시할 때는 사전에 이스케이프나 새니타이즈(:특별한 의미를 가진 문자의 특별함을 무효화시켜 의도하지 않은 동작이나 처리가 행해지지 않도록 방지하는 것)
  • SQL인잭션이 일어날만한 SQL문이 존재하지 않을 것
  • 유저가 URL에 포함된 핸들 네임등을 지정할 수 있는 경우, 검증이 적절히 이뤄질 것
    • 유저 지정의 핸들 네임이 https://example.com/○○라고 할 경우 반드시 주의
    • 어플리케이션에서 사용하고 있는 경로나 덮어쓸 수 있는 문자는 거부
    • 언더스코어로 시작하는 문자열은 거부 (호스팅처의 클라우드 서비스가 보류하는 경우가 있음. 예를 들면 Google App Engine의 경우 /_ah가 보류됨)

 

응답 헤더

  • Strinct-Transport-Security가 응답헤더에 지정되어 있을 것
    • 브라우저에 지정된 기간중, 지정된 도메인의 접속은 항상 HTTP가 아닌 HTTPS를 사용하고 있도록 하는 지표
{
  key: 'Strict-Transport-Security',
  value: 'max-age=31536000; includeSubDomains; preload'
}
  • X-Cotent-Type-Options: nosniff가 지정되어 있을 것

 

그 외

  • 탈퇴, 메일 주소 변경 등의 공격을 특히 방지하고 싶은 부분엔 직전의 로그인을 필수로 할 것
    • XSS나 세션 하이잭이 발생했을 때의 완화책으로
  • 유저에 따라 내용이 바뀌는 리스폰드가 CDN이나 KVS에 캐시되어 있지 않을 것
  • 오브젝트 스토리지의 디렉토리 페이지의 URL가 공개되어 있지 않을 것
    • 이미지의 URL로 부터 다른 이미지의 URL을 찾을 수 없도록 한다. 서비스 사양에 따라 문제가 없지만, 설정해 두는 것이 무난
  • 클라이언트부터 전달된 URL에서 리다이렉트하는 부분에 검증 로직을 구현해 둘 것
  • 갱신, 삭제 처리에 있어서, 권한을 가지고 있지 않은 유저나 인증되지 않은 유저가 데이터를 갱신하지 못하도록 할 것
    • SQL의 DELETE나 UPDATE문에서 WHERE가 적절히 설정되어 있을 것
  • 유저로부터 전달된 문자열을 그대로 리스폰스 헤더에 포함하지 않도록 할 것
    •  리스폰스헤더가 조작될 가능성을 배제
  • 서버에서 발생한 에러 메시지를 그대로 브라우저에 표시하지 않도록 할 것
  • 파일의 업로드 기능에 있어서 파일 형식이나 사이즈, 파일 명등의 검증을 할 것
  • DB의 정기적인 버전업을 유효로 해 둘 것
  • 오브젝트 스트리지의 버전 업을 유효로 해 둘 것
  • 이용하는 브라우저 서비스의 계정에 이중인증을 유효로 해둘 것

 



로그인


  • 메일 주소의 본인 인증을 할 것
    • ID프로바이더로부터 전달된 메일 주소라고 할지라도 본인 확인이 되어 있는지 검증할 것
  • 등록되어 있는 메일 주소의 열거가 안 될 것
    • 로그인 화면이나 패스워드 재설정 화면에 "이 메일주소는 등록되어 있지 않습니다"라는 에러 메시지를 표시하면 제3자가 등록되어 있는지 아닌지를 조사할 수 있게 됨
  • 여러 로그인 방법을 제공하고 있는 경우, 동일 유저가 계정 등록했을 때의 사양이 정해져 있어 구현에 반영되어 있을 것
    • 예를 들어 메일 주소 + 패스워드 인증으로 계정을 등록한 유저가 동일한 메일 주소의 Google 계정으로 로그인했을 경우 어떻게 할 것인가
  • 메일 주소 변경이나 연계 계정의 변경이 가능할 것

 



메일 송신


  • 유저의 입력 값이 메일에 포함될 경우 해당 내용을 악용한 스팸 메일이 발송되지 않을 것
    • 예를 들어 유저명이나 아이템의 타이틀에 광고나 스팸적인 내용을 포함하면 그 내용을 편집하여 스팸 메일이 되어버리게 되는 등의 문제를 고려
  • 유저가 특정 조작을 했을 때 불특정 다수에게 반복된 메일을 송신하지 않도록 할 것
    • 예를 들어 팔로우 기능에 있어서 1만명을 팔로우하면 그 1만명에게 통지 메일을 보내는 등
  • SPF/DKIM/DMARC의 설정이 완료되어 있을 것
  • 배치 처리로 메일을 보내는 겨웅, 연속해서 처리가 호출됐을 때에도 메일이 중복되어 송신되지 않도록 할 것
  • 메거진이나 캠페인 메일의 경우, 로그인 없이 구독 취소가 되도록 할 것
  • 대량의 인원에게 캠페인 메일을 보내는 경우 List-Unsubscribe = One-Click 대응이 되어 있을 것

 

 

SEO


  • 모든 페이지에 title 태그가 적절히 설정되어 있을 것
  • SEO상 중요한 페이지는 canonical URL의 설정이 되어 있을 것
  • 에러 관련 페이지의 상태코드가 40X 혹은 50X로 되어 있거나, noindex로 되어 있을 것
  • 검색 결과 페이지에 noindex 혹은 canonical URL가 설정되어 있을 것
  • 사이트 전체적으로 noindex가 부여되어 있지 않을 것
  • 탑 페이지등의 검색 유입이 많을 것으로 예상되는 페이지에 meta desciptions가 설정되어 있을 것
  • 동적으로 공용 페이지가 생성될 경우 XML 사이트 맵을 작성하고 Search Console에 등록되어 있을 것

 

 

OGP


  • 빈번히 공유될 것으로 상정되는 페이지의 OGP 설정이 완료되어 있을것
    • og:title
    • og:description
    • og:url
    • og:image
    • twitter:card

 


결제 기능이 있는 경우


  • 회계처리를 어떻게 하는지 담당자와 확인이 되어 있을 것
  • 결제에 실패했을 때 어플리케이션 상의 데이터와 Stripe 등의 결제 대행 서비스 상의 데이터에서 부정합이 발생하지 않도록 할 것
    • 만일 발생했을 경우에는 그 사실을 검지할 수 있도록 되어 있는가
    • 예시: Stripe 상에서 결제가 성공하였으나 DB 갱신 처리에 실패하는 등
  • 중복 결제가 발생하지 않도록 구현되어 있을 것
  • 결제를 했던 적이 있는 유저가 탈퇴해도 회계나 어플리케이션 로직에 부정합이 발생하지 않도록 되어 있을 것
  • 서브스크립션을 계약적인 유저가 서비스를 탈퇴(혹은 휴식)를 했을 때 서브스크립션을 자동으로 취소되도록 되어 있을 것
  • 결제를 했던 적이 있는 유저가 탈퇴했을 때 환불 유무나 일관 계산에 대한 이용 규약을 정해 둘 것
    • 탈퇴 페이지에도 이와 관련된 내용을 명시할 것
  • 해약에 대한 동선이 준비되어 있을 것
  • 카드 기한 만료 등으로 서브스크립션 갱신에 실패했을 때의 핸들링도 구현해 둘 것. 또한 유저에게 지불 정보 갱신 동선을 제공할 것
  • 영수증이 적격 청구서의 요건을 충족할 것 (인보스이스 제도)

 


접근성


  • 이미지(<img>)의 alt 속성이 적절하게 설정되어 있을 것
  • 내부가 svg 아이콘뿐의 <button>이나 <a>의 역할이 스크린 리더가 제대로 인식되도록 할 것

 

 

퍼포먼스


  • 불필요한 모듈이 번들 JS에 포함되어 있을 않을 것
    • 릴리즈 전에 bundle-analyzer등으로 확인할 것
  • 정적 파일이 CDN에 캐시되어 있을 것
  • 이미지에 따른 레이아웃 시프트가 일어나지 않을 것
    • img요소에서 CSS의 aspect-ratio 혹은 width/height 속성을 지정
  • 필요이상의 거대한 이미지가 읽어들여지지 않아야 할 것
    • 예를 들어, 폭 400px정도의 작게 표시되어 있는 이미지의 사이즈가 실제는 2MB인 경우
  • SQL의 인덱스가 적절히 부여되어 있을 것
    • 릴리즈 후에 데이터 증가에 따른 대책으로 실시해도 괜찮음

 


여러 환경에서의 동작 확인


  • 스마트폰이나 태블릿 크게 화면등으로 표시했을 때 UI가 흐트러지지 않아야 할 것
  • 각 OS에서 봤을 때 폰트가 이상하지 않은지 확인 할 것
  • (개발 환경이 Mac인 경우) 시스템 환경 설정에서 "스크롤바 항상 표시"로 되어 있어도 문제가 없을 것
  • 유저가 지정한 핸들 네임등의 입력 값 길이에 따라 UI가 흐트러지지 않아야 할 것

 

 

그 외 기타


  • 로컬 스토리지나 http-only가 아닌 Cookie 등이 7일만에 사라져도 문제가 없을 것
    • 잘 알려져 있지 않지만, 최근 iOS Safari에서는 ITP 사양에 따라 브라우저 상의 자바스크립트에서 저장된 쿠키나 로컬 스토리지의 내용은 7일 이상 사용자가 만지지 않으면 자동으로 삭제
  • 한국어 사이트의 경우 <html lang="ko">으로 설정되어 있을 것
    • 프레임워크에 따라 기본값으로 en이 되어 있는 경우가 많으므로 주의
  • 서트 파티 Cookie에 의지하지 않을 것
  • 서버 에러가 발생했을 때 에러의 내용이 통지 혹은 검지될 수 있도록 구현해 둘 것
  • 404페이지나 50X페이지가 제대로 설정되어 있을 것
    • 404의 경우 톱 페이지 등으로의 링크 등 다음 액션이 설정되 어있을 것
  • 파비콘이 설정되어 있을 것
  • apple-touch-icon이 설정되어 있을 것
  • 필요하다면, Google Analytics 등의 액세스 해석 툴을 도입하고 있을 것
  • 서비스명이 다른 나라 언어로 해도 이상하지 않을 것

참고자료

https://zenn.dev/catnose99/articles/547cbf57e5ad28

728x90