现在的位置: 首页 > 综合 > 正文

使oracle运行在selinux中的实践-附源代码

2018年05月19日 ⁄ 综合 ⁄ 共 12177字 ⁄ 字号 评论关闭

已经差不多1年半没有发文了,眼看着2012即将成为过去,看着荒草丛生的博客,心中想着还是发点什么东西,也许会帮到别人。同时,也聊以自慰自己还在技术圈混呢。

2011年初,在一次安装体验FC14的过程中注意到了其已经很完善的SELinux模块。记得在几年前第一次看到Linux发行版中的SELinux简直认为就是个鸡肋,什么都不能运行。但在FC14中大量的模块使我映像深刻,所有系统的默认服务:比如,httpd,ftpd,mysql等等都有了相应的安全策略模块,而且都可以在开启SELinux的情况下使用这些服务,注意,带来的好处是系统运行在SELinux 的enforcing的安全策略上下文中-即MAC(Mandatory Access Control),那就是说这里的web服务器将比任何一个不运行SELinux的web服务器安全的多,黑客的入侵基本上不可能。技术人员的天生的学习欲望驱使我开始学些并挖掘如何能最大化SELinux的优点,并为我所用。当时,正好碰到一个问题,我安装的Oracle服务器无法启动,当时忘记了系统默认是SELinux开启的。最后经过一番苦斗才无意中发现了/var/log/audit.log中尽然有大量被Denied请求,而且进程都是oracle的进程,才意识到是SELinux阻止了oracle进程运行。所以,作为一个学习SELinux练习和实践,开始练习如何自己创建SELinux模块,以使某一个服务能够运行于其安全上下文的实践。

过程不是很长,大概1个多星期的所有业余时间,最终完成了创建oracle SELinux模块。也对整个SELinux的架构有了深刻的了解。设计细节就不讲太多了,直接上结果和代码。也许有人需要(据我了解oracle他们给客户的解决方案仍然停留在:停止SELinux,运行Oracle 层面 :-))

这是ps的截屏:

可以看到oracle的进程运行在一个自定义的安全上下文unconfined_u:system_r:oradb_t:SystemLow 中。 oradb_t是进程运行的域(Domain)-我大致按照SELinux命名习惯起的名字。后面在相关代码将看到更多命名。

这是相关文件一览。

