标签:
catalog
1. Linux进程权限原理 2. 最小权限原则 - 进程降权运行最佳实践 3. 进程权限控制包含的攻防向量 4. 进程高权限安全风险检查技术方案
1. Linux进程权限原理
我们知道,Linux的权限管理体系中,有2个基础权限规则源
1. MAC模型: 磁盘ACL权限,在Linux文件管理中,每个文件又有九位的权限说明,用来指明该文件允许哪些用户执行哪些操作(读、写或者执行) 2. DAC模型: SELINUX权限管理
这2类权限规则是相对静态的东西,穿插在它们之间,相对动态的东西是
1. 用户权限: Linux的用户在登录(login)之后,就带有一个用户身份(user ID, UID)和一个组身份(group ID, GID),用户权限不能直接作用于DAC、MAC等静态权限规则体系,而需要借助进程得以实现 2. 进程权限: 从本质上来说,进程权限代表了启动它的用户的权限(父子进程继承本质还是从启动用户继承的权限)
但是需要明白的是,这里静态的(MAC/DAC磁盘目录权限)和动态的进程权限也会存在"互相影响"的情况,基于"最小权限原则",Linux会对一些敏感ELF设置只有root可执行,而在日常的运维中用户只能使用普通账户(例如admin)进行登录,为了让普通账户admin能够正常执行这些程序,Linux对这些程序设置了s位,s位是磁盘目录文件的一个标志位,但是它可以影响到进程的动态权限,在启动这种带s位的程序的时候,进程的save uid、effect uid都会被置位为属主权限(这样就能以属主的身份去启动这个程序),从而获得临时的只针对这个程序的权限提升,同时又遵循了最小权限原则,保证了系统的安全
0x1: 进程权限分类
1. 真实身份 1) real UID 2) real GID 2. 有效身份 1) effective UID 2) effective GID 3. 存储身份 1) saved UID 2) saved GID
1. 真实身份
real uid、gid用于在进程创建时标识并验证用户身份,也就是说,用户只有符合相应的ACL限制才能执行某条命令(启动进程)或者查看某个资源,真实身份是我们登录shell终端时使用的身份,进程在启动时直接继承的用户的uid、gid,并赋值给进程的real uid、real gid
2. 有效身份
有效身份是当该进程真正去操作文件时所检查的身份,用于在进程运行时,当希望访问其他资源时表示并验证用户身份,也就是说,进程在运行的时候要去访问别的资源或者启动别的程序,这个时候,进程的身份是以euid、egid作为依据
一般情况下,当一个用户登陆系统时,系统会将UID和EUID都赋值为/etc/passwd文件中的UID,一般情况下2个ID是相同的(即euid=uid egid=gid),但是sudo情况下,进程的euid会临时变化成文件属主权限,这时候就有可能出现uid != euid的情况了
#include <stdio.h> main() { printf("getuid(): %d\ngeteuid(): %d\ngetgid(): %d\ngetegid(): %d\n", getuid(), geteuid(), getgid(), getegid()); } /* su zhenghan gcc test.c -o test chmod ug+s test su root ./test */
3. 存储身份
存储身份就是真实身份之外的另一个身份。当我们将一个程序文件执行成为进程的时候,该程序文件的拥有者(owner)和拥有组(owner group)可以被存储成为进程的存储身份。在随后进程的运行过程中,进程就将可以选择将真实身份或者存储身份复制到有效身份,以拥有真实身份或者存储身份的权限。并不是所有的程序文件在执行的过程都设置存储身份的。需要这么做的程序文件会在其九位(bit)权限的执行位的x改为s。这时,这一位(bit)叫做set UID bit或者set GID bit
$ls -l /usr/bin/uuidd -rwsr-sr-x 1 libuuid libuuid 17976 Mar 30 2012 /usr/sbin/uuidd
当我以root(UID), root(GID)的真实身份运行这个程序的时候,由于拥有者(owner)有s位的设定,所以saved UID被设置成为libuuid,saved GID被设置成为libuuid。这样,uuidd的进程就可以在两个身份之间切换
这实现权限运行态临时变化的目的,即用户还是以非root的低权限进行login登录,但是有机会能够执行那些原本只有root才能执行的程序(虽然仅仅是运行态临时可以)
我们通常使用chmod来修改set-UID bit和set-GID bit:
$chmod 4700 file
我们看到,这里的chmod后面不再只是三位的数字。最前面一位用于处理set-UID bit/set-GID bit,它可以被设置成为4/2/1以及或者上面数字的和。4表示为set UID bit, 2表示为set GID bit,1表示为sticky bit (暂时不介绍)。必须要先有x位的基础上,才能设置s位
0x2: 进程权限继承
当进程fork的时候,真实身份和有效身份都会复制给子进程。大部分情况下,真实身份和有效身份都相同。当Linux完成开机启动之后,init进程会执行一个login的子进程。我们将用户名和密码传递给login子进程。login在查询了/etc/passwd和/etc/shadow,并确定了其合法性之后,运行(利用exec)一个shell进程,shell进程真实身份被设置成为该用户的身份。由于此后fork此shell进程的子进程都会继承真实身份,所以该真实身份会持续下去,直到我们登出并以其他身份再次登录(当我们使用su成为root的时候,实际上就是以root身份再次登录,此后真实身份成为root)
0x3: 最小权限原则
Linux通常希望进程只拥有足够完成其工作的特权,而不希望赋予更多的特权给它。从设计上来说,最简单的是赋予每个进程以super user的特权,这样进程就可以想做什么做什么。然而,这对于系统来说是一个巨大的安全漏洞,特别是在多用户环境下,如果每个用户都享有无限制的特权,就很容易破坏其他用户的文件或者系统本身。"最小特权"就是收缩进程所享有的特权,以防进程滥用特权
然而,进程的不同阶段可能需要不同的特权。比如一个进程最开始的有效身份是真实身份,但运行到中间的时候,需要以其他的用户身份读入某些配置文件,然后再进行其他的操作。为了防止其他的用户身份被滥用,我们需要在操作之前,让进程的有效身份变更回来成为真实身份。这样,进程需要在两个身份之间变化,这就是seteuid() api、磁盘文件-s标志位的作用,它们可以起到运行态临时改变权限的目的
0x4: 进程权限在内核态的存储
正如uid,euid的关系一样,task_struct也有两种身份cred
struct task_struct { ... /* process credentials */ const struct cred __rcu *real_cred; /* objective and real subjective task credentials (COW) */ const struct cred __rcu *cred; /* effective (overridable) subjective task credentials (COW) */ ... }
struct cred
http://www.cnblogs.com/LittleHann/p/3865490.html //搜索:0x2: struct cred
Relevant Link:
http://avaj.iteye.com/blog/657185 http://www.cnblogs.com/vamei/archive/2012/10/07/2713593.html http://blog.chinaunix.net/uid-27105712-id-3349522.html http://onestraw.net/linux/linux-struct-cred/ http://www.pizzhacks.com/personal/stesab79/univ/so2/esercitazioni/02-hello-world/hello_world.c
2. 最小权限原则 - 进程降权运行最佳实践
0x1: Linux Nginx最小权限运行
在配置文件最外层增加配置:
worker_process 1; user user;
也可以在编译安装时就显式指定账户、属主
ps -ax -o ruid -o euid -o suid -o fuid -o pid -o fname | grep nginx
权限出让使用最多的场景是类似apache或mysql程序,启动的时候使用root用户启动,设置一些root用户才能操作的系统配置。创建子进程时候通过setuid降级为nobody用户
但是对于nginx这种master-slave架构来说,nginx master必须一直保持root root账户权限,而fork出来的slave worker权限则是降权后的user user(具体名称根据配置文件而定)
0x2: Linux Apache最小权限运行
/etc/httpd/conf/httpd.conf
User daemon
Group daemon
apache没有master-slave的概念,所有apache都是独立的进程,由一个apache父进程fork出多个子进程,它们共同接收HTTP请求
对于apache来说,需要以root权限启动apache,处理完必要的事情后,然后主进程fork出子进程,同时主动让出root权限,主动降权
ps -ax -o ruid -o euid -o suid -o fuid -o pid -o fname | grep httpd
0x3: Linux Tomcat最小权限运行
tomcat本质是一个java程序,对于这类web容器来说,最佳安全实践都是建立一个独立的低权限(仅仅够用)的帐号来运行web容器
0x4: Linux lighttpd最小权限运行
Lighttpd: Lighttpd是一个具有非常低的内存开销,cpu占用率低,效能好,以及丰富的模块等特点。
lighttpd是众多OpenSource轻量级的web server中较为优秀的一个。支持FastCGI, CGI, Auth, 输出压缩(output compress), URL重写, Alias等重要功能。Lighttpd使用fastcgi方式运行php,它会使用很少的PHP进程响应很大的并发量
vim /etc/lighttpd/lighttpd.conf server.username = "lighttpd" server.groupname = "lighttpd"
ps -ax -o euid -o egid -o pid -o fname | grep lighttpd
0x5: Linux mysql最小权限运行
在linux下,新建一个mysql账号,并在安装的时候就指定mysql以mysql账户来运行,给与程序所在目录的读取权限,data所在目录的读取和写入权限
1. mysql运行账号的磁盘权限
1. mysql运行账号需要给予程序所在目录的读取权限,以及data目录的读取和写入权限 2. 不容许给予其他目录的写入和执行权限,特别是有网站的目录 3. 取消mysql运行账户对于cmd,sh等一些程序的执行权限
2. 独立账户运行
vim /etc/my.cnf
user=mysql
可以看到,mysql的udf扩展目录plugin是不允许other运行写操作的,如果我们使用独立账户运行mysql,仅给予程序所在目录的读取权限,以及data目录的读取和写入权限,这样即使mysql被入侵黑客也无法向plugin下写入udf文件
0x6: Linux mongdb最小权限运行
为mongdb建立独立的账户,并赋值mongdb所需要的文件夹的操作权限,以独立账户启动mongdb
0x7: Linux redis最小权限运行
0x8: Linux memcache最小权限运行
0x9: Linux PHP-FPM最小权限运行
建议以独立账户运行,并将相关目录的owner、owngourp改为该账户
Relevant Link:
http://www.z-dig.com/nginx-optimization-25.html http://www.cnblogs.com/LittleHann/p/4902573.html http://howiefh.github.io/2014/04/26/mongodb-note-1-install-mongodb/ http://blog.csdn.net/stronglyh/article/details/46830919 http://linux.it.net.cn/m/view.php?aid=15509
3. 进程权限控制包含的攻防向量
在Linux下进行进程运行权限控制的核心在于: 当进程以独立的非root帐号在运行的时候,它对所有磁盘文件的ACL权限矩阵来说都属于other组,如果磁盘文件ACL本身配置得当,这将极大地保证的web容器的权限范围被控制在一个很小的区间内
0x1: mysql入侵提权分析及防止措施
一般来说,mysql的提权有这么几种方式
1. udf提权 此方式的关键导入一个dll文件,个人认为只要合理控制了进程账户对目录的写入权限即可防止被导入dll文件;然后如果万一被攻破,此时只要进程账户的权限够低,也没办执行高危操作,如添加账户等 2. 写入启动文件 这种方式同上,还是要合理控制进程账户对目录的写入权限 3. 普通账户泄露 此处说的普通账户指网站使用的账户,一个比较方便的建议是直接给予特定库的所有最低权限。账户泄露包括存在注入及web服务器被入侵后直接拿到数据库账户密码
Relevant Link:
http://drops.wooyun.org/tips/2245 http://blog.chinaunix.net/uid-20639775-id-3249105.html http://www.cnblogs.com/LittleHann/p/4903789.html
0x2: mongdb未授权访问
未授权访问漏洞成因:Mongodb 在启动的时候提供了很多参数,如日志记录到哪个文件夹,是否开启认证等。造成未授权访问的根本原因就在于启动Mongodb的时候未设置 --auth
Relevant Link:
https://phphub.org/topics/328 http://blog.itpub.net/26250550/viewspace-1364758/ http://segmentfault.com/a/1190000003002017
0x3: Redis未授权访问漏洞
redis 默认不需要密码即可访问,黑客直接访问即可获取数据库中所有信息,造成严重的信息泄露
Relevant Link:
http://help.aliyun.com/knowledge_detail/5988808.html http://www.goingtodo.net/linux-install-redis-and-autorun/ http://shift-alt-ctrl.iteye.com/blog/1882850 http://www.osyunwei.com/archives/7225.html
0x4: memcached未授权访问漏洞
Relevant Link:
http://lcx.cc/?i=3340 http://securityer.lofter.com/post/1d0f3ee7_79e25bb
4. 进程高权限安全风险检查技术方案
0x1: 进程checklist
1. Nginx 3. Apache/httpd 3. Tomcat 4. lighttpd 5. mysqld 6. mongdb 7. redis 8. memcache 9. PHP-FPM
0x2: 检测流程
1. 枚举/proc/pid 2. 检查/proc/pid/cmdline是否在checklist中出现(findstr) 3. 如果命中则继续查看/proc/pid/status,获取euid、egid这2个字段 4. 判断当前获取的euid、egid是否为0、0,如果是,则报告异常
Relevant Link:
euid egid
ps -ax -o euid -o egid -o pid -o fname | grep nginx
Copyright (c) 2015 LittleHann All rights reserved
Linux process authority、the security risks in running process with high authority
标签:
原文地址:http://www.cnblogs.com/LittleHann/p/4898999.html