2009년 10월 30일 금요일

MySQL 보안 - SSL통신6

클라이언트에서 접속

--ssl옵션을 사용해서 접속한다. 키는 ~/.bimil/에 보존지정한다고 가정한다.

shell$ mysql --ssl --ssl-key=~/.bimil/private.pem --ssl-cert=~/.bimil/cert.pem

보통은 만약 SSL의 handshake에 실패하면 평문대로 접속한다.

서버에 접속한 후 STATUS나 SHOW STATUS를 실행하면 SSL로 접속하고 있는지 그렇지 않은지 확인할 수 있다.

○SSL통신을 개시한 경우
mysql> SHOW STATUS LIKE 'Ssl_cipher';
------------------------------------------------
Variable_name | Value
------------------------------------------------
Ssl_cipher | DHE-RSA-AES256-SHA
------------------------------------------------

○SSL통신을 개시하지 못했을 경우
mysql> STATUS
(중략)
SSL: Not in use
(중략)




2009년 10월 18일 일요일

MySQL 보안 - SSL통신5

●Certificate Request 파일에 서명하기

각 Certificate Request 파일을 local CA로 서명한다.

root@shell# openssl ca -policy policy_anything -out signed-cert.pem -in dareka-csr.pem

local CA의 키를 사용해 인증하고픈 누군가의 Certificate Request파일에 서명을 한다.
-out로 지정된 파일이 서명이 끝난 파일이 된다.

policy_anything은 openssl.cnf섹션에 설정되어 있다. 그곳에서는 어느 항목이 필수인가 지정되어 있다. policy_anything은 commonName만이 필수항목으로 되어있다.


policy 섹션에서 키워드에 주어지는 값의 의미


match: 필수항목 그리고 내용은 인증국과 일치
supplied: 필수항목, 내용은 상관없음
optional:있거나 없거나 상관없음.

●MySQL옵션에 파일을 지정하기

서명된 signed-cert.pem파일을 MySQL옵션 --ssl-cert=에 지정하고 --ssl-ca나 --ssl-capath=에 CA의 CERTIFICATE 파일을 지정한다.

예를 들어 다음 예의 경우, 2가지 지정방법이 있다.

  • local CA의 CETIFICATE파일: local-ca-cert.pem
  • local CA에 사인된 파일 : signed-cert.pem
  • private key: private-key.pem
①--ssl-key=private-key.pem --ssl-cert=signed-cert.pem --ssl-ca=local-ca-cert.pem
②--ssl-key=private-key.pem --ssl-cert=signed-cert.pem --ssl-capath= {local-ca-cert.pem을 보존하는 디렉토리 }

local-ca-cert.pem을 보존하는 디렉토리에는 local-ca-cert.pem파일을 보존하는 것만으로는 부족하고 파일의 해쉬를 이름으로 한 파일을 작성할 필요가 있다.

local-ca-cert.pem해쉬
shell$ openssl x509 -hash -noout -in local-ca-cert.pem
a808a98b

local-ca-cert.pem의 해쉬를 붙인 파일을 작성하고 local-ca-cert.pem과 같은 디렉토리에 놓는다.
다음 처럼 조작한다.

local-ca-cert.pem 복사와 해쉬를 파일명으로 한 파일의 작성
shell# cp local-ca-cert.pem capath/
shell# cd capath/
shell# ln -s local-ca-cert.pem a808a98b.0

ln 대신 cp여도 상관없다.
파일명이 "해쉬.숫자"로 되어있다. 숫자는 0이상 정수를 자유로 붙이면 된다.
이것은 만에 하나 해쉬가 다른 파일의 해쉬하고 일치했을 경우에 구별을 두기위한 것이다.

2009년 10월 15일 목요일

MySQL 보안 - SSL통신4

● 자기의 CA섹션을 openssl.cnf에 추가한다.

OpenSSL설정파일, openssl.cnf파일의 [ CA_default ]를 참고로 자기의 CA섹션을 openssl.cnf에 추가한다. 이름은 적당히 붙인다.
ca_my여도 상관없다.
또, openssl.cnf파일을 복사한 다음, 표준인 [ CA_default ] 를 편집해도 상관없다.