于2011-02-16上传最后一次修改,到2012年年底才发文,我太懒了:-(

模块源文件介绍:

oradb.fc  - SELinux模块的文件上下文(file context)定义,或安全上下文定义。我们将需要用restorecon或setfiles工具 重新label文件系统,使所有这里定义的文件具有我们所设计的安全上下文。

oradb.if  - SELinux接口定义。我还没有想到代码重用的必要,所以并没有设计可重用的接口,所以这个文件是空的,只有一行注释。我也不贴内容了。

oradb.te  - 这就是SELinux安全策略源文件。所有的访问,运行,以及域转换的策略都定义于此。

oradb.pp -  这不是源文件,只是上面的3个源文件编译后生成的目标代码。使用semodule工具进行安装。

源文件oradb.fc

# dbora executable will have:
# label: system_u:object_r:oradb_exec_t
# MLS sensitivity: s0
# MCS categories: <none>

#
# ORACLE_HOME
#
/usr/share/oracle/product/11.2.0/dbhome_1(/.*)?         gen_context(system_u:object_r:oradb_dbhome_content_t,s0)
/usr/share/oracle/product/11.2.0/dbhome_1/.*\.log  --      gen_context(system_u:object_r:oradb_log_t,s0)
/usr/share/oracle/product/11.2.0/dbhome_1(/.*)?/bin/.*      gen_context(system_u:object_r:oradb_exec_t,s0)
/usr/share/oracle/product/11.2.0/dbhome_1/lib(/.*)?		gen_context(system_u:object_r:lib_t,s0)
#
# /usr/share/oracle/diag
#
/usr/share/oracle/diag(/.*)?            gen_context(system_u:object_r:oradb_diag_content_t,s0)

#
# /usr/share/oracle/admin
#
/usr/share/oracle/admin(/.*)?            gen_context(system_u:object_r:oradb_admin_content_t,s0)

#
# /usr/share/oracle/flash_recovery_area
#
/usr/share/oracle/flash_recovery_area(/.*)?            gen_context(system_u:object_r:oradb_flash_recovery_area_t,s0)

#
# /usr/share/oracle/cfgtoollogs
#
/usr/share/oracle/cfgtoollogs(/.*)?            gen_context(system_u:object_r:oradb_cfgtoollogs_t,s0)
/usr/share/oracle/cfgtoollogs(/.*)?\.log  --      gen_context(system_u:object_r:oradb_log_t,s0)

#
# /usr/share/oraInventory
#
/usr/share/oraInventory(/.*)?           gen_context(system_u:object_r:oraInventory_home_t,s0)


#
# /etc
#
/etc/rc\.d/init\.d/dbora	--	gen_context(system_u:object_r:oradb_initrc_exec_t,s0)
/etc/oratab			--	gen_context(system_u:object_r:oradb_etc_t,s0)

#
# /var
#
/var/lock/subsys/dbora	--	gen_context(system_u:object_r:oradb_var_lock_t,s0)
/var/spool/cron/oracle  --  gen_context(system_u:object_r:user_cron_spool_t,s0)

#
# /repo
#
/repo/oradata(/.*)?	gen_context(system_u:object_r:oradb_db_t,s0)


注意:我把oracle安装到/usr/share/oracle目录中的,数据文件(表空间)放在/repo/oradata,生产环境这样做不好。如果你要用这代码,自己修改吧。

源文件oradb.te

policy_module(oradb,1.0.0)

########################################
#
# Declarations
#

type oradb_t;
type oradb_exec_t;
type oradb_dbhome_content_t;
type oradb_diag_content_t;
type oradb_admin_content_t;
type oradb_flash_recovery_area_t;
type oraInventory_home_t;
type oradb_cfgtoollogs_t;

allow oradb_t oradb_dbhome_content_t:dir { rw_dir_perms setattr };
allow oradb_t oradb_dbhome_content_t:file { manage_file_perms exec_file_perms };
allow initrc_t oradb_dbhome_content_t:dir search;
allow oradb_t oradb_diag_content_t:dir { rw_dir_perms setattr };
allow oradb_t oradb_diag_content_t:file manage_file_perms;
allow oradb_t oradb_admin_content_t:dir rw_dir_perms;
allow oradb_t oradb_admin_content_t:file manage_file_perms;
allow oradb_t oradb_flash_recovery_area_t:dir rw_dir_perms;
allow oradb_t oradb_flash_recovery_area_t:file manage_file_perms;
allow oradb_t oraInventory_home_t:dir { rw_dir_perms setattr };
allow oradb_t oraInventory_home_t:file manage_file_perms;
allow oradb_t oradb_cfgtoollogs_t:dir { rw_dir_perms setattr };
allow oradb_t oradb_cfgtoollogs_t:file manage_file_perms;

allow oradb_t tmpfs_t:dir rw_dir_perms;
allow oradb_t tmpfs_t:file { manage_file_perms exec_file_perms };
allow oradb_t tmpfs_t:filesystem getattr;
gen_require(`
        type sysfs_t;
')
allow oradb_t sysfs_t:file { read open getattr };
allow oradb_t sysfs_t:dir { search read open };
allow oradb_t sysfs_t:filesystem { getattr };
allow oradb_t sysfs_t:lnk_file read;

# for read font
gen_require(`
        type fonts_t;
')
gen_require(`
        type fonts_cache_t;
')
allow oradb_t fonts_t:dir { search read open getattr };
allow oradb_t fonts_t:file { read open getattr };
allow oradb_t usr_t:file { read open getattr };
allow oradb_t fonts_cache_t:dir { search };
allow oradb_t fonts_cache_t:file { read open getattr };



# allow /dev/urandom & /dev/random
gen_require(`
        type urandom_device_t;
')
gen_require(`
        type random_device_t;
')
allow oradb_t urandom_device_t:chr_file { getattr read open ioctl };
allow oradb_t random_device_t:chr_file { getattr read open ioctl };

gen_require(`
        type ping_exec_t;
')
gen_require(`
        type ifconfig_exec_t;
')
allow oradb_t ping_exec_t:file { execute read open execute_no_trans };
allow oradb_t ifconfig_exec_t:file { getattr execute read open execute_no_trans };
# for sysctl
gen_require(`
        type binfmt_misc_fs_t;
')
allow oradb_t binfmt_misc_fs_t:dir { getattr read open search };
allow oradb_t binfmt_misc_fs_t:file { getattr read open };

fstools_domtrans(oradb_t)
allow fsadm_t oradb_dbhome_content_t:dir { search getattr };
fstools_getattr_swap_files(oradb_t)

gen_require(`
        type fixed_disk_device_t;
')
allow oradb_t fixed_disk_device_t:blk_file read_blk_file_perms;
#for mount
mount_domtrans(oradb_t)
#for lvm
gen_require(`
        type lvm_exec_t;
')
allow oradb_t lvm_exec_t:file getattr;
storage_getattr_removable_dev(oradb_t)

gen_require(`
        type setroubleshootd_t;
')
allow setroubleshootd_t oradb_dbhome_content_t:dir list_dir_perms;
allow setroubleshootd_t oradb_diag_content_t:dir list_dir_perms;

# can make crond_t (unconfined_t) transit into oradb_t
gen_require(`
        type unconfined_t;
')
gen_require(`
        type crond_t;
')
# for cron
# crond will executing in crond_t domain, it will fork several times,
# so the cronjob will executing in grandchild process of crond, 
# and cronjob will executing in domain of cron user's default security context.
# normally, it is unconfined_u:unconfined_r:unconfined_t:s0. with MLS_LEVEL set
# to level. so we need transit from unconfined_t -> oradb_t. and oradb_t domain
# need send sigchld to grandparent crond_t.
domain_auto_trans(unconfined_t,oradb_exec_t,oradb_t)
allow unconfined_t oradb_dbhome_content_t:dir list_dir_perms;
allow unconfined_t oradb_dbhome_content_t:file manage_file_perms;
# this is for allow a combin of unconfined_r:oradb_t
role unconfined_r types oradb_t;
allow oradb_t crond_t:process sigchld;

fs_associate(oradb_diag_content_t)
fs_associate(oradb_dbhome_content_t)
fs_associate(oradb_admin_content_t)

# /home/oracle search getattr, /home search
userdom_getattr_user_home_dirs(oradb_t)
userdom_search_user_home_dirs(oradb_t)

allow oradb_t user_tmp_t:dir { setattr write remove_name add_name };
userdom_manage_user_tmp_sockets(oradb_t)

corenet_tcp_bind_generic_node(oradb_t)
corenet_tcp_bind_generic_port(oradb_t)
corenet_tcp_connect_xserver_port(oradb_t)
corenet_tcp_connect_snmp_port(oradb_t)


# create a domain type that can be entered from initrc_t domain
init_daemon_domain(oradb_t, oradb_exec_t)
role system_r types oradb_t;

# create file type oradb_initrc_exec_t that can transit into initrc_t domain
type oradb_initrc_exec_t;
init_script_file(oradb_initrc_exec_t)

#create file type oradb_etc_t as configfile
type oradb_etc_t;
files_config_file(oradb_etc_t)

type oradb_db_t;
files_type(oradb_db_t)

type oradb_var_lock_t;
files_lock_file(oradb_var_lock_t)

#create oradb_log_t as a logfile.
type oradb_log_t;
logging_log_file(oradb_log_t)
#allow rw in /var/log and create oradb_log_t
logging_log_filetrans(oradb_t, oradb_log_t, file)
# complete manage on file oradb_log_t
manage_files_pattern(oradb_t, oradb_log_t, oradb_log_t)
logging_send_syslog_msg(oradb_t)
logging_send_audit_msgs(oradb_t)

allow oradb_t oradb_var_lock_t:file manage_file_perms;
files_lock_filetrans(initrc_t, oradb_var_lock_t, file)
# complete permssion to ora db file and dirs
manage_dirs_pattern(oradb_t, oradb_db_t, oradb_db_t)
manage_files_pattern(oradb_t, oradb_db_t, oradb_db_t)
manage_lnk_files_pattern(oradb_t, oradb_db_t, oradb_db_t)
manage_fifo_files_pattern(oradb_t, oradb_db_t, oradb_db_t)
manage_sock_files_pattern(oradb_t, oradb_db_t, oradb_db_t)

# allow to read locale_t
miscfiles_read_localization(oradb_t)
# allow /proc/meminfo
kernel_read_system_state(oradb_t)
# allow read /etc/resolv.conf, perform DNS name resolv. a lot of staff here.
sysnet_dns_name_resolve(oradb_t)
# exec hostname in oradb_t domain, without transition.
hostname_exec(oradb_t)

files_read_etc_files(oradb_t)
allow oradb_t self:capability { kill dac_override dac_read_search chown fowner fsetid setuid setgid sys_nice sys_tty_config sys_admin sys_rawio };
allow oradb_t self:process { signal_perms execmem execstack setsched setpgid };
allow oradb_t self:fifo_file rw_fifo_file_perms;
allow oradb_t self:file { getattr read };
allow oradb_t self:sem create_sem_perms;
allow oradb_t self:shm create_shm_perms;
allow oradb_t self:tcp_socket create_stream_socket_perms;
allow oradb_t self:udp_socket create_stream_socket_perms;
allow oradb_t self:unix_dgram_socket create_socket_perms;
allow oradb_t self:unix_stream_socket { create_stream_socket_perms connectto };
allow oradb_t self:netlink_selinux_socket create_socket_perms;
allow oradb_t self:rawip_socket { create setopt getopt read write };
allow oradb_t self:capability net_raw;
#for node_bind request
corenet_udp_bind_generic_node(oradb_t)
# for netlink_route_socket
allow oradb_t self:netlink_route_socket r_netlink_socket_perms;
# allow port:tcp_socket name_connect
corenet_tcp_connect_generic_port(oradb_t)
# can exec grep,cut
corecmd_exec_bin(oradb_t)
# can exec shell
corecmd_exec_shell(oradb_t)
# can exec so
libs_legacy_use_shared_libs(oradb_t)
# can read /proc/1
init_read_state(oradb_t)

# for lspci
gen_require(`
        type hwdata_t;
')
gen_require(`
        type modules_object_t;
')
gen_require(`
        type modules_dep_t;
')
allow oradb_t hwdata_t:dir search;
allow oradb_t hwdata_t:file { open read getattr };
allow oradb_t modules_object_t:dir search;
allow oradb_t modules_object_t:file { open read getattr };
allow oradb_t modules_dep_t:file { open read getattr };

# for uptime
gen_require(`
        type initrc_var_run_t;
')
gen_require(`
        type rpc_pipefs_t;
')
allow oradb_t initrc_var_run_t:file { open read lock };
# for df
gen_require(`
        type samba_share_t;
')
gen_require(`
        type var_lib_nfs_t;
')
allow oradb_t { devpts_t binfmt_misc_fs_t rpc_pipefs_t }:filesystem getattr;
allow oradb_t { samba_share_t var_lib_nfs_t }:dir { getattr search };
# for sh
gen_require(`
        type dmesg_exec_t;
')
allow oradb_t dmesg_exec_t:file { execute read open execute_no_trans getattr };
# for rpm, I don't want role transition
domain_system_change_exemption(oradb_t)
rpm_domtrans(oradb_t)
allow rpm_t oradb_dbhome_content_t:dir { search getattr };

gen_require(`
        type sysstat_log_t;
')
allow oradb_t sysstat_log_t:file read;

# read all sysctl_type, for ex: sysctl_net_t, sysctl_t, proc_net_t,sysctl_fs_t etc.
kernel_read_all_sysctls(oradb_t)
allow oradb_t proc_net_t:file read_file_perms;

# allow to access /tmp dir and file
allow oradb_t tmp_t:dir manage_dir_perms;
allow oradb_t tmp_t:file manage_file_perms;
# allow fs_t:filesystem / getattr
fs_getattr_xattr_fs(oradb_t)

#  execute_no_trans
can_exec(oradb_t,oradb_exec_t)
allow oradb_t oradb_exec_t:lnk_file { getattr read };

# make a fake decl to use in here for sysctl_kernel_t which have been declared in kernel.te, actuall sysctl_kernel_t is a sysctl_type :-) 
gen_require(`
        type sysctl_kernel_t;
')
allow oradb_t sysctl_kernel_t:dir search;
allow oradb_t sysctl_kernel_t:file read;

gen_require(`
        type kernel_t;
')
allow oradb_t kernel_t:dir { search read getattr };
allow oradb_t kernel_t:file { read open };
allow oradb_t kernel_t:system { syslog_read ipc_info };


# prevent ps command from flushing audit.log, no priviledge to do this on most of pid.
# do not use *! only neverallow suport * and ~
#dontaudit oradb_t *:{ dir file } { getattr search read open };
domain_dontaudit_read_all_domains_state(oradb_t)
allow oradb_t self:capability sys_ptrace;

# for dbca/emca
gen_require(`
	type xauth_home_t;
')
allow oradb_t xauth_home_t:file { getattr read open };
allow oradb_t oradb_dbhome_content_t:dir create;
allow oradb_cfgtoollogs_t fs_t:filesystem associate;

我都写有注释的,想用的人看看还是有帮助的。

不要怪我没说,研究selinux可能会耗尽你的生命 微笑,珍惜生命者莫入。如果你想build自己的CIA级别安全系统,那么你可能需要这样做。

该模块还是比较简单的,仍然是基于enforcing policy的MAC实现。可以简单方便的应用于RH或FC血统的Linux发行。没试过其他。也许可以也许需要结构的修改。

对于更高级别的安全实现,比如MLS/MCS/RBACS - 多级安全-多敏感度安全/多范畴安全/基于角色的访问控制安全,那SELinux需要进行重新配置,以支持MLS/MCS/RBACS 策略,这个模块的安全上下文和policy需要重新设计。这已经超出我目前的知识范畴,需要更多学习,需要更多的生命去完成微笑,目前不打算这样浪费我的青春了-虽然已经青春不再。

现在SELinux在中国的应用还非常少,在国外也是如此,有同事告诉我CIA在用类似的系统。我估计看过美剧《24小时》的人都注意到CTU总部里面的安全系统,随时可以提高级别或者降低级别,以致于有些人一下就不可以访问了,一下又可以了。其实它就是一个MLS/MCS/RBACS的安全系统例子。

SELinux固然可以大大提高系统的安全性,可以说几乎不可攻破(我坚信世上没有绝对,所以不能说绝对不能)。但代价是它会使系统管理员的维护/诊断工作量大量增加。所以,在一个要求安全性非常高的系统中。也许值得这样做。

抱歉!评论已关闭.