赞
踩
audit是Linux内核提供的一种审计机制,由于audit是内核提供的,因此,在使用audit的过程中就包含内核空间和用户空间部分:
通常的使用流程:
audit的主要应用场景是安全审计,通过对日志进行分析发现异常行为。
auditctl是用户态的控制程序,可以修改audit配置以及审计规则的操作。
auditctl的选项可以分成两类。
配置类:
审计规则类:
例如,假如我们想要获取调用execve系统调用的事件,可以增加下列的规则:
auditctl -a always,exit -S execve -F key=123456
然后就可以通过ausearch查找该日志:
ausearch -k 123456
如果想要获取执行tail命令的事件,可以增加规则:
auditctl -w /usr/bin/tail -p x -k 123456
然后使用tail命令查看通过ausearch命令查看日志:
time->Sun Apr 23 15:47:36 2023
type=PROCTITLE msg=audit(1682236056.128:4318964): proctitle=7461696C002D6E0032006C756F2E7368
type=PATH msg=audit(1682236056.128:4318964): item=1 name="/lib64/ld-linux-x86-64.so.2" inode=36969 dev=08:03 mode=0100755 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:ld_so_t:s0 objtype=NORMAL cap_fp=0000000000000000 cap_fi=0000000000000000 cap_fe=0 cap_fver=0
type=PATH msg=audit(1682236056.128:4318964): item=0 name="/usr/bin/tail" inode=100666597 dev=08:03 mode=0100755 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:bin_t:s0 objtype=NORMAL cap_fp=0000000000000000 cap_fi=0000000000000000 cap_fe=0 cap_fver=0
type=CWD msg=audit(1682236056.128:4318964): cwd="/root"
type=EXECVE msg=audit(1682236056.128:4318964): argc=4 a0="tail" a1="-n" a2="2" a3="luo.sh"
type=SYSCALL msg=audit(1682236056.128:4318964): arch=c000003e syscall=59 success=yes exit=0 a0=20749e0 a1=218ecd0 a2=2179ee0 a3=7fffa4a99460 items=2 ppid=58219 pid=59519 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts1 ses=956 comm="tail" exe="/usr/bin/tail" subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key="123456"
可以看到,开头一行是事件发生的事件,后面的若干行是执行tail命令产生的事件日志,有些日志很简单,例如CWD,表示操作的当前路径,而有些日志很复杂,例如SYSCALL,有接近30个字段。每行日志都有type字段和msg字段(冒号前面是时间戳,可以通过date命令转换,冒号后面是事件ID,同一条规则产生的事件的事件ID是一样的,因此,如果不使用ausearch查找某条规则产生的日志,就需要先用key进行查找,找到对应的事件ID,然后再通过事件ID查找产生的所有日志)。
这里的tail命令的监控,我们只关注上面的2个事件:
通过auditctl -s命令可以看到当前audit的一些属性和配置:
其中backlog_wait_time是后面的版本提供的。
除了上述的使用外,audit还有一个特点:独占性。实际的审计操作是由内核中的kauditd完成的,auditd再通过netlink读取审计日志。而kauditd是只允许与一个用户态进程连接,因此,如果系统上已经有auditd进程与kauditd建立连接,后续其他进程进行了抢占,auditd则会断开。那么,如果判断当前是哪个进程与kautid建立了连接呢?可以通过auditctl -s中的pid进行判断。
另一个重要的地方是kaudit如何去应用配置的规则。在auditctl的-a <l,a>
选项中,给出的选项含义是:将规则和对应的action加入到list后面。list有4种:task、exit、user、exclude,action有2种:never、always。
task、exit、user分别表示审计事件的三种类型:user事件是指与用户相关的事件,例如用户登录、注销、切换等。task是指与进程相关的事件,例如进程创建、退出、切换等。exit是指与系统调用相关的事件。exclude只是一个关键字,用于排除不需要审计的文件或者目录。因此,这里面的事件类型与其他的某些选项有强相关:
配置和规则的变更:
当通过auditctl操作配置或者规则时,会通过netlink将规则发送到内核,内核接收到到配置后会对内部的配置或者规则进行更新
对于规则来说,内核(4.19.281)内部会维护7个链表:
auditctl使用netlink与内核进行交互,因此,要想实现audit的一些能力,就需要采用netlink实现一套交互接口,幸运的是,已经有库可以完成这项工作:yum install -y audit-libs-devel,然后编译时带上-laudit
。
安装完成后,可以查看头文件/usr/include/libaudit.h看下提供的方法。
#include <iostream> #include <libaudit.h> using namespace std; int main() { int fd = audit_open(); audit_request_status(fd); struct audit_reply reply; audit_get_reply(fd, &reply, GET_REPLY_BLOCKING, 0); struct audit_status *status; status = reply.status; cout <<"auditctl -s return:" <<endl; cout << "enabled=" << status->enabled << endl; cout << "failure=" << status->failure << endl; cout << "pid=" << status->pid << endl; cout << "rate_limit=" << status->rate_limit << endl; cout << "backlog_limit=" << status->backlog_limit << endl; cout << "lost=" << status->lost << endl; cout << "backlog=" << status->backlog << endl; return 0; }
先试用audit_request_status()向内核发送请求,表明要获取配置信息,然后再通过audit_get_reply()接收数据,数据放在struct audit_reply的结构体:
// /usr/src/libaudit.h struct audit_reply { int type; int len; struct nlmsghdr *nlh; struct audit_message msg; /* Using a union to compress this structure since only one of * the following should be valid for any packet. */ union { struct audit_status *status; struct audit_rule_data *ruledata; struct audit_login *login; char *message; struct nlmsgerr *error; struct audit_sig_info *signal_info; struct daemon_conf *conf; #ifdef AUDIT_FEATURE_BITMAP_ALL struct audit_features *features; #endif }; };
如果是获取配置信息,此时数据放在status中:
// include/uapi/linux/audit.h struct audit_status { __u32 mask; /* Bit mask for valid entries */ __u32 enabled; /* 1 = enabled, 0 = disabled */ __u32 failure; /* Failure-to-log action */ __u32 pid; /* pid of auditd process */ __u32 rate_limit; /* messages rate limit (per second) */ __u32 backlog_limit; /* waiting messages limit */ __u32 lost; /* messages lost */ __u32 backlog; /* messages waiting in queue */ union { __u32 version; /* deprecated: audit api version num */ __u32 feature_bitmap; /* bitmap of kernel audit features */ }; };
因此,只要读取返回的audit_reply中的status中的上述字段即可。需要注意的是,如果audit_get_reply()中的第3个参数设置为GET_REPLY_NONBLOCKING,可能拿不到数据,因为fd可能还没有可读的数据,所以,这里要么设置为GET_REPLY_BLOCKING,要么使用select:
#include <iostream> #include <libaudit.h> using namespace std; int main() { struct timeval t = { .tv_sec = 0, .tv_usec = 500000 }; int fd = audit_open(); audit_request_status(fd); fd_set read_mask; FD_ZERO(&read_mask); FD_SET(fd, &read_mask); select(fd+1, &read_mask, NULL, NULL, &t); struct audit_reply reply; audit_get_reply(fd, &reply, GET_REPLY_NONBLOCKING, 0); struct audit_status *status; status = reply.status; cout <<"auditctl -s return:" <<endl; cout << "enabled=" << status->enabled << endl; cout << "failure=" << status->failure << endl; cout << "pid=" << status->pid << endl; cout << "rate_limit=" << status->rate_limit << endl; cout << "backlog_limit=" << status->backlog_limit << endl; cout << "lost=" << status->lost << endl; cout << "backlog=" << status->backlog << endl; return 0; }
对于修改配置的操作,libaudit直接提供了对应的api函数,例如,设置backlog_limit,可以直接调用audit_set_backlog_limit()。
#include <iostream> #include <libaudit.h> using namespace std; int main() { struct timeval t = { .tv_sec = 0, .tv_usec = 500000 }; int fd = audit_open(); do { audit_request_rules_list_data(fd); fd_set read_mask; FD_ZERO(&read_mask); FD_SET(fd, &read_mask); select(fd+1, &read_mask, NULL, NULL, &t); struct audit_reply reply; audit_get_reply(fd, &reply, GET_REPLY_NONBLOCKING, 0); if(reply.type == NLMSG_DONE) { break; } struct audit_rule_data *rules; rules = reply.ruledata; cout <<"auditctl -l return:" <<endl; cout << audit_flag_to_name(rules->flags) << endl; cout << audit_action_to_name(rules->action) << endl; } while(true); return 0; }
获取规则跟获取配置的区别只是发起操作的函数和数据解析不同,获取规则使用audit_request_rules_list_data()发起操作,解析数据时则需要解析struct audit_rule_data的数组。
#include <iostream> #include <libaudit.h> #include <linux/audit.h> using namespace std; int main() { int fd = audit_open(); struct audit_rule_data *rule = new(struct audit_rule_data); audit_rule_syscall_data(rule, 57); audit_add_rule_data(fd, rule, AUDIT_FILTER_EXIT, AUDIT_NEVER); return 0; }
上面的代码相当于auditctl -a exit,never -S execve
。
#include <iostream> #include <libaudit.h> #include <linux/audit.h> using namespace std; int main() { int fd = audit_open(); struct audit_rule_data *rule = new(struct audit_rule_data); audit_add_watch(&rule, "/etc/passwd"); audit_add_rule_data(fd, rule, AUDIT_FILTER_EXIT, AUDIT_ALWAYS); return 0; }
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数网络安全工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年网络安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上网络安全知识点!真正的体系化!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
[外链图片转存中…(img-HJZ4xV1i-1715566803431)]
[外链图片转存中…(img-zNsLYPnl-1715566803432)]
[外链图片转存中…(img-wc9ZtsZ3-1715566803432)]
[外链图片转存中…(img-puPd8Pc2-1715566803432)]
[外链图片转存中…(img-e85622y5-1715566803432)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上网络安全知识点!真正的体系化!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。