AppArmor零知识学习十四、实操与实践(2)

本文内容参考:

Linux安全模块AppArmor总结-CSDN博客

apparmor首页、文档和下载 - 应用程序访问控制系统 - OSCHINA - 中文开源技术交流社区

AppArmor · GitBook

AppArmor配置(二)_domybest_nsg的博客-CSDN博客

接前一篇文章:AppArmor零知识学习十三、实操与实践(1)

上一篇文章使能了AppArmor,但是目前系统中还没有具有配置文件的应用程序,本文就来添加访问控制规则以使系统中存在具有配置文件的应用程序。

二、添加访问控制规则

1. 编写测试例程

先编写一个测试例程,代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>


int main(int argc, char *argv[])
{
        FILE *f;
        int i = 0;
        char ch;

        if(3 == argc)
        {
                f = fopen(argv[1], "w");
                if(!f)
                {
                        fprintf(stderr, "fopen failed with w, error: %s\n", strerror(errno));
                        return 2;
                }
                while(i < strlen(argv[2]))
                {
                        fputc(argv[2][i], f);
                        i++;
                }
                fclose(f);
        }
        else if(argc == 2)
        {
                f = fopen(argv[1], "r");
                if(!f)
                {
                        fprintf(stderr, "fopen failed with r, error: %s\n", strerror(errno));
                        return 2;
                }
                while((ch=fgetc(f)) != EOF)
                        printf(" %c", ch);
                fclose(f);
        }
        else
        {
                printf("Usage:\n");
                printf("\ttest_app file \"string\"\n");
                printf("\ttest_app file\n");
                return 3;
        }

        return 0;
}

对测试例程进行编译和简单测试。如下所示:

$ gcc test_app.c -o test_app
$ ls
test_app  test_app.c
$ ./test_app kkk
fopen failed with r, error: No such file or directory

$ ./test_app kkk 1234
$ ./test_app kkk
 1 2 3 4

2. 创建规则

利用genprof创建规则。步骤如下:

(1)进入到创建测试例程的目录

penghao@Ding-Perlis-MP260S48:~/AppArmor$ cd sample_code/
penghao@Ding-Perlis-MP260S48:~/AppArmor/sample_code$ ls
kkk  test_app  test_app.c

penghao@Ding-Perlis-MP260S48:~/AppArmor/sample_code$ rm kkk
penghao@Ding-Perlis-MP260S48:~/AppArmor/sample_code$ ls
test_app  test_app.c

(2)创建规则

$ aa-genprof test_app
正在在 /etc/apparmor.d 中更新 AppArmor 配置文件。Writing updated profile for /home/penghao/AppArmor/sample_code/test_app.

ERROR: [Errno 13] Permission denied: '/etc/apparmor.d/tmpdy6clx3q~'

前边加上sudo,再次执行以上命令:

$ sudo aa-genprof test_app
[sudo] penghao 的密码:正在在 /etc/apparmor.d 中更新 AppArmor 配置文件。Writing updated profile for /home/penghao/AppArmor/sample_code/test_app.
正在将 /home/penghao/AppArmor/sample_code/test_app 设置为投诉模式。
在开始之前,您可能希望检查您希望限制的应用程序的配置文件是否已经存在。有关详细信息,请参考以下维基页面:https://gitlab.com/apparmor/apparmor/wikis/Profiles

分析中: /home/penghao/AppArmor/sample_code/test_app

请启动要在另一个窗口中分析的应用程序,并立即执行其功能。
完成后,选择下面的“扫描”选项,以扫描系统日志中的AppArmor事件。
对于每个 AppArmor 事件,您将有机会选择是应允许还是拒绝访问。
[扫描系统日志以查找 AppArmor 事件(S)] / 完成(F)

按'F'键(无需回车)完成过程,如下所示:

[扫描系统日志以查找 AppArmor 事件(S)] / 完成(F)
正在设置 /home/penghao/AppArmor/sample_code/test_app 到强制模式
重启 AppArmor 到强制模式
请考虑贡献您的新配置文件!参阅以下 wiki 页面获取更多信息:https://gitlab.com/apparmor/apparmor/wikis/Profiles

已完成为 /home/penghao/AppArmor/sample_code/test_app 生成配置文件。

查看/etc/apparmor.d/下的内容:

对比之前的内容:

可以看到,最大的变化是在/etc/apparmor.d/下多了一个home.penghao.AppArmor.sample_code.test_app文件,文件名就是该文件的绝对路径,只是由'/'变为了'.'。文件内容如下:

# Last Modified: Wed Apr 19 10:23:02 2023
abi <abi/3.0>,

include <tunables/global>

/home/penghao/AppArmor/sample_code/test_app {
  include <abstractions/base>

  /home/penghao/AppArmor/sample_code/test_app mr,

}

此时再使用上一篇文章中提到的aa-status命令查看当前AppArmor的运行状态和具有配置文件的应用程序。命令及结果如下所示:

$ sudo aa-status 
apparmor module is loaded.
1 profiles are loaded.
1 profiles are in enforce mode.
   /home/penghao/AppArmor/sample_code/test_app
0 profiles are in complain mode.
0 profiles are in kill mode.
0 profiles are in unconfined mode.
0 processes have profiles defined.
0 processes are in enforce mode.
0 processes are in complain mode.
0 processes are unconfined but have a profile defined.
0 processes are in mixed mode.
0 processes are in kill mode.

对比之前没有设置规则时的结果:

$ sudo apparmor_status 
apparmor module is loaded.

(3)修改规则

修改/etc/apparmor.d/home.penghao.AppArmor.sample_code.test_app文件,在文件大括号内加入以下内容:

/home/penghao/AppArmor/sample_code/abcde rwm,
/home/penghao/AppArmor/sample_code/abcd  w,
/home/penghao/AppArmor/sample_code/abc r,

前一部分为文件名,后一部分为权限。

修改后的文件内容如下:

# Last Modified: Wed Apr 19 10:23:02 2023
abi <abi/3.0>,

include <tunables/global>

/home/penghao/AppArmor/sample_code/test_app {
  include <abstractions/base>

  /home/penghao/AppArmor/sample_code/test_app mr,
  /home/penghao/AppArmor/sample_code/abcde rwm,
  /home/penghao/AppArmor/sample_code/abcd w,
  /home/penghao/AppArmor/sample_code/abc r,

}

(4)重新装载

执行以下命令重新装载:

sudo /etc/init.d/apparmor reload

实际命令及结果如下:

$ sudo /etc/init.d/apparmor reload
sudo: /etc/init.d/apparmor:找不到命令

实际上,/etc/init.d/apparmor文件在Ubuntu下才有,由于笔者电脑的系统并非Ubuntu,因此并不存在这个文件。将Ubuntu下的/etc/init.d/apparmor文件拷贝过来,该文件内容如下:

#!/bin/sh
# ----------------------------------------------------------------------
#    Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
#     NOVELL (All rights reserved)
#    Copyright (c) 2008, 2009 Canonical, Ltd.
#
#    This program is free software; you can redistribute it and/or
#    modify it under the terms of version 2 of the GNU General Public
#    License published by the Free Software Foundation.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, contact Novell, Inc.
# ----------------------------------------------------------------------
# Authors:
#  Steve Beattie <[email protected]>
#  Kees Cook <[email protected]>
#
# /etc/init.d/apparmor
#
# Note: "Required-Start: $local_fs" implies that the cache may not be available
# yet when /var is on a remote filesystem. The worst consequence this should
# have is slowing down the boot.
#
### BEGIN INIT INFO
# Provides: apparmor
# Required-Start: $local_fs
# Required-Stop: umountfs
# Default-Start: S
# Default-Stop:
# Short-Description: AppArmor initialization
# Description: AppArmor init script. This script loads all AppArmor profiles.
### END INIT INFO

APPARMOR_FUNCTIONS=/lib/apparmor/rc.apparmor.functions

# Functions needed by rc.apparmor.functions

. /lib/lsb/init-functions

aa_action() {
	STRING=$1
	shift
	$*
	rc=$?
	if [ $rc -eq 0 ] ; then
		aa_log_success_msg $"$STRING "
	else
		aa_log_failure_msg $"$STRING "
	fi
	return $rc
}

aa_log_action_start() {
	log_action_begin_msg $@
}

aa_log_action_end() {
	log_action_end_msg $@
}

aa_log_success_msg() {
	log_success_msg $@
}

aa_log_warning_msg() {
	log_warning_msg $@
}

aa_log_failure_msg() {
	log_failure_msg $@
}

aa_log_skipped_msg() {
	if [ -n "$1" ]; then
		log_warning_msg "${1}: Skipped."
	fi
}

aa_log_daemon_msg() {
	log_daemon_msg $@
}

aa_log_end_msg() {
	log_end_msg $@
}

# Source AppArmor function library
if [ -f "${APPARMOR_FUNCTIONS}" ]; then
	. ${APPARMOR_FUNCTIONS}