● 자기 인증국 키를 작성한다.

자기 인증국(local CA)의 키를 작성한다. 이것은 서버 키를 작성하는 순서와 마찬가지이다.

자기인증국 키 작성
root@shell# openssl req -new -x509 -keyout local-ca-key.pem -out local-ca-cert.pem -days 10000

local CA용으로 추가한 이름이 ca_my인 경우, -name ca_my옵션을 추가한다.
여기에서 작성한 키 파일이름을 openssl.cnf파일에 지정해 둔다.
CA정의 섹션에서는 dir, certificate, private_key, serial, database 변수에 주의해야한다.

기본값은 openssl.cnf에 기재되어 있다.

OpenSSL에는 인증국 작성 작업을 한번에 수행하는( 키를 작성하거나 디렉토리나 파일을 작성하거나 한다. ) CA.sh 스크립트가 부속되어 있다.

CA.sh스크립트는 디렉토리명등이 고정되어 있기때문에 편한대로 맞춰서 편집해서 실행하면 될 듯 싶다.
편집할 때는 openssl.cnf의 local CA용 섹션 기술과 맞춰놓도록 한다.

예> root@shell# bash CA.sh -newca

2009년 10월 13일 화요일

MySQL 보안 - SSL통신3

자기 인증국을 세우기

데이터베이스 서버이기때문에 보통은 일반 대다수에게 무작위로 공개하지는 않을 것이다.

제 3자기관의 서명을 받을 것이 아니라 자기 스스로 인증국을 세워 그곳에서 인증하는 방법도 있다.


● 전제지식: OpenSSL 설정파일 또는 사용할 CA섹션을 지정한다.

OpenSSL은 표준 openssl.cnf파일(컴파일할 때 고정됨)을 읽어들여 동작한다.
자기 스스로 인증국으로 하는 경우는 이 파일을 편집하거나 바꿀 필요가 있다.

①별도 파일을 설정파일에 지정한다.
만약 설정파일을 별도의 파일로 했을 경우는 다음과 같이 설정파일을 앞으로 실행하는 모든 명령어 라인의 최초의 옵션에 추가하면 된다.

-config 설정파일

다른 옵션 후에 지정하면 무효가 될 수 있다.

②사용할 CA섹션을 지정한다.
각 CA섹션은 파일내에 [섹션명]으로 정의되어 있지만 [ ca ]섹션 안의 default_ca키워드가 표준으로 사용되는 CA섹션이라는 의미이다.
이것과는 다른 CA섹션을 읽어들이는 경우의 옵션은 다음과 같이 된다.

-name CA섹션명

이것을 각 명령에 추가하면 읽어들이는 섹션은 바뀌게 된다.





2009년 10월 11일 일요일

MySQL 보안 - SSL통신2

서버측 키 생성

■private key 파일 생성

MySQL서버가 사용하는 private key파일(server-key.pem), Certificate Request파일(server-csr.pem)을 작성한다. ( 파일명은 임의로 붙여도 된다. )

※private key파일과 Certificate Request파일 작성
root@shell# openssl req -new -nodes -keyout server-key.pem -out server-csr.pem -days 1000

--nodes를 빼면 pass phrase이 요구되는 키를 작성한다. Common Name ( ....)[] : 에는 서버의 FQDN을 입력해야한다.
또 다음처럼 조작하더라도 같은 결과를 얻을 수 있다.

※make PRIVATE KEY
root@shell# openssl genrsa -des3 -out server-key.pem 1024

※remove pass phrase
root@shell# openssl rsa -in server-key.pem -out server-key.pem

※make CERTIFICATE REQUEST
root@shell# openssl req -new -key server-key.pem -out server-csr.pem -days 1000

■자기 서명 파일 생성
X.509 CERTIFICATE 파일(server-cert.pem)을 작성한다. 스스로 사인(자기서명)을 해 둔다.

※서명
root@shell# openssl x509 -in server-csr.pem -out server-cert.pem -req -signkey server-key.pem -days 1000

■private key 파일과 자기서명 파일의 동시 작성
또, 지금까지의 순서를 정리해서 한번에 private key 파일과 자기서명 파일을 작성할 수 있다.

