Loading...
MySQL 9.5 Reference Manual 9.5의 8.1.7 Client Programming Security Guidelines의 한국어 번역본입니다.
아래의 경우에 피드백에서 신고해주신다면 반영하겠습니다.
감사합니다 :)
MySQL에 접근하는 클라이언트 애플리케이션은 외부 데이터를 잘못 해석하거나 민감한 정보를 노출하지 않도록 다음 지침을 따라야 합니다.
MySQL에 접근하는 애플리케이션은 사용자가 입력하는 어떤 데이터도 신뢰해서는 안 됩니다. 사용자는 웹 폼, URL 또는 당신이 만든 기타 애플리케이션에 특수 문자나 이스케이프 문자 시퀀스를 입력하여 당신의 코드를 속이려고 시도할 수 있습니다. 사용자가 폼에 ; DROP DATABASE mysql; 같은 내용을 입력해 SQL 인젝션을 시도하더라도, 애플리케이션이 계속 안전하게 동작하는지 반드시 확인하십시오. 이는 극단적인 예이지만, 이러한 유사한 기법에 대비하지 않을 경우, 해커가 비슷한 기술을 사용하여 심각한 보안 누수와 데이터 손실을 초래할 수 있습니다.
일반적인 실수는 문자열 데이터 값만 보호하는 것입니다. 숫자형 데이터도 반드시 검사해야 합니다. 애플리케이션이 사용자가 값 234를 입력했을 때 SELECT * FROM table WHERE ID=234 같은 쿼리를 생성한다면, 사용자는 234 OR 1=1 값을 입력해 애플리케이션이 SELECT * FROM table WHERE ID=234 OR 1=1 쿼리를 생성하도록 만들 수 있습니다. 그 결과 서버는 테이블의 모든 행을 가져옵니다. 이는 모든 행을 노출시키고 과도한 서버 부하를 유발합니다. 이런 유형의 공격으로부터 보호하는 가장 간단한 방법은 숫자 상수 주위에 작은따옴표를 사용하는 것입니다: SELECT * FROM table WHERE ID='234'. 사용자가 추가 정보를 입력하면, 그것은 모두 문자열의 일부가 됩니다. 숫자형 컨텍스트에서 MySQL은 이 문자열을 자동으로 숫자로 변환하고, 뒤에 오는 비숫자 문자들을 제거합니다.
일부 사람들은 데이터베이스에 공개 데이터만 들어 있다면 보호할 필요가 없다고 생각합니다. 이는 잘못된 생각입니다. 데이터베이스의 모든 행을 표시하는 것이 허용되더라도, 서버의 자원을 낭비하게 만드는(예를 들어, 앞 단락에서 설명한 기법을 기반으로 하는) 서비스 거부 공격에 대해서는 여전히 보호해야 합니다. 그렇지 않으면 서버는 정상적인 사용자의 요청에 응답하지 못하게 됩니다.
Checklist:
strict SQL 모드를 활성화하여 서버가 허용하는 데이터 값에 대해 더 엄격하게 만들십시오. Section 7.1.11, “Server SQL Modes”를 참조하십시오.
모든 웹 폼에 작은따옴표 및 큰따옴표(' 및 ")를 입력해 보십시오. 어떤 종류의 MySQL 오류라도 발생한다면, 즉시 그 문제를 조사하십시오.
동적 URL을 수정하여 그 안에 %22 ("), %23 (#), %27 (')을 추가해 보십시오.
동적 URL에서 앞의 예제들에 나온 문자들을 사용하여 데이터 타입을 숫자형에서 문자형으로 바꿔 보십시오. 애플리케이션은 이러한 공격과 유사한 공격에 대해 안전해야 합니다.
숫자 필드에 숫자 대신 문자, 공백, 특수 기호를 입력해 보십시오. 애플리케이션은 이를 MySQL에 전달하기 전에 제거하거나, 그렇지 않으면 오류를 발생시켜야 합니다. 검증되지 않은 값을 MySQL에 전달하는 것은 매우 위험합니다!
데이터를 MySQL에 전달하기 전에 크기를 확인하십시오.
애플리케이션이 데이터베이스에 연결할 때, 관리 용도로 사용하는 사용자 이름과는 다른 사용자 이름을 사용하게 하십시오. 애플리케이션에 필요하지 않은 액세스 권한은 부여하지 마십시오.
많은 애플리케이션 프로그래밍 인터페이스는 데이터 값에서 특수 문자를 이스케이프하는 기능을 제공합니다. 이를 적절히 사용하면, 애플리케이션 사용자가 당신이 의도한 것과 다른 효과를 내는 문장을 애플리케이션이 생성하도록 만드는 값을 입력하지 못하게 할 수 있습니다:
MySQL SQL 문장: SQL 프리페어드 스테이트먼트를 사용하고, 플레이스홀더를 통해서만 데이터 값을 받으십시오. Section 15.5, “Prepared Statements”를 참조하십시오.
MySQL C API: mysql_real_escape_string_quote() API 호출을 사용하십시오. 또는 C API 프리페어드 스테이트먼트 인터페이스를 사용하고, 플레이스홀더를 통해서만 데이터 값을 받으십시오. C API Prepared Statement Interface를 참조하십시오.
MySQL++: 쿼리 스트림에 escape 및 quote 한정자를 사용하십시오.
PHP: mysqli 또는 pdo_mysql 확장을 사용하고, 오래된 ext/mysql 확장은 사용하지 마십시오. 선호되는 API는 개선된 MySQL 인증 프로토콜과 비밀번호, 그리고 플레이스홀더를 사용하는 프리페어드 스테이트먼트를 지원합니다. MySQL and PHP도 참조하십시오.
오래된 ext/mysql 확장을 반드시 사용해야 한다면, 이스케이프에는 mysql_real_escape_string_quote() 함수를 사용하고, mysql_escape_string()이나 addslashes()는 사용하지 마십시오. 문자 집합을 인식하는 것은 mysql_real_escape_string_quote()뿐이며, 다른 함수는 (유효하지 않은) 멀티바이트 문자 집합을 사용할 때 “우회”될 수 있습니다.
Perl DBI: 플레이스홀더나 quote() 메서드를 사용하십시오.
Java JDBC: PreparedStatement 객체와 플레이스홀더를 사용하십시오.
다른 프로그래밍 인터페이스에도 유사한 기능이 있을 수 있습니다.
애플리케이션은 MySQL 데이터베이스 서버에서 SQL 문장을 실행한 결과로 발생하는 오류를 가로채고, 이를 적절히 처리할 책임이 있습니다.
MySQL 오류에서 반환되는 정보는 단순한 서비스 차원의 정보가 아닙니다. 이 정보는 MySQL을 사용하는 애플리케이션을 디버그할 때 핵심적인 역할을 합니다. 예를 들어, 문제가 되는 데이터베이스, 테이블 및 기타 객체가 무엇인지에 대한 정보 없이 일반적인 10-way 조인 SELECT 문장을 디버그하는 것은 사실상 불가능할 것입니다. 따라서 MySQL 오류에는 때때로 이러한 객체 이름에 대한 참조가 반드시 포함될 수밖에 없습니다.
애플리케이션이 MySQL로부터 이런 오류를 받았을 때, 이를 가로채 클라이언트에게 있는 그대로 표시하는 것은 단순하지만 안전하지 않은 접근 방식입니다. 그러나 오류 정보를 노출하는 것은 알려진 애플리케이션 취약점 유형이며 (CWE-209), 애플리케이션 개발자는 애플리케이션에 이 취약점이 존재하지 않도록 해야 합니다.
예를 들어, 다음과 같은 메시지를 표시하는 애플리케이션은 클라이언트에게 데이터베이스 이름과 테이블 이름 모두를 노출하는데, 이는 클라이언트가 악용을 시도할 수 있는 정보입니다:
1ERROR 1146 (42S02): Table 'mydb.mytable' doesn't exist
대신, 애플리케이션이 MySQL로부터 이러한 오류를 받았을 때의 올바른 동작은, 오류 정보를 포함한 적절한 정보를 신뢰할 수 있는 인원만 접근할 수 있는 보안 감사 위치에 로그로 기록하는 것입니다. 애플리케이션은 사용자에게 “Internal Error”와 같은 보다 일반적인 내용을 반환할 수 있습니다.
8.1.6 Security Considerations for LOAD DATA LOCAL
8.2 Access Control and Account Management