This is just a short how-to, more information about chrooting MySQL can be obtained in these 2 threads:
mysqld doesn't chroot securely
chrooting mysql
Following the
MySQL documentation mysqld can be run chrooted using the --chroot command line option. Chrooting however is not really done. In a chrooted area things outside of the area can't be accessed. Just place your databases-directory outside of the area and give it a try ... it WILL work, ergo chrooting is not completely done! So we don't rely on the program chrooting capabilities and use the "standard" method.
I've used the
Binary Linux package (Intel libc6 systems) for this time. Steps to install the binary package chrooted:[list=1][*]add mysql user + group[*]create jail directories[*]set up chroot jail[*]install mysql binary package (to /server/mysql)[*]install mysql and test database[*]create /server/mysql/etc/my.cnf (mysql configuration)[*]adjust permissions[/list=1]
Script that does this for us:
Code:
#!/usr/bin/perl
# install MySQL chrooted
# base is the binary distribution of MySQL
system("chattr -i /etc/group /etc/gshadow /etc/passwd /etc/shadow");
system("groupadd mysql ; useradd -g mysql mysql -m -k /server/mysql -s /bin/false -d /server/mysql");
system("chattr +i /etc/group /etc/gshadow /etc/passwd /etc/shadow");
system("mkdir -p /server/mysql/dev /server/mysql/etc /server/mysql/tmp");
system("cp my.cnf /server/mysql/etc ; chown mysql:mysql /server/mysql/etc/my.cnf ; chmod 440 /server/mysql/etc/my.cnf");
system("cp mysql-*-pc-linux-gnu-i686.tar.gz /server");
chdir("/server");
system("tar xvfz mysql-*-pc-linux-*.tar.gz ; rm mysql-*-pc-linux-*.tar.gz");
system("mv mysql-*-pc-linux-* mysql/binary");
chdir("/server/mysql/binary");
open(FHANDLE, "/server/mysql/binary/bin/mysqlaccess");
@mysqlaccess = <FHANDLE>;
close(FHANDLE);
for ($i = 0; $i < scalar(@mysqlaccess); $i++) {
if (@mysqlaccess[$i] =~ /\$MYSQL/) {
@mysqlaccess[$i] = "\t\$MYSQL = '/server/mysql/binary/bin/mysql'\n";
last;}
}
open(FHANDLE, "/server/mysql/binary/bin/mysqlaccess");
print FHANDLE @mysqlaccess;
close(FHANDLE);
system("mv /server/mysql/etc/my.cnf /server/mysql/etc/config.cnf");
system("./scripts/mysql_install_db");
system("mv /server/mysql/etc/config.cnf /server/mysql/etc/my.cnf");
system("mv data ../databases");
system("chown -R root /server/mysql/binary");
system("chown -R mysql /server/mysql/databases");
system("chgrp -R mysql /server/mysql/binary /server/mysql/databases");
system("chmod 777 /server/mysql/tmp ; chattr +t /server/mysql/tmp");
system("ln -s /server/mysql/tmp/mysql.sock /tmp/mysql.sock");
system("less /etc/passwd | grep mysql > /server/mysql/etc/passwd");
system("chmod 0444 /server/mysql/etc/passwd");
system("strip /server/mysql/binary/bin/* &> /dev/null");
system("chattr +i -R /server/mysql/etc");
system("mknod /server/mysql/dev/null c 1 3 ; chattr +i -R /server/mysql/dev");
Quote:
# my.cnf
# ----------------------------------------------------------------------
# MySQL client configuration (options will be passed to MySQL clients)
# ----------------------------------------------------------------------
[client]
port = 3306
socket = /tmp/mysql.sock
# ----------------------------------------------------------------------
# ----------------------------------------------------------------------
# MySQL server configuration
# ----------------------------------------------------------------------
[mysqld]
basedir = /binary
datadir = /databases
port = 3306
socket = /tmp/mysql.sock
tmpdir = /tmp/
local-infile = 0
safe-show-database
safe-user-create
server-id = 0
skip-innodb
skip-locking
skip-show-database
set-variable = interactive_timeout=3600
set-variable = key_buffer=256M
set-variable = max_allowed_packet=1M
set-variable = max_connections=1000
set-variable = myisam_sort_buffer_size=64M
set-variable = record_buffer=1M
set-variable = sort_buffer=1M
set-variable = table_cache=256
set-variable = thread_cache=8
set-variable = wait_timeout=3600
# ----------------------------------------------------------------------
[mysqldump]
quick
set-variable = max_allowed_packet=16M
[mysql]
no-auto-rehash
[isamchk]
set-variable = key_buffer=128M
set-variable = read_buffer=2M
set-variable = sort_buffer=128M
set-variable = write_buffer=2M
[myisamchk]
set-variable = key_buffer=128M
set-variable = read_buffer=2M
set-variable = sort_buffer=128M
set-variable = write_buffer=2M
[mysqlhotcopy]
interactive-timeout
|
You might want to do a
ln -s /server/mysql/etc/my.cnf /etc/my.cnf and adjust the manpath configuration (/etc/man.config) and add the path for the mysql client programs (/server/mysql/binary/bin) to your $PATH variable ... for instance using /root/.bash_profile but this shouldn't be too much of a problem!
To startup the chrooted area you need to do chroot /server/mysql /binary/bin/mysqld --user=mysql & so you can write this in a startup script... or you can modify the safe_mysqld script a bit to run mysqld chrooted from there ...
More information regarding chrooting can be found at
You might also want to look at the
grsecurity-kernel-patch!