else
	aa_log_failure_msg "Unable to find AppArmor initscript functions"
	exit 1
fi

usage() {
    echo "Usage: $0 {start|stop|restart|reload|force-reload|status}"
}

test -x ${PARSER} || exit 0 # by debian policy
# LSM is built-in, so it is either there or not enabled for this boot
test -d /sys/module/apparmor || exit 0

# do not perform start/stop/reload actions when running from liveCD
test -d /rofs/etc/apparmor.d && exit 0

rc=255
case "$1" in
	start)
		if [ -x /usr/bin/systemd-detect-virt ] && \
		   systemd-detect-virt --quiet --container && \
		   ! is_container_with_internal_policy; then
			aa_log_daemon_msg "Not starting AppArmor in container"
			aa_log_end_msg 0
			exit 0
		fi
		apparmor_start
		rc=$?
		;;
	restart|reload|force-reload)
		if [ -x /usr/bin/systemd-detect-virt ] && \
		   systemd-detect-virt --quiet --container && \
		   ! is_container_with_internal_policy; then
			aa_log_daemon_msg "Not starting AppArmor in container"
			aa_log_end_msg 0
			exit 0
		fi
		apparmor_restart
		rc=$?
		;;
	stop)
		aa_log_daemon_msg "Leaving AppArmor profiles loaded"
		cat >&2 <<EOM
No profiles have been unloaded.

Unloading profiles will leave already running processes permanently
unconfined, which can lead to unexpected situations.

To set a process to complain mode, use the command line tool
'aa-complain'. To really tear down all profiles, run 'aa-teardown'."
EOM
		;;
	status)
		apparmor_status
		rc=$?
		;;
	*)
		usage
		rc=1
		;;
	esac
exit $rc

再次执行重新装载命令,结果如下:

$ sudo /etc/init.d/apparmor reload
sudo: /etc/init.d/apparmor:找不到命令

需要添加可执行权限,命令及结果如下:

$ ls /etc/init.d/ -l
总计 12
-rw-rw-r-- 1 root root 3740  4月19日 14:36 apparmor
-rwxr-xr-x 1 root root 1893  2月15日 03:03 fuse
-rw-r--r-- 1 root root 1151  2月15日 00:36 README

$ sudo chmod 755 /etc/init.d/apparmor 
$ 
$ ls /etc/init.d/ -l
总计 12
-rwxr-xr-x 1 root root 3740  4月19日 14:36 apparmor
-rwxr-xr-x 1 root root 1893  2月15日 03:03 fuse
-rw-r--r-- 1 root root 1151  2月15日 00:36 README

再次执行,结果如下:

$ sudo /etc/init.d/apparmor reload
/etc/init.d/apparmor:行43: /lib/lsb/init-functions: 没有那个文件或目录

Ubuntu下会有/lib/lsb/init-functions文件,笔者系统中没有。不“折腾”了,直接重启,重启之后看看能否生效。

3. 测试

进入例程所在目录,依次执行以下命令:

$ pwd
/home/penghao/AppArmor/sample_code
penghao@Ding-Perlis-MP260S48:~/AppArmor/sample_code$ ls
apparmor  test_app  test_app.c
penghao@Ding-Perlis-MP260S48:~/AppArmor/sample_code$ ./test_app abc 1abc
penghao@Ding-Perlis-MP260S48:~/AppArmor/sample_code$ ./test_app abcd 2abcd
penghao@Ding-Perlis-MP260S48:~/AppArmor/sample_code$ ./test_app abcde 3abcde
penghao@Ding-Perlis-MP260S48:~/AppArmor/sample_code$ ls
abc  abcd  abcde  apparmor  test_app  test_app.c

可以看到,3个文件都可以正常生成,依次查看3个文件的内容:

penghao@Ding-Perlis-MP260S48:~/AppArmor/sample_code$ cat abc
1abc
penghao@Ding-Perlis-MP260S48:~/AppArmor/sample_code$ cat abcd
2abcd
penghao@Ding-Perlis-MP260S48:~/AppArmor/sample_code$ cat abcde
3abcde

文件内容也有。那么就有问题了,上边的规则:

 /home/penghao/AppArmor/sample_code/abcde rwm,
  /home/penghao/AppArmor/sample_code/abcd w,
  /home/penghao/AppArmor/sample_code/abc r,

要求abc只能被读取,而abcd只能被写入。怎么没起作用?查看系统日志/var/log/syslog,理论上应该能看到类似于如下信息:

kernel: [140321.028000] audit(1191433716.584:1578):  type=1502 operation=”inode_create” requested_mask=”w” denied_mask=”w” name=”/home/n1/Desktop/abc” pid=4864 profile=”/home/n1/Desktop/testapp”
kernel: [140362.236000] audit(1191433758.086:1579):  type=1502 operation=”inode_permission” requested_mask=”r” denied_mask=”r” name=”/home/n1/Desktop/abcd” pid=4877 profile=”/home/n1/Desktop/testapp”

表明虽然操作被允许了,但abc文件在写入时被“记账”了,abcd 文件在读取时被“记账”了。因为在 /etc/apparmor.d/home.penghao.AppArmor.sample_code.test_app他们没有对应的权限。但很遗憾,笔者的/var/log/syslog下并没有看到类似的信息,可能是AppArmor日志方面的配置还有些问题。

先不管这个问题,看一下当设置为enforce即强制模式时的情况。

执行以下命令进入强制模式:

$ sudo aa-enforce /etc/apparmor.d/home.penghao.AppArmor.sample_code.test_app 
正在设置 /etc/apparmor.d/home.penghao.AppArmor.sample_code.test_app 到强制模式

此时再次依次执行以上3条命令(先删除之前生成的abc、abcd、abcde文件),结果如下:

penghao@Ding-Perlis-MP260S48:~/AppArmor/sample_code$ rm abc
penghao@Ding-Perlis-MP260S48:~/AppArmor/sample_code$ rm abcd
penghao@Ding-Perlis-MP260S48:~/AppArmor/sample_code$ rm abcde

penghao@Ding-Perlis-MP260S48:~/AppArmor/sample_code$ ./test_app abc 1abc
fopen failed with w, error: Permission denied

penghao@Ding-Perlis-MP260S48:~/AppArmor/sample_code$ cat abc
cat: abc: 没有那个文件或目录

penghao@Ding-Perlis-MP260S48:~/AppArmor/sample_code$ echo "1abc" > abc
penghao@Ding-Perlis-MP260S48:~/AppArmor/sample_code$ ls abc
abc

penghao@Ding-Perlis-MP260S48:~/AppArmor/sample_code$ cat abc
1abc

可见,test_app对abc文件只有读权限、没有写权限,其它程序(进程)不受此限制。 

penghao@Ding-Perlis-MP260S48:~/AppArmor/sample_code$ ./test_app abcd 2abcd
penghao@Ding-Perlis-MP260S48:~/AppArmor/sample_code$ ls abcd
abcd

penghao@Ding-Perlis-MP260S48:~/AppArmor/sample_code$ ./test_app abcd
fopen failed with r, error: Permission denied

penghao@Ding-Perlis-MP260S48:~/AppArmor/sample_code$ cat abcd
2abcd

可见,test_app对abcd文件只有写权限、没有读权限,其它程序(进程)无此限制。  

penghao@Ding-Perlis-MP260S48:~/AppArmor/sample_code$ ./test_app abcde 3abcde
penghao@Ding-Perlis-MP260S48:~/AppArmor/sample_code$ ls abcde
abcde

penghao@Ding-Perlis-MP260S48:~/AppArmor/sample_code$ ./test_app abcde
 3 a b c d e 

penghao@Ding-Perlis-MP260S48:~/AppArmor/sample_code$ cat abcde
3abcde

可见,test_app对abcde文件既有写权限、又有读权限,最为正常。

如果将abcde文件的权限设置为0444,再来看一下结果:

penghao@Ding-Perlis-MP260S48:~/AppArmor/sample_code$ chmod 444 abcde

penghao@Ding-Perlis-MP260S48:~/AppArmor/sample_code$ echo "1abc" > abcde
bash: abcde: 权限不够

penghao@Ding-Perlis-MP260S48:~/AppArmor/sample_code$ ./test_app 1abc abcde
fopen failed with w, error: Permission denied


penghao@Ding-Perlis-MP260S48:~/AppArmor/sample_code$ cat abcde 
3abcde

penghao@Ding-Perlis-MP260S48:~/AppArmor/sample_code$ ./test_app abcde
 3 a b c d e

以上测试表明,在增强(enforce)模式下,apparmor正常工作了。

以上是最简单的应用,通过aa-genprof创建规则文件,只添加最少需要的文件读写权限规则,
可实现除了文件系统权限以外对某未知程序的读写文件控制(在规则文件里的文件名路径可带通配符)。

要取消只要删除 /etc/apparmor.d/下对应的文件,重启apparmor服务就行。

猜你喜欢

转载自blog.csdn.net/phmatthaus/article/details/130226606