




已阅读5页,还剩115页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Linux 安全体系分析与编程2.2 审计系统2.2 审计系统Linux提供了用来记录系统安全信息的审计系统,审计系统分为用户空间和内核空间审计系统,用户空间审计系统用来设置规则和审计系统状态、将内核审计系统传来的审计消息写入log文件。内核审计系统用于产生和过滤内核的各种审计消息。本节重点分析内核审计系统产生和过滤审计消息的机制。2.2.1 审计系统构架审计系统提供了一种记录系统安全信息的方法,为系统管理员在用户违反系统安全法则时提供及时的警告信息。审计系统的审计信息包括:可被审计的事件名称、事件状态(成功或失败)和安全信息等。审计系统可以将记录系统内部发生的事件的信息根据用户的需求,提供不同的报表功能,从而实现对系统信息的追踪、审查、统计和报告等功能。Linux审计系统子系统之间通信如图2-3所示。应用程序auditctl用来设置审计消息过滤规则、查询内核审计系统状态等,它通过netlink机制与内核审计系统的socket线程进行双向通信。内核其他线程的审计信息通过内核审计API写入套接字缓冲区队列audit_skb_queue中,内核线程kauditd通过netlink机制将审计消息定向发送给用户空间的审计后台auditd的主线程,auditd主线程再通过事件队列将审计消息传给审计后台的写log文件线程,由写log文件线程将审计消息写入log文件。另一方面,审计后台还通过一个与套接字绑定的管道将审计消息发送给dispatcher应用程序。2.2.2 用户空间审计系统应用程序在用户空间,审计系统由auditd、audispd、auditctl、autrace、ausearch和aureport等应用程序组成。审计后台auditd应用程序通过netlink机制从内核中接收审计消息,然后,通过一个工作线程将审计消息写入到审计日志文件中,其中,还有一部分消息通过消息分发后台进程dispatcher调用syslog写入日志系统。下面分别说明这些应用程序的功能。1审计后台auditd在用户空间,审计系统通过auditd后台进程接收内核审计系统传送来的审计信息,将信息写入到/var/log/audit/audit.log 中,audit.log的路径可在/etc/auditd.conf 中指定。图2-3 Linux审计系统子系统之间通信当auditd没有运行时,内核将审计信息传送给 syslog,这些消息通常保存在/var/log/messages文件中,可以用dmesg命令查看。如果要启用内核中的审计功能,必须在系统启动时将audit=1传递给内核。也可以在运行时,使用下列命令来启用内核审计功能:auditctl -e 1审计系统后台应用程序auditd是Linux审计系统的用户空间部件,它负责将审计记录写入到硬盘中。ausearch或aureport工具用来查看写在文件中的审计记录,auditctl工具用来设置审计规则。系统启动时,auditctl读取/etc/audit.rules中的规则,审计后台可以通过auditd.conf文件定制配置。运行auditd后台的命令如下:auditd -f 其中,选项-f表示让auditctl在前台运行,以方便调试,消息可以直接输出到stderr,而不是输出到log系统。用于配置auditd后台的文件说明如下:/etc/auditd.conf用于auditd后台的配置文件。/etc/audit.rules启动时装载的审计规则。2auditctl工具auditctl控制行为、得到状态、从内核审计系统增加或删除规则。命令格式如下:auditctl options工具auditctl的命令行选项(options)很多,例如:-e 0|1表示停止或启动内核审计功能;-a表示将规则追加到链表;-S表示系统调用号或名字;-F表示规则域。工具auditctl设置规则的样例如下:/查看程序所有的系统调用auditctl -a entry,always -S all -F pid=1005/查看指定用户打开的文件auditctl -a exit,always -S open -F auid=510/查看不成功的open系统调用auditctl -a exit,always -S open -F success!=0设置规则和显示规则的命令样例列出如下:-$ auditctl -a entry,always -S all -F pid=1005-$ auditctl -lLIST_RULES: entry,always pid=1005 (0x3ed) syscall=all工具auditctl的选项说明如表2-1所示。表2-1 工具auditctl的选项说明选 项 名选项的值说 明-b 设置内核允许的缓冲区数,默认值为64-e 0|1关闭或启动内核审计系统-f 0.2设置失败标识0=silent 1=printk 2=panic,默认值为1。设置内核如何处理临界错误,如:backlog限制超出、内存错误等-h 帮助信息-i当从文件中读取规则时忽略错误-l列出所有的规则,每行一条规则-k 设置审计规则上的过滤关键词key,key是不超过32字节长的任意字符串,它能唯一鉴别由watch产生的审计记录-m text仅由root用户发送用户空间消息到审计系统。为文件系统watch设置许可过滤器。r=read,w=write,x=execute,a=attribute change。这些许可不是文件的标准许可,而是系统调用使用的,read和write系统调用将忽略这种设置,否则它们将淹没log-r 设置每秒传输的消息数限制,默认值为0,表示无限制-R 从file文件中读取规则-s报告状态-a 追加规则到l链表,a表示规则的动作有效链表名ltask追加规则到每个任务链表AUDIT_FILTER_TASK 。域应用任务创建时的uid、gid等entry追加规则到系统调用进入链表AUDIT_FILTER_ENTRY,用于决定进入到系统调用时是否创建审计事件exit追加规则到系统调用退出链表AUDIT_FILTER_EXIT 。用于决定退出系统调用时是否创建审计事件user追加规则到用户消息过滤链表AUDIT_FILTER_USER ,内核在转播用户空间产生的事件到审计后台之前,用这个链表过滤这些事件。仅域为uid、auid、gid和pid时有效exclude用于过滤不想看到的事件,对应内核消息过滤链表AUDIT_FILTER_TYPE 规则的有效动作anever不产生审计记录always分配一个审计上下文,在系统调用退出时填充-A 添加规则到l链表头,动作为a-d 从带有a动作的l链表删除规则-D删除所有的规则和watch-S 系统调用名或号|all如果程序使用指定的系统调用,则它启动一项审计记录。如果给出域规则而没有指定系统调用,它将默认为所有系统调用续表 选 项 名选项的值说 明-F n=v | n!=v | nv | n=v创建一个规则域:名字、操作、值。可以单个命令行传递最多64个域。每个域必须启动一个审计记录。可支持6种操作:等于、不等于、小于、大于、小于或等于和大于或等于有效的规则域na0, a1, a2, a3对应系统调用的前4个参数。不支持字符串参数。常用于复合的套接字或IPC操作arch系统调用的CPU构架auidaudit uid,是用户注册的最初的IDb32用于32位系统调用表的archb64用于64位系统调用表的archdevmajor主设备号(Device Major Number)devminor次设备号(Device Minor Number)egid有效组IDeuid有效用户IDexit从一个系统调用退出时的值fsgid文件系统组IDgid组IDinode节点号key设置过滤关键字,与-k选项一样msgtype用于匹配消息类型编号,仅用于排除(exclude)过滤链表obj_user资源的SELinux用户obj_role资源的SELinux角色obj_type资源的SELinux类型obj_lev_low资源的SELinux低级别obj_lev_high资源的SELinux高级别path监视的文件的全路径,仅用于exit链表pers操作系统(OS)个人特征序列号pid进程IDppid父进程IDsubj_user程序的SELinux用户subj_role程序的SELinux角色subj_type程序的SELinux类型subj_sen程序的SELinux敏感度(Sensitivity)subj_clr程序的SELinux的间隔(Clearance)sgid设置组IDsuccess如果退出值大于或等于0,这个值为true/yes,否则为false/no。当写规则时,用1表示true/yes,用0表示false/nosuid设置用户ID(Set User ID)uid用户ID(User ID)-w 为文件系统对象插入一个watch(监视)。不支持匹配符-W 移去文件系统对象path上的watch3autraceautrace是一个程序,它将添加审计规则、类似于strace跟踪一个进程,审计信息的结果将记录在审计log文件中。在目标程序执行的前后,它都将删除审计规则。autrace用于模拟strace工具。语法列出如下:autrace program 一个使用sutrace程序的典型样例列出如下:-$ auditd -$ autrace /bin/ls /tmpWaiting to execute: /bin/lsgconfd-rootvirtual-root.SReCx6Cleaning up.No rulesTrace complete. You can locate the records with ausearch -i -p 5722-$ vi /var/log/audit/audit.logtype=DAEMON_START msg=audit(1174214581.293:1962) auditd start, ver=1.2.8, format=raw, auid=4294967295 pid=5477 res=success, auditd pid=54type=CONFIG_CHANGE msg=audit(1174214581.514:38): audit_enabled=1 old=1 by auid=4294967295 subj=user_u:system_r:unconfined_t:s04ausearch工具ausearch用于查询审计后台的日志,它能基于不同搜索规则的事件查询审计后台日志。每个系统调用进入内核空间运行时有个唯一的事件ID,系统调用在进入内核后的运行过程的审计事件共享这个ID。内核可以添加各种审计记录,例如:系统调用“open”的审计事件将引起内核发送一个带有文件名的PATH记录。ausearch的语法列出如下:ausearch options 其中,options表示选项值,如:-a 、-f 等。基于用户ID的搜索样例列出如下:-$ ausearch -ui 4294967295-time-Sun Mar 18 18:43:01 2007type=DAEMON_START msg=audit(1174214581.293:1962) auditd start, ver=1.2.8, format=raw, auid=4294967295 pid=5477 res=success, auditd pid=54-time-Sun Mar 18 18:43:01 2007type=CONFIG_CHANGE msg=audit(1174214581.514:38): audit_enabled=1 old=1 by auid=4294967295 subj=user_u: system_r:unconfined_t:s05aureport工具aureport用于产生审计后台日志的总结报告,语法列出如下:aureport options 其中,options表示选项,如:-a报告所有的AVC(Access Vector Cache)消息;-c报告配置改变的消息;-e报告事件消息。工具aureport运行后结果列出如下:-$ aureportSummary Report=Range of time: 03/18/2007 18:43:01.293 - 03/18/2007 18:43:01.514Number of changes in configuration: 1Number of changes to accounts or groups: 0Number of logins: 0Number of failed logins: 0Number of users: 0Number of terminals: 0Number of host names: 0Number of executables: 0Number of files: 0Number of avc denials: 0Number of failed syscalls: 0Number of anomaly events: 0Number of responses to anomaly events: 0Number of process IDs: 1Number of events: 26audispdaudispd是消息分发的后台进程,用于将auditd后台发过来的一些消息通过syslog写入日志系统。2.2.3 内核审计缓冲区管理机制内核审计系统将审计消息写入审计用的缓冲区(称为审计缓冲区)。由于审计信息是通过netlink机制发往用户空间后台进程的,因此,审计缓冲区包括了结构sk_buff描述的套接字缓冲区,套接字缓冲区用来存储用于发送的审计消息记录。审计缓冲区的结构定义如下(在linux26/kernle/audit.c中):struct audit_buffer struct list_head list; struct sk_buff *skb; /*格式化的套接字缓冲区,准备用于发送审计消息 */ /*每个进程的审计上下文,包括进程的状态、时间和uid等,与进程上下文相关,可以为空 */ struct audit_context *ctx; gfp_t gfp_mask;/缓存区的标识,如:_GFP_WAIT;审计套接字缓冲区组成链表,用于存入填充了审计消息的审计套接字缓冲区指针,链表定义如下(在linux26/kernle/audit.c中):static struct sk_buff_head audit_skb_queue;审计套接字缓冲区链表用于存入审计消息,当链表中的缓冲区个数超过上限时,当前进程需要等待用户空间的后台进程将审计消息写入log文件,直到缓冲区个数小于上限值为止。内核审计系统还使用空闲审计缓冲区链表audit_freelist 存放空闲的审计缓冲区,存放的个数上限为AUDIT_MAXFREE。这样,维持一定数据的空闲缓冲区数,对于频繁操作的审计系统来说,可以减少缓冲区的分配与释放次数,提高系统性能。当申请审计缓冲区时,系统先查看链表audit_freelist是否存在空闲的审计缓冲区;如果存在,就从链表中取下一个返回给申请者。如果链表中没有空闲审计缓冲区,就分配一个审计缓冲区。当调用函数audit_buffer_free释放审计缓冲区时,先检查空闲审计缓冲区链表audit_freelist的空闲审计缓冲区是否超过上限;如果没有超过上限,就将审计缓冲区放入链表audit_freelist,留给以后使用。否则,释放缓冲区。函数audit_buffer_free释放审计缓冲区时,每次都释放它包含的套接字缓冲区。空闲审计缓冲区链表的定义列出如下:#define AUDIT_MAXFREE (2*NR_CPUS)static LIST_HEAD(audit_freelist);2.2.4 审计事件分类审计系统的消息事件分为以下几个部分:10001099用于审计系统的命令。11001199 用户空间可信的应用程序消息。12001299 审计后台的内部消息。13001399 审计事件消息。14001499 SELinux使用的消息。15001599 内核LSPP事件。16001699 内核加密(crypto)事件。17001799 内核正常记录。18001999 将来内核使用(可能是整数标签和相关的事件)。2000 用于其他没有分类的内核审计消息(假想)。20012099 未使用(内核)。21002199 用户空间正常记录。22002299 用户空间对正常记录相应的动作。23002399 用户空间产生的LSPP事件。24002499 用户空间加密事件。25002999 用户空间将来使用(可能是整数标签和相应的事件)。10001199是内核和用户空间双向使用的,12001299和21002999是用户空间专有的,13002099是内核-用户空间通信用的。审计事件的详细定义在linux26/include/linux/audit.h中实现,事件的定义在内核和用户空间的审计系统都是一致的。内核审计系统根据审计事件执行相应的操作或者完成相应的审计消息过滤。2.2.5 内核审计系统的接口函数在Linux内核需要输出审计信息时,它先调用函数audit_log_start创建缓冲区。接着,调用函数audit_log或audit_log_format写缓冲区写入审计信息,最后调用函数audit_log_end发送审计信息,并释放缓冲区。这三个函数分别说明如下:1函数audit_log_start 函数audit_log_start申请审计缓冲区,如果任务当前在系统调用中,系统调用被标识为可审计的,并在系统调用退出时,产生一条审计记录。函数audit_log_start的参数ctx为审计上下文结构实例;参数gfp_mask为分配内存的类型,如:_GFP_WAIT表示可以等待和重调度;参数type为审计消息类型。如果缓存区申请成功,它返回审计缓冲区的指针,否则返回NULL表示错误。函数audit_log_start申请审计缓冲区,当审计缓冲区链表的缓冲区个数超过上限时,当前进程需要等待用户空间的后台进程将审计消息写入log文件,直到缓冲区个数小于上限值为止。函数audit_log_start在申请并初始化审计缓冲区后,给缓冲区加时间戳和审计记录序列号。函数audit_log_start列出如下(在linux26/kernel/audit.c中):/声明等待队列头,用于等待审计消息被后台进程写入log文件static DECLARE_WAIT_QUEUE_HEAD(audit_backlog_wait);struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, int type) struct audit_buffer *ab = NULL; struct timespec t; unsigned int serial; int reserve; unsigned long timeout_start = jiffies; /开始的时间 if (!audit_initialized)/如果已初始化,就直接退出 return NULL; if (unlikely(audit_filter_type(type) return NULL; if (gfp_mask & _GFP_WAIT) reserve = 0; else reserve = 5; /*允许调用者多出5个条目*/ /当链表中审计缓冲区数超出上限时,进程等待auditd处理链表中缓冲区 while (audit_backlog_limit & skb_queue_len(&audit_skb_queue) audit_backlog_limit + reserve) if (gfp_mask & _GFP_WAIT & audit_backlog_wait_time & time_before(jiffies, timeout_start + audit_backlog_wait_time) /* 等待后台进程auditd从队列中处理部分缓冲区 */ DECLARE_WAITQUEUE(wait, current); set_current_state(TASK_INTERRUPTIBLE); /设置当前进程的状态为可中断等待状态 add_wait_queue(&audit_backlog_wait, &wait); /将当前进程加入等待队列 if (audit_backlog_limit & skb_queue_len(&audit_skb_queue) audit_backlog_limit) schedule_timeout(timeout_start + audit_backlog_wait_time - jiffies);/调度 _set_current_state(TASK_RUNNING);/设置当前进程为运行状态 remove_wait_queue(&audit_backlog_wait, &wait); continue; /检查每秒发送的记录数不能超过上限,以防止受非法攻击 if (audit_rate_check() printk(KERN_WARNING audit: audit_backlog=%d audit_backlog_limit=%dn, skb_queue_len(&audit_skb_queue), audit_backlog_limit); audit_log_lost(backlog limit exceeded); audit_backlog_wait_time = audit_backlog_wait_overflow; wake_up(&audit_backlog_wait); return NULL; ab = audit_buffer_alloc(ctx, gfp_mask, type);/申请审计缓冲区 if (!ab) audit_log_lost(out of memory in audit_log_start); return NULL; /得到当前时间存入t,计算审计记录的序列号,存入serial audit_get_stamp(ab-ctx, &t, &serial); /将时间戳和序列号写入审计记录 audit_log_format(ab, audit(%lu.%03lu:%u): , t.tv_sec, t.tv_nsec/1000000, serial); return ab;函数audit_buffer_alloc申请审计缓冲区,先尝试从空闲链表上取下一个缓冲区,如果空闲链表中没有,就分配一个缓冲区。然后,填充netlink消息头。该函数列出如下:static DEFINE_SPINLOCK(audit_freelist_lock);/定义自旋锁,用于锁住链表audit_freeliststatic struct audit_buffer * audit_buffer_alloc(struct audit_context *ctx, gfp_t gfp_mask, int type) unsigned long flags; struct audit_buffer *ab = NULL; struct nlmsghdr *nlh; /从空闲链表中得到一个缓冲区 spin_lock_irqsave(&audit_freelist_lock, flags);/加锁 if (!list_empty(&audit_freelist) ab = list_entry(audit_freelist.next, struct audit_buffer, list); list_del(&ab-list); -audit_freelist_count; spin_unlock_irqrestore(&audit_freelist_lock, flags);/释放锁 /如果空闲链表中没有空闲缓冲区成员,就分配一个缓冲区 if (!ab) ab = kmalloc(sizeof(*ab), gfp_mask); if (!ab) goto err; ab-skb = alloc_skb(AUDIT_BUFSIZ, gfp_mask);/分配套接字缓冲区 if (!ab-skb) goto err; ab-ctx = ctx; ab-gfp_mask = gfp_mask; /扩展套接字缓冲区skb的已使用数据区,将netlink消息头数据nlmsghdr加到skb nlh = (struct nlmsghdr *)skb_put(ab-skb, NLMSG_SPACE(0); nlh-nlmsg_type = type; nlh-nlmsg_flags = 0; nlh-nlmsg_pid = 0; nlh-nlmsg_seq = 0; return ab;err: audit_buffer_free(ab); return NULL;2函数audit_log_format函数audit_log_format将一个审计消息按格式写入审计缓冲区,参数ab为审计缓冲区,参数fmt为格式化的字符串。其列出如下:void audit_log_format(struct audit_buffer *ab, const char *fmt, .) va_list args; if (!ab) return; va_start(args, fmt); audit_log_vformat(ab, fmt, args); va_end(args);函数audit_log_vformat将一个审计消息按格式写入套接字缓冲区中,如果审计缓冲区没有足够的空间,就扩展套接字缓冲区的数据域。由于printk缓冲区为1024,扩展的套接字缓冲区最小应为1024。函数audit_log_vformat列出如下:static void audit_log_vformat(struct audit_buffer *ab, const char *fmt, va_list args) int len, avail; struct sk_buff *skb; va_list args2; if (!ab) return; BUG_ON(!ab-skb); skb = ab-skb; avail = skb_tailroom(skb);/计算套接字缓冲区的空闲数据空间 if (avail = 0) /如果套接字缓冲区没有空闲数据空间,扩展空间 avail = audit_expand(ab, AUDIT_BUFSIZ);/ AUDIT_BUFSIZ为1024, if (!avail) goto out; va_copy(args2, args); len = vsnprintf(skb-tail, avail, fmt, args);/将信息写入到缓冲区 if (len = avail) /如果实际信息长度比可用的缓冲区大,扩展空间 /* 由于printk缓冲区是1024,因此,扩展空间最少为1024 */ avail = audit_expand(ab, max_t(unsigned, AUDIT_BUFSIZ, 1+len-avail); if (!avail) goto out; len = vsnprintf(skb-tail, avail, fmt, args2);/将审计信息写入到缓冲区 if (len 0) skb_put(skb, len); /将写入信息的数据缓冲区附加到skb上out: return;函数audit_expand扩展在审计缓冲区中的套接字缓冲区,扩展成功,返回可用的空间大小,扩展失败返回0,表示没有空间。参数ab表示审计缓冲区的指针,参数extra表示加到套接字缓冲区skb尾部的缓冲区空间大小。函数audit_expand列出如下:static inline int audit_expand(struct audit_buffer *ab, int extra) struct sk_buff *skb = ab-skb; int ret = pskb_expand_head(skb, skb_headroom(skb), extra, ab-gfp_mask); if (ret skb-data; nlh-nlmsg_len = ab-skb-len - NLMSG_SPACE(0); skb_queue_tail(&audit_skb_queue, ab-skb); ab-skb = NULL; wake_up_interruptible(&kauditd_wait);/发送了数据,唤醒等待队列 else /使用printk记录数据 printk(KERN_NOTICE %sn, ab-skb-data + NLMSG_SPACE(0); audit_buffer_free(ab);2.2.6 内核审计系统初始化函数audit_init在系统启动时初始化内核审计系统,它创建nelink机制套接字,注册接收函数,给SELinux注册审计回调函数,注册文件系统变化监控机制的操作函数集。该函数列出如下:/* 基于节点规则的Hash表 */struct list_head audit_inode_hashAUDIT_INODE_BUCKETS;static int _init audit_init(void) int i; printk(KERN_INFO audit: initializing netlink socket (%s)n, audit_default ? enabled : disabled); /创建nelink机制套接字audit_sock,将函数audit_receive注册作为netlink机制接收函数 audit_sock = netlink_kernel_create(NETLINK_AUDIT, 0, audit_receive, THIS_MODULE); if (!audit_sock) audit_panic(cannot initialize netlink socket); else audit_sock-sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;/定义发送超时时间 skb_queue_head_init(&audit_skb_queue); /初始化 audit_initialized = 1; audit_enabled = audit_default; /*给SELinux注册回调函数,当新的策略发生变化时,将触发这个回调函数*/ selinux_audit_set_callback(&selinux_audit_rule_update); audit_log(NULL, GFP_KERNEL, AUDIT_KERNEL, initialized);#ifdef CONFIG_AUDITSYSCALL audit_ih = inotify_init(&audit_inotify_ops);/注册文件系统变化监控机制的操作函数集 if (IS_ERR(audit_ih) audit_panic(cannot initialize inotify handle);#endif for (i = 0; i sk_receive_queue); qlen; qlen-) skb = skb_dequeue(&s
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 成都市锦江区招聘员额教师26人备考考试题库附答案解析
- 2025黑龙江省校园引才活动绥化市人才引进389人备考考试题库附答案解析
- 2026中铁电气化局二公司校园招聘备考考试题库附答案解析
- 工厂安全培训照片素材库课件
- 2025广西工商职业技术学院招聘广西重点领域急需紧缺高层次人才12人备考考试题库附答案解析
- 2026中船航海科技有限责任公司校园招聘备考考试题库附答案解析
- 元素世界探秘
- 娱乐业商务礼仪解析
- 文化旅游局宣传营销方案
- 阅读的力量与智慧
- 2025合伙制合同协议书
- 福建省全国名校联盟2026届高三上学期联合开学摸底考试语文试题及参考答案
- 2025年广工建筑电气试卷及答案
- 2024年广西桂林理工大学南宁分校招聘真题
- 排污许可证管理条例课件
- 乡镇人大主席“干在实处、走在前列”学习讨论发言材料
- 2025年食品安全管理员考试题库及参考答案
- 用户反馈收集及问题分析表
- 公路施工质量培训课件
- 化工总控工项目6任务28精馏操作专项训练课件
- 委托办理原产地证书授权书
评论
0/150
提交评论