Tweet

Geniş Mysql Güvenliği





MySQL Internet üzerindeki en popülerveritabanlarından biridir ve sıklıkla PHP ile birlikte kullanılır.Yüksek performansına oranla kolay kullanımı gibi bir çok avantajı biryana, MySQL basit fakat çok etkili bir güvenlik mekanizmasısunmaktadır.[...]

MySQL Internet üzerindeki en popüler veritabanlarından biridir vesıklıkla PHP ile birlikte kullanılır. Yüksek performansına oranla kolaykullanımı gibi bir çok avantajı bir yana, MySQL basit fakat çok etkilibir güvenlik mekanizması sunmaktadır. Ne yazık ki, MySql'in defaultkurulumu, şifresiz root yetkisi sağlaması ve hafıza taşması ataklarıiçin potansiyel güvelik açıkları bulundurması bu veritabanınısaldırılar için kolay hedef haline getirmektedir. Bu makale, lokal veuzak saldırılara karşı MySql'in nasıl güvenli hale getirilebileceğinintemel adımların tarif etmektedir.

Fonksiyonellik

Makalemizde bir önceki Apache ile ilgili makalemizde belirtilenlereuygun olarak üzerinde PHP kurulmuş Apache sunucumuz olduğunuvarsayacağız ve bu da /chroot/httpd dizininde bulunacak.
Yukarıdakilerden farklı olarak, aşağıda belirtilenlerinvarolduğunu kabul edeceğiz: MySQL veritabanı sadece PHP uygulamalarıiçin kullanılacak, aynı host üzerinde kurulu olacak;
Mysqladmin, mysql, mysqldump gibi default yönetim araçları veritabanı yönetimi için kullanılacaktır;
Uzaktan veri yedeklemesi SSH protokolü kullanılarak gerçekleşecektir.

Güvenlik Gereklilikleri

Yüksek güvenlik seviyesi sağlamak için, MYSQL'in kurulumu vekonfigürasyonu, aşağıda belirtilen güvenlik gerekliliklerigerçekleştirilmelidir:
MySQL veritabanı chroot edilmiş ortamda uygulanacaktır;
MySQL işlemleri tek bir UID/GID altında çalışacak ve bu başka bir sistem işlemi için kullanılmayacaktır;

MYSQL'e sadece lokal erişime izin verilecektir;
MySQL root hesabı tahmini zor bir şifre ile korunacaktır;
Yönetici hesabı ismi değiştirilecektir;
Veritabanına Anonim erişim ( Nobody hesabı ile) engellenecektir;
Tüm örnek veritabanları ve tablolar silinecektir.

MySQL Kurulumu

MySQL güvenliğine başlamadan önce, sunucu üzerine yazılımıyüklemeliyiz. Daha önceki makalelerde olduğu gibi, kuruluma, işletimsistemi üzerinde MySQL veritabanı için kullanılacak tek ve düzgün grupve kullanıcı hesabı yaratmakla başlayacağız:
pw groupadd mysql
pw useradd mysql -c "MySQL Server" -d /dev/null -g mysql -s /sbin/nologin


MySQL'i Derlemek

MYSQL yazılımını /usr/local/mysql dizini içinde derleyip kuracağız:
configure --prefix=/usr/local/mysql --with-mysqld-user=mysql--with-unix-socket-path=/tmp/mysql.sock--with-mysqld-ldflags=-all-static
make
su
make install
strip /usr/local/mysql/libexec/mysqld
scripts/mysql_install_db
chown -R root /usr/local/mysql
chown -R mysql /usr/local/mysql/var
chgrp -R mysql /usr/local/mysql

Genellikle, sunucu üzerinde kuurlum işlemleri daima MySQLmanuelinde tarif edildiği gibidir.Tek değişiklik ise ./configuresatırında belirtilmiş birkaç ilgili parametrenin kullanımıdır. Enönemli farklılık ise MySQL'in statik linklenmesine etki eden--with-mysqld-ldflags=-all-static parametresinin kullanımıdır. Bu, 3.bölümde de tarif edildiği gibi, önemli bir değerde sunucu chrootayarlama işlemlerini basite indirger. Diğer parametreleri de dikkatealırsak, bunlar da programa /usr/local/mysql dizinine yazılımıyüklemesi emrini verir, mysql account yetkisinde MySQL Daemon'uçalıştırır ve /tmp dizininde mysql.sock socket'i oluşturur.

Konfigürasyon Dosyasının Kopyalanması

Yukarıdaki komutlar uygulandıktan sonra, veritabanının muhtemelboyutuna göre (küçük, orta, büyük, çok büyük) default konfigürasyondosyasını kopyalamalıyız. Örneğin:

cp support-files/my-medium.cnf /etc/my.cnf
chown root:sys /etc/my.cnf
chmod 644 /etc/my.cnf

Sunucunun Çalıştırılması

Bu noktada MySQL tamamı ile yüklenmiş ve çalışmaya hazırdır.Aşağıdaki komutu kullanarak MySQL'i çalıştırabiliriz:

/usr/local/mysql/bin/mysqld_safe &

Bağlantı Testi

Aşağıdaki şekilde veritabanı ile bağlantı kurmaya çalışın:
/usr/local/mysql/bin/mysql -u root mysql

Welcome to MySQL Monitor. Commands end with ; or g. Your MySQLconnection id is 2 to server version: 4.0.13-log Type 'help;' or 'h'for help. Type 'c' to clear the buffer.

mysql> show databases;
+----------+
| Database |
+----------+
| mysql |
| test |
+----------+
2 rows in set (0.00 sec)

mysql> quit;

Birkez bağlantı başarılı olarak sağlandığında, veritabanını kapatabiliriz:
/usr/local/mysql/bin/mysqladmin -u root shutdown

ve yazılımın güvenliğine başlayabiliriz. Aksi halde, the/usr/local/mysql/var/`hostname`.err log dosyasını analiz etmeli ve bazısorunları elimine etmeliyiz.

Sunucu Chroot Ayarları

MySQL güvenliğindeki ilk adım, MySQL sunucunun çalışacağı chrootedilmiş bir alan hazırlanmasıdır. Chroot tekniği "' Adım adım ApacheGüvenliği"' makalemizde ayrıntılı olarak tarif edilmişti, bu sebepleeğer bu teknik hakkında bilginiz yoksa ya da neden gerekli olduğunuöğrenmek istiyorsanız, bahse konu makaleyi okumanızı tavsiye ederim.

İşletim Sistemi

Bir önceki makalede olduğu gibi, işletim sistemimiz FreeBSD 4.7.Ancak belirtilen metotlar gelişmiş Unix ve Unix_benzeri sistemlerde deuygulanabilir.

Chroot Alanı Hazırlama

Chroot alanı hazırlamak için, aşağıdaki dizin yapısını oluşturmamız gerekiyor:
mkdir -p /chroot/mysql/dev
mkdir -p /chroot/mysql/etc
mkdir -p /chroot/mysql/tmp
mkdir -p /chroot/mysql/var/tmp
mkdir -p /chroot/mysql/usr/local/mysql/libexec
mkdir -p /chroot/mysql/usr/local/mysql/share/mysql/english

Erişim Haklarının Ayarlanması

Yukarıda belirtilen dizinlere erişim hakları, aşağıdaki şekilde ayarlanmalıdır:
chown -R root:sys /chroot/mysql
chmod -R 755 /chroot/mysql
chmod 1777 /chroot/mysql/tmp

Dizin Yapısı Oluşturmak

Sonrasında ise, aşağıdaki dosyalar yeni dizin yapısıne kopyalanmalıdır:

cp /usr/local/mysql/libexec/mysqld /chroot/mysql/usr/local/mysql/libexec/
cp /usr/local/mysql/share/mysql/english/errmsg.sys /chroot/mysql/usr/local/mysql/share/mysql/english/
cp /etc/hosts /chroot/mysql/etc/
cp /etc/host.conf /chroot/mysql/etc/
cp /etc/resolv.conf /chroot/mysql/etc/
cp /etc/group /chroot/mysql/etc/
cp /etc/master.passwd /chroot/mysql/etc/passwords
cp /etc/my.cnf /chroot/mysql/etc/

Şifreleri ve Grupları Güçlendirmek

Mysql hesabı ve grubu hariç, /chroot/mysql/etc/passwords ve/chroot/mysql/etc/group dosyalarından tüm satırları kaldırmalıyız.Sonra, aşağıda belirtildiği şekilde şifre veritabanı oluşturmalıyız (Busadece FreeBSD sistemlerde uygulanır):
cd /chroot/mysql/etc
pwd_mkdb -d /chroot/mysql/etc passwords
rm -rf /chroot/mysql/etc/master.passwd

Özel Hususlar

Apache web sunucu kullanımı halinde, özel bir aygıt dosyası yaratmalıyız /dev/null:
ls -al /dev/null
crw-rw-rw- 1 root sys 2, 2 Jun 21 18:31 /dev/null
mknod /chroot/mysql/dev/null c 2 2
chown root:sys /chroot/mysql/dev/null
chmod 666 /chroot/mysql/dev/null

Ayrıca, MySQL kurulumunda oluşturulmuş grant tablolar içeren mysql veritabanını da kopyalamalıyız:
cp -R /usr/local/mysql/var/ /chroot/mysql/usr/local/mysql/var
chown -R mysql:mysql /chroot/mysql/usr/local/mysql/var

Sabitleme

Eğer ingilizce haricinde başka bir dil kullanılacaksa, ayrıca/usr/local/mysql/share/mysql/charsets dizininden ilgili charset'leri dekopyalamalıyız.

Konfigürasyonun Testi

Bu noktada MySQL Chroot edilmiş alanda çalışmaya hazırdır. Eğer doğru çalışıyorsa aşağıdaki komutlarla test yapabiliriz:
chrootuid /chroot/mysql mysql /usr/local/mysql/libexec/mysqld &

Eğer herhangi bir hata oluşursa truss komutunu ya da ktrace/kdump,strace gibi alternatiflerini kullanmalıyız. Bu sorunların sebeplerinitespit ve elimine atmak için bize yardımcı olacaktır.
Not olarak, mysqld işlemini çalıştırmak için, Apache ya da PHPkullanımlarında chrootuid programı chroot yerine kullanılabilir. Anafarklılık ise, chrootuid'in, uygulanan işlemin sahibinideğiştirmesidir. Bizim örneğimizde, mysqld chroot edilmiş ortamdaçalışmaktadır, fakat işlemin sahibi root değildir, mysqlkullanıcısıdır. Chrootuid , bir çok sistemde default olarak gelmez vegerekliliğinden dolayı manual olarak yüklenmeli ve kurulmalıdır.

Sunucu Konfigürasyonu

Sonraki adım ise veritabanı sunucusunu, bizim güvenlik gerekliliklerimizi tamamlayacak şekilde konfigüre etmektir.
MySQL'in default kurulumu halinde, ana konfigürasyon dosyası/etc/my.cnf dır. Bizim durumumuzda, her ne kadar chroot edilmişortamda çalışan sunucu olsa da, biz 2 konfigürasyon dosyasıkullanacağız: /chroot/mysql/etc/my.cnf ve /etc/my.cnf. İlk dosya sadeceMySQL sunucu tarafından kullanılacaktır, sonraki ise MySQL araçlarıtarafından (mysqladmin, mysql, mysqldump vb.). Her iki durumda da bazıkonfigürasyon değişiklikleri gerekebilir.

Uzaktan Erişimin Kapatılması

İlk değişiklik, MySQL'in default olarak dinlemede olduğu 3306/TCPportunda uygulanır. Çünkü, ilk ayarlamalara göre veritabanı sadecelokal olarak kurulmuş PHP uygulaması tarafından kullanılacaktır,rahatlıkla bu port üzerinden dinlemeyi kapatabiliriz. Bu, diğerhostlardan direkt olarak TCP/IP protokolü üzerinden MySQL'e yapılacaksaldırı ihtimallerini kısıtlayacaktır. Lokal bağlantı ise mysql.socksoket üzerinden çalışmaya devam edecektir. Bahse konu port üzerindedinlemeyi kapatmak için, aşağıdaki parametrelerin/chroot/mysql/etc/my.cnf dizininin [mysqld] bölümüne eklenmesigerekmektedir:
skip-networking

Eğer bir sebeple veritabanına uzaktan erişim hala gerekiyorsa(örneğin veri yedeklemesi için), SSH protokolü aşağıda belirtildiğişekilde kullanılabilir:
backuphost$ ssh mysqlserver /usr/local/mysql/bin/mysqldump -A > backup

Lokal Güvenliğin Geliştirilmesi

Sonraki değişiklik ise LOAD DATA LOCAL INFILE komutunun kullanımakapatılmasıdır, ki bu da lokal dosyalar üzerindeki yetkisiz "'okuma"'hakkı elde edilmesini önlemek içindir. Bu PHP uygulamalarında yeni SQLenjeksiyon teknikleri keşfedildiği zamanlarda oldukça önem kazanır.
Bu amaçla, aşağıdaki parametrelerin /chroot/mysql/etc/my.cnf dizininin [mysqld] bölümüne eklenmesi gerekir:
set-variable=local-infile=0

İlaveten, veritabanı yönetim araçlarının kullanımı mümkün ise,/etc/my.cnf dizininin [client] bölümünde bulunan aşağıdaki parametrelerdeğiştirilmelidir:
socket = /chroot/mysql/tmp/mysql.sock

Artık her zaman bu araçları çalıştıracağımız zaman--socket=/chroot/mysql/tmp/mysql.sock komutu ile mysql, mysqladmin,mysqldump araçlarını desteklememiz gerekmiyor.

Yönetici Şifresinin Değiştirilmesi

MySQL'in güvenliğinde en önemli adımlardan biri de default olarakşifresiz olan veritabanı yöneticisinin şifresinin değiştirilmesidir.Bunu uygulayabilmek için MySQL'i çalıştırmamız gerekmektedir ( eğer oanda çalışmıyorsa):
chrootuid /chroot/mysql mysql /usr/local/mysql/libexec/mysqld &
and change the administrator's password as follows:
/usr/local/mysql/bin/mysql -u root
mysql> SET PASSWORD FOR root[at]localhost=PASSWORD('new_passwo rd');

Bu, komut satırından şifre değiştirilmemesi için, örneğin bir"mysqladmin password" kullanmadan, iyi bir uygulamadır. Bu özelliklediğer kullanıcılar sunucu üzerinde çalışıyorsa önemlidir. Uygunsuzerişim izinleri ayarlanmış olsa bile bu şekilde şifre, örneğin "ps aux"komutu kullanarak ya da history dosyalarına bakarak (~/.history,~/.bash_history etc) kolaylıkla ortaya çıkmayacaktır.

Default Kullanıcı/Veritabanlarının Kaldırılması

Sonraki adımda ise, örnek veritabanını (test) ve lokal root hesabı hariç diğer tüm hesapları kaldırmalıyız:
mysql> drop database test;
mysql> use mysql;
mysql> delete from db;
mysql> delete from user where not (host="localhost" and user="root");
mysql> flush privileges;

Bu, veritabanına anonim bağlantılar sağlanmasını ve/chroot/mysql/etc/my.cnf dizinindeki skip-networking parametresinebakmaksızın uzak bağlantıları önleyecektir.

Yönetici Hesap İsminin Değiştirilmesi

Ayrıca default yönetici hesabı isminin de ( root), farklı ve tahminedilmesi zor bir isim ile değiştirilmesi tavsiye edilmektedir.Bu tipbir değişiklik yönetici şifresine brute-force ve dictionary tabiredilen saldırıların yapılmasını oldukça zorlaştıracaktır. Bu durumdasaldırgan sadece şifreyi değil, birincil ve mecburi olarak yöneticihesabı ismini de tahmin etmek zorundadır.
mysql> update user set user="mydbadmin" where user="root";
mysql> flush privileges;

History Dosyasının Kaldırılması

En son olarak, uygulanmış tüm SQL komutlarının bulunduğu (özellikle basit text olarak tutulan şifreler) MySQL History(~/.mysql_history) dosyasının içeriğini de kaldırmamız gerekmektedir:
cat /dev/null > ~/.mysql_history

PHP ile MySQL Arasındaki Haberleşme

Bir diğer makalemizde ("Adım adım PHP Güvenliği"), programlardanbiri chroot edilmiş alanda çalıştırıldığında PHP ile MySQL arasındakihaberleşme sorunlarına dikkat çekmiştik.. Çünkü lokal olarak PHP,/tmp/mysql.sock soketi aracılığı ile MySQL ile haberleşmektedir,PHP'nin chroot edilmiş alanda olması demek, birbirleri ilehaberleşememeleri anlamına gelmektedir. Bu sorunu çözmek için, MySQL'içalıştırdığımız her zaman, PHP'nin chroot edilmiş alanına hard linkoluşturmamız gerekmektedir:
ln /chroot/mysql/tmp/mysql.sock /chroot/httpd/tmp/

Not edilmelidir ki, /chroot/mysql/tmp/mysql.sock soketi ve/chroot/httpd/tmp dizini fiziksel olarak aynı dosya sistemindebulunmalıdır. Aksi halde programların birbirleri ile haberleşmelerimümkün olmayacaktır -- hard linkler dosya sistemleri arasında çalışmaz.

Son Adımlar

Bu noktada spesifik PHP uygulaması tarafından kullanılacak olan tümveritabanlarını ve hesapları yaratmalıyız. Önemle vurgulamak gerekir kibu hesaplar, sadece PHP uygulaması tarafından kullanılan veritabanınagirmeye yetkili olmalıdır. Farklı olarak bu hesaplar mysql veritabanınaerişim iznine ya da herhangi bir sistem için yönetici yetkisine sahipolmamalıdır, (FILE, GRANT, ALTER, SHOW DATABASE, RELOAD, SHUTDOWN,PROCESS, SUPER vb.).
Son olarak, işletim sistemi çalıştığında MySQL'inde çalışması içinayrıca bir shell script'i yaratmalıyız. Örnek script aşağıdagösterilmektedir:

#!/bin/sh

CHROOT_MYSQL=/chroot/mysql
CHROOT_PHP=/chroot/httpd
SOCKET=/tmp/mysql.sock
MYSQLD=/usr/local/mysql/libexec/mysqld
PIDFILE=/usr/local/mysql/var/`hostname`.pid
CHROOTUID=/usr/local/sbin/chrootuid

echo -n "mysql"

case "$1" in
start)
rm -rf ${CHROOT_PHP}/${SOCKET}
nohup ${CHROOTUID} ${CHROOT_MYSQL} mysql ${MYSQLD} >/dev/null 2>&1
&
sleep 5 && ln ${CHROOT_MYSQL}/${SOCKET} ${CHROOT_PHP}/${SOCKET}
;;
stop)
kill `cat ${CHROOT_MYSQL}/${PIDFILE}`
rm -rf ${CHROOT_MYSQL}/${SOCKET}
;;
*)
echo ""
echo "Usage: `basename $0` {start|stop}" >&2
exit 64
;;
esac

exit 0
FreeBSD sistem kullanımı halinde, yukarıdaki script, mysql.sh ismi ile /usr/local/etc/rc.d dizini altında bulunmalıdır.

Anlatılan methodlarla %100 güvenliği olduğunuzu düşünmeyin.Bunlar kötü niyetli girişimleri engellmek amacıyla vurgulanan önemli noktalardan ibarettir.Teknolojinin hiçbir alanında %100 güvenlikten bahsetmek söz konusu değildir.Kolay gelsin.


Oguzz
oguz@thecoders.net
2 Haziran 2007 17:33

İlgili Olabilecek Makaleler


Yorumlar (0)




Ziyaretçi olarak yorum yazamazsınız. Üye olmak için tıklayın Üye iseniz giriş yapın.



MENÜ » FORUM
Menü » Takip et
RSS Facebook Twitter Friendfeed
Sık Kullanılanlar Google Yahoo Live
Menü » Paylaş
E-Posta ile gönder Twitter Facebook Friendfeed
Buzz Stumbleupon Delicious Digg