보안

이 페이지에서는 웹 보안과 관련된 몇 가지 “모범 사례”와 CodeIgniter의 내부 보안 기능에 대해 설명합니다.

참고

보안 연락처를 찾고 있다면 기여 가이드 <../contributing/index>를 참조하세요.

URI 보안

CodeIgniter는 악의적인 데이터가 애플리케이션에 전달될 가능성을 최소화하기 위해 URI 문자열에 허용되는 문자에 대해 상당히 제한적입니다. URI에는 다음만 포함될 수 있습니다:

  • 영숫자 텍스트 (라틴 문자만)

  • 틸드: ~

  • 퍼센트 기호: %

  • 마침표: .

  • 콜론: :

  • 밑줄: _

  • 대시: -

  • 공백

Register_globals

시스템 초기화 중에 $_GET, $_POST, $_REQUEST, $_COOKIE에 존재하는 것으로 확인된 모든 전역 변수가 unset됩니다.

해제 루틴은 register_globals = off와 효과적으로 동일합니다.

display_errors

프로덕션 환경에서는 일반적으로 내부 display_errors 플래그를 0으로 설정하여 PHP의 에러 보고를 “비활성화”하는 것이 좋습니다. 이렇게 하면 민감한 정보가 포함될 수 있는 기본 PHP 에러가 출력으로 렌더링되는 것을 비활성화합니다.

index.php에서 CodeIgniter의 ENVIRONMENT 상수를 'production' 값으로 설정하면 이러한 에러가 꺼집니다. 개발 모드에서는 ‘development’ 값을 사용하는 것이 좋습니다. 환경 구분에 대한 자세한 내용은 환경 처리 페이지에서 찾을 수 있습니다.

magic_quotes_runtime

magic_quotes_runtime 지시문은 시스템 초기화 중에 꺼져 있으므로 데이터베이스에서 데이터를 검색할 때 슬래시를 제거할 필요가 없습니다.

모범 사례

폼 제출의 POST 데이터, COOKIE 데이터, URI 데이터, XML-RPC 데이터, 심지어 SERVER 배열의 데이터든 애플리케이션에 데이터를 수락하기 전에 다음 세 단계 접근 방식을 실천하는 것이 좋습니다:

  1. 데이터가 올바른 유형, 길이, 크기 등을 준수하는지 검증합니다.

  2. 오염된 것처럼 데이터를 필터링합니다.

  3. 데이터베이스에 제출하거나 브라우저에 출력하기 전에 데이터를 이스케이프합니다.

CodeIgniter는 이 과정을 도와주는 다음 함수와 팁을 제공합니다:

XSS 필터링

CodeIgniter에는 크로스 사이트 스크립팅 필터가 있습니다. 이 필터는 데이터에 악성 JavaScript를 삽입하거나 쿠키를 가로채거나 다른 악의적인 일을 하려는 다른 유형의 코드를 임베드하는 데 일반적으로 사용되는 기법을 찾습니다. XSS 필터는 여기에 설명되어 있습니다.

참고

XSS 필터링은 출력에서만 수행해야 합니다. 입력 데이터를 필터링하면 비밀번호에서 특수 문자를 제거하는 등 원하지 않는 방식으로 데이터를 수정할 수 있으며, 이는 보안을 향상시키는 것이 아니라 오히려 약화시킵니다.

CSRF 보호

CSRF는 Cross-Site Request Forgery의 약자로, 공격자가 피해자를 속여 모르게 요청을 제출하게 만드는 과정입니다.

CodeIgniter는 기본적으로 CSRF 보호를 제공하며, GET이 아닌 모든 HTTP 요청에 대해 자동으로 트리거되지만, 특정 방식으로 제출 양식을 만들어야 합니다. 이것은 Security 라이브러리 문서에 설명되어 있습니다.

비밀번호 처리

애플리케이션에서 비밀번호를 올바르게 처리하는 것은 매우 중요합니다.

안타깝게도 많은 개발자들이 이 방법을 모르고 있으며, 웹에는 오래되거나 잘못된 조언들이 가득해서 도움이 되지 않습니다.

다음은 도움을 드리기 위한 해야 할 것과 하지 말아야 할 것의 결합 목록입니다. 아래를 읽어보세요.

  • 비밀번호를 평문 형식으로 저장하지 마세요.

    항상 비밀번호를 해시하세요.

  • 비밀번호 저장에 Base64 또는 유사한 인코딩을 사용하지 마세요.

    이것은 평문으로 저장하는 것만큼이나 좋지 않습니다. 정말로. 인코딩이 아닌 해싱을 하세요.

    인코딩과 암호화 모두 양방향 프로세스입니다. 비밀번호는 소유자만 알아야 하는 비밀이므로 한 방향으로만 작동해야 합니다. 해싱이 그것을 합니다 - 언해싱이나 디해싱은 없지만 디코딩과 복호화는 있습니다.

  • MD5나 SHA1 같은 약하거나 깨진 해싱 알고리즘을 사용하지 마세요.

    이 알고리즘들은 오래되어 결함이 있음이 증명되었으며 애초에 비밀번호 해싱을 위해 설계되지 않았습니다.

    또한 자신만의 알고리즘을 만들지 마세요.

    PHP의 자체 비밀번호 해싱 함수에서 사용되는 BCrypt와 같은 강력한 비밀번호 해싱 알고리즘만 사용하세요.

    PHP 5.5+를 실행하지 않더라도 이것들을 사용하세요. CodeIgniter가 제공합니다.

  • 비밀번호를 평문 형식으로 표시하거나 전송하지 마세요!

    비밀번호 소유자에게도 마찬가지입니다. “비밀번호 찾기” 기능이 필요한 경우 새로운 일회용(이것도 중요합니다) 비밀번호를 무작위로 생성하여 대신 보내세요.

  • 사용자 비밀번호에 불필요한 제한을 두지 마세요.

    BCrypt(72자 제한이 있음) 이외의 해싱 알고리즘을 사용하는 경우 DoS 공격을 완화하기 위해 비밀번호 길이에 비교적 높은 제한(예: 1024자)을 설정해야 합니다.

    그 외에는 비밀번호가 특정 수의 문자까지만 가능하거나 특정 특수 문자를 포함할 수 없다는 규칙을 강제할 이유가 없습니다.

    이것은 보안을 향상시키는 것이 아니라 오히려 약화시킬 뿐만 아니라, 말 그대로 그렇게 할 이유가 없습니다. 해시한 후에는 기술적 제한도 (실질적인) 저장 제약도 없습니다, 전혀!

입력 데이터 검증

CodeIgniter에는 데이터를 검증, 필터링, 준비하는 데 도움이 되는 폼 검증 라이브러리가 있습니다.

하지만 사용 사례에 맞지 않더라도 모든 입력 데이터를 항상 검증하고 정제해야 합니다. 예를 들어 입력 변수에 숫자 문자열이 필요한 경우 is_numeric() 또는 ctype_digit()로 확인할 수 있습니다. 항상 특정 패턴으로 확인 범위를 좁히려고 하세요.

이것은 $_POST$_GET 변수뿐만 아니라 쿠키, 사용자 에이전트 문자열, 기본적으로 자신의 코드에서 직접 생성되지 않은 모든 데이터도 포함한다는 것을 명심하세요.

데이터베이스 삽입 전 모든 데이터 이스케이프

이스케이프하지 않고 데이터베이스에 정보를 삽입하지 마세요. 자세한 내용은 데이터베이스 쿼리를 논의하는 섹션을 참조하세요.

파일 숨기기

또 다른 좋은 보안 관행은 서버의 webroot 디렉터리(일반적으로 “htdocs/”로 명명됨)에 index.php와 “assets”(예: .js, css, 이미지 파일)만 남겨두는 것입니다. 이것들이 웹에서 접근 가능해야 하는 유일한 파일입니다.

방문자가 다른 것을 볼 수 있게 허용하면 민감한 데이터에 접근하거나 스크립트를 실행하는 등의 가능성이 있습니다.

그렇게 할 수 없다면 .htaccess 파일을 사용하여 해당 리소스에 대한 접근을 제한할 수 있습니다.

CodeIgniter는 이 데이터의 일부를 숨기기 위해 모든 디렉터리에 index.html 파일을 두지만, 이것만으로는 심각한 공격자를 막기에 충분하지 않다는 것을 명심하세요.