root@shell# openssl req -new -x509 -nodes -keyout server-key.pem -out server-cert.pem -days 1000

■my.cnf설정
키를 작성했으면 mysqld옵션에 지정해 둔다.

[mysqld]
ssl
ssl-key=/usr/local/mysql/secu/server-key.pem
ssl-cert=/usr/local/mysql/secu/server-cert.pem #주의: 서명한 파일.

#ssl-ca=/usr/local/mysql/secu/ca_cert.pem
#ssl-ca는 CA(Certificate Authority) 증명서이다.

제 3자 인증기관 증명이 필요한 경우에는 server-csr.pem파일( Certificate Request)을 해당 기관에 보낸다. 그리고 인증기관으로부터 받은 서명확인완료 파일을 ssl-cert옵션에 지정한다.
또, ssl-ca나 ssl-capath를 지정할 필요가 있다.


클라이언트 키 생성

클라이언트 키 생성도 서버에서와 마찬가지로 만드는 법은 같다.

2009년 10월 8일 목요일

MySQL 보안 - SSL통신


MySQL의 서버와 클라이언트 사이의 통신을 SSL암호화하는 것이 가능하다.
SSL통신을 실행하려면 서버와 클라이언트 양쪽에 SSL을 구성할 필요가 있다.

SSL구성의 확인
mysql>SHOW VARIABLES LIKE 'have_openssl';

결과가 YES 또는 DISABLED이면 서버에 SSL구성되어 있는 것이다.  DISABLED인 경우 SSL은 구성되어있지만 ssl옵션을 붙여서 서버가 기동되지 않았다라는 뜻이다. NO인 경우는 SSL가 포함되어있지 않으므로 소스에서 부터 MySQL을 빌드할 필요가 있다.

SSL구성

configure옵션에서는 --with-ssl를 지정한다.
다만, --with-openssl-includes, --with-openssl-libs, --with-yassl옵션은 5.1.11-beta에서 폐지되었으므로 주의해야한다.

SSL의 구성
shell$ ./configure --with-ssl [=OpenSSL 인스톨 디렉토리]

OpenSSL인스톨 디렉토리를 지정하면 지정된 디렉토리에 있는 OpenSSL라이브러리를 사용한다.
디렉토리지정을 생략하면 소스 부속의 yaSSL(extra/yassl/)를 사용한다.

현재 OpenSSL을 사용할 경우 핸드쉐이크할 때 miss가 적다고 한다.
디렉토리를 지정해서 OpenSSL을 사용하는 것이 좋을 듯 싶다.





2009년 10월 6일 화요일

MySQL 권한 5

Password Hashing

MySQL에서는 패스워드는 독자의 방법으로 암호화된다. (한방향)

MySQL 4.1에서 이 방식이 변경되었다.

mysql> select password('mycom');
+-------------------------------------------+
| password('mycom') |
+-------------------------------------------+
| *5BD79BBCCD59CEB5DC80FB46F393EC6FA414994D |
+-------------------------------------------+
1 row in set (0.00 sec)

mysql> select old_password('mycom');
+-----------------------+
| old_password('mycom') |
+-----------------------+
| 0425a28758eb7712 |
+-----------------------+
1 row in set (0.00 sec)

4.1이상의 패스워드는 PASSWORD() 함수에서 4.0이하의 패스워드는 OLD_PASSWORD()함수로 확인할 수 있다.

또 4.1이상에서 4.0까지의 암호화를 사용하려면 다음과 같은 방법이 있다.

①mysqld --old-passwords
②SQL문에서는 OLD_PASSWORD()함수를 사용한다.

old-passwords옵션을 지정하면 4.1이상의 PASSWORD()함수는 OLD_PASSWORD()함수와 같은 동작을 한다.


4.0이하의 클라이언트에서 4.1이상의 서버에 접속하려고 하면 다음과 같은 에러가 나올 때가 있다.

"Client does not support authentication protocol requested by server; consider upgrading MySQL client"

이것에 대처하기 위해서는 mysql.user.Password컬럼의 값을(패스워드) OLD_PASSWORD()함수로 세팅한다.



MySQL 권한 4

권한 계산

권한의 식을 간단하게 나타내면 다음과 같다.

글로벌권한
OR ( db권한 AND host권한 )
OR table권한
OR column권한
OR routine권한

이것을 테이블로 바꾸면 다음과 같다.

user
OR ( db AND host)
OR tables_priv
OR columns_priv
OR procs_priv

계산순서는 다음과 같다.

①user테이블 권한(글로벌 권한)을 확인
②db테이블 권한 확인
③db.Host == ''일 때, host테이블을 확인한다.
④순차로 tables_priv과 columns_priv, procs_priv테이블 설정을 확인한다.

db테이블과 host테이블 처리에 주의해야한다.


2009년 10월 5일 월요일

MySQL 권한 3

권한 테이블

권한은 "권한테이블"이라고 불리우는 테이블에 기록된다. 권한테이블에는 다음과 같은 것이 있다. 이것은 mysql데이터베이스의 테이블이다. 그리고 권한테이블은 MyISAM이지 않으면 안된다.

  • user
  • db
  • host
  • tables_priv
  • columns_priv
  • procs_priv

●user테이블
글로벌 권한을 세팅한다. 따라서 user테이블의 권한 칼럼에 Y가 세팅되어있으면 다른 권한 테이블에서 N으로 해도 권한 계산 결과는 Y 그대로 이다. 그외에 패스워드나 최대접속횟수, SSL 접속정보등도 기록된다.

●db테이블
데이터베이스에 대한 권한을 부여한다. db.Host == ''의 경우 host테이블을 참조한다.
db.Host == '%'인 경우는 모든 호스트라는 의미가 된다.

●host테이블
host.Host == '' 나 host.Host == '%'의 경우 모든 호스트라는 의미가 된다.

●tables_priv테이블, columns_priv테이블, pros_priv테이블
Db, Table_name, Column_name칼럼에는 ''나 와일드카드는 사용할 수 없다. Host컬럼에는 와일드카드를 사용할 수 있다.
Host컬럼이 '%'또는 ''인 경우에는 모든 호스트라는 의미가 된다.
이 테이블들의 모든 Host, DB컬럼에는 와일드 카드 %, _ 를 사용할 수 있다.
User컬럼 == ''의 경우 Anonymous유저를 나타낸다.

2009년 10월 4일 일요일

MySQL 권한 2

GRANT문으로 지정가능한 권한

FILE, PROCESS, RELOAD, REPLICATION CLIENT, REPLICATION SLAVE, SHOW DATABASES, SHUTDOWN, SUPER권한은 글로벌권한만( ON *.*) 존재하므로 주의해야한다.
이것들은 데이터베이스 단위나 호스트단위로 권한을 바꾸는 것은 되지 않는다.


ALL, USAGE

일반
: ALTER, CREATE, CREATE TEMPORARY TABLES, DELETE, DROP, FILE, INDEX, INSERT, LOCK TABLES, SELECT, SHOW DATABASES, UPDATE

뷰, 스토어드 프로시져, 트리거
CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EXECUTE, TRIGGER

이벤트스케줄러
EVENT

관리자
CREATE USER, PROCESS, RELOAD, SHUTDOWN, SUPER

권한복사
GRANT OPTION

복제
REPLICATION SLAVE
REPLICATION CLIENT



2009년 10월 1일 목요일

MySQL 권한

MySQL권한에는 적용범위가 있다. 권한이 어느 범위에 부여되는지에 대해서 주의할 필요가 있다.

MySQL에서는 이것을 Scope라고 부른다. scope에는 다음과 같은 것이 있다.

글로벌
이 범위에 부여된 권한은 다른 scope에서 어떠한 설정을 하더라도 바뀌지 않는다.

호스트/DB/테이블/컬럼
글로벌권한보다도 적용범위가 좁게 된다. 각각 호스트나 DB단위로 권한을 설정하는 것이 가능하다.
글로벌 scope를 부여한 권한은 (글로벌 권한이라 부른다. ) 다른 scope에의한 설정을 무시한다.

다시말하면, 글로벌로 권한을 부여한 경우 아무리 호스트로 권한을 N으로 하더라도 권한은 부여된 상태이다.