zoukankan      html  css  js  c++  java
  • Linux的capability深入分析(2)【转】

    转自:https://blog.csdn.net/wangpengqi/article/details/9821231



    rpm -ql libcap-2.16-5.2.el6.i686 
    /lib/libcap.so.2.16
    /usr/sbin/capsh
    /usr/sbin/getpcaps
    /usr/share/doc/libcap-2.16
    /usr/share/doc/libcap-2.16/capability.notes
    /usr/share/man/man8/setcap.8.gz
     
    getpcaps可以获得进程所具有的能力(CAP).
    我们下面主要用setcap来进行调试.
     
     

    setcap cap_chown=eip /bin/chown 
     
    getcap /bin/chown               

    su - test

    -rwxr-xr-x. 1 test test 118736 Jun 14  2010 /bin/ls
     
    1)cap_chown=eip是将chown的能力以cap_effective(e),cap_inheritable(i),cap_permitted(p)三种位图的方式授权给相关的程序文件.
    3)用setcap -r /bin/chown可以删除掉文件的能力.
    4)重新用setcap授权将覆盖之前的能力. 
     
     

    setcap cap_dac_override=eip /usr/bin/vim 
     
    su - test
     
    vim /etc/shadow
    bin:*:14790:0:99999:7:::
    adm:*:14790:0:99999:7:::
     
    DAC_OVERRIDE能力是DAC_READ_SEARCH能力的超集.
     
     
     

    setcap cap_dac_read_search=eip /bin/cat
     
    su - test
     
    cat /etc/shadow
    bin:*:14790:0:99999:7:::
    adm:*:14790:0:99999:7:::
     
     
     

     
    ls -l /tmp/passwd   

    setcap cap_fowner=eip /usr/bin/vim
     
    su - test
     
    vi /tmp/passwd

     
    -rw-r--r-- 1 test test 1176 2011-04-29 19:21 /tmp/passwd
     
     
     
    起因是当文件被修改后,会清除掉文件的setuid/setgid位,而设定CAP_FSETID后将保证setuid/setgid位不被清除.但这对chown函数无用.
     
    #include <sys/types.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <sys/stat.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    {
            int handle;
            char string[40];
            int length, res;
     
            {
                    exit(1);
            }
            length = strlen(string);
            if ((res = write(handle, string, length)) != length)
            {
                    exit(1);
            }
            close(handle);
    gcc fsetid.c -o fsetid
     
    chmod 6777 /tmp/passwd
    -rwsrwsrwx 1 test test 14 2011-04-30 14:22 /tmp/passwd
    /tmp/fsetid 
    ls -l /tmp/passwd
    我们看到setuid/setgid位被清除了.
     
    chmod 6777 /tmp/passwd
    ls -l /tmp/passwd     

    setcap cap_fsetid=eip /tmp/fsetid
     
    /tmp/fsetid
    ls -l /tmp/passwd

     
     
     
     

     

    su - root

    pgrep top     
    /bin/kill 3114
    我们发现无法对不属于自己的进程发送信号.
     
     

    setcap cap_kill=eip /bin/kill 
     
    /bin/kill 3114
    0
     
    普通用户要用/bin/kill这种绝对路径的方式,而不能用kill这种方式.
     
     
     

     
    chown root.root /tmp/shadow

    su - test
    #include <unistd.h>
    main ()
            gid_t gid = 0;
            setgid(gid);
            return 0;
    gcc setgid.c -o setgid
     
    setcap cap_setgid=eip /tmp/setgid
     
    su - test
    /tmp/setgid 
    daemon:*:14479:0:99999:7:::
    sys:*:14479:0:99999:7:::
    games:*:14479:0:99999:7:::
    lp:*:14479:0:99999:7:::
    news:*:14479:0:99999:7:::
    proxy:*:14479:0:99999:7:::
    backup:*:14479:0:99999:7:::

    setcap -r /tmp/setgid
     
    /tmp/setgid 

     
     
     

     
    chown root.root /tmp/shadow

    su - test
    vi setuid.c
    #include <unistd.h>
    main ()
            uid_t uid = 0;
            setuid(uid);
            return 0;
    gcc setuid.c -o setuid
     
    su - root

    su - test
    root:$1$S9AmPHY8$ZIdORp6aLnYleb5EORxw8/:14479:0:99999:7:::
    bin:*:14479:0:99999:7:::
    sync:*:14479:0:99999:7:::
    man:*:14479:0:99999:7:::



    /tmp/setuid 

     
     
     
    事实上只有init进程可以设定其它进程的能力,而其它程序无权对进程授权,root用户也不能对其它进程的能力进行修改,只能对当前进程通过cap_set_proc等函数进行修改,而子进程也会继承这种能力.

     
     
     
    普通用户不能通过chattr对文件设置IMMUTABLE(chattr +i)和APPEND-ONLY(chattr +a)权限,而通过CAP_LINUX_IMMUTABLE可以使普通用户通过自己增减(immutable/append-only)权限.
     
     
     
    touch /tmp/test
    chattr: Operation not permitted while setting flags on /tmp/test
     
    此时切换到root用户:
    su - 
    setcap cap_linux_immutable=eip /usr/bin/chattr 
     
    su - test
    lsattr /tmp/test 
    我们看到授权成功了,注意,这里只能对自己的文件授权(immutable/append-only)权限,对于其它用户的权限LINUX_IMMUTABLE不起作用(root除外),如下:
    chattr +i /etc/passwd

     
     
     
    普通用户不能通过bind函数绑定小于1024的端口,而root用户可以做到,CAP_NET_BIND_SERVICE的作用就是让普通用户也可以绑端口到1024以下.
     
    nc -l -p 500

    setcap cap_net_bind_service=eip /usr/bin/nc
     
    nc -l -p 500
     
    netstat -tulnp|grep nc
    tcp        0      0 0.0.0.0:500             0.0.0.0:*               LISTEN      2523/nc       
     
     
     
     


     
     
     


    /sbin/ifconfig eth0:1 172.16.27.133 netmask 255.255.255.0
    SIOCSIFFLAGS: Permission denied

    setcap cap_net_admin=eip /sbin/ifconfig
     
    /sbin/ifconfig eth0:1 172.16.27.133 netmask 255.255.255.0
    eth0:1    Link encap:Ethernet  HWaddr 00:0c:29:f9:5e:06  
              inet addr:172.16.27.133  Bcast:172.16.27.255  Mask:255.255.255.0
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              Interrupt:18 Base address:0x1080 
     
    /sbin/ifconfig eth0:1 down 
     
    /sbin/route add -host 192.168.27.139 gw 192.168.27.2

    setcap cap_net_admin=eip /sbin/route
     
    /sbin/route add -host 192.168.27.139 gw 192.168.27.2
    /sbin/route  -n
    Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
    192.168.27.139  192.168.27.2    255.255.255.255 UGH   0      0        0 eth0
    192.168.27.0    0.0.0.0         255.255.255.0   U     0      0        0 eth0
    0.0.0.0         192.168.27.2    0.0.0.0         UG    0      0        0 eth0
    /sbin/route del -host 192.168.27.139 gw 192.168.27.2   
     

    普通用户不能用iptables来管理防火墙,如下:
    iptables v1.4.2: can't initialize iptables table `filter': Permission denied (you must be root)

    setcap cap_net_admin,cap_net_raw=eip /sbin/iptables-multi
     
    /sbin/iptables -A INPUT -p tcp -j ACCEPT
    Chain INPUT (policy ACCEPT)
    target     prot opt source               destination         
    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           
     
    target     prot opt source               destination         
     
    target     prot opt source               destination     
     
    /sbin/iptables -F
    /sbin/iptables -X
     
     
     
     
    原始套接字编程可以接收到本机网卡上的数据帧或者数据包,对监控网络流量和分析是很有作用的.
     
    socket(PF_INET, SOCK_RAW, IPPROTO_ICMP) = 3
     
     
    chmod u-s /bin/ping
    -rwxr-xr-x 1 root root 30788 2007-12-09 23:03 /bin/ping
     
    ping  192.168.27.2  

    setcap cap_net_raw=eip /bin/ping
     
    ping  192.168.27.2
    64 bytes from 192.168.27.2: icmp_seq=1 ttl=128 time=0.266 ms
    64 bytes from 192.168.27.2: icmp_seq=3 ttl=128 time=0.319 ms
     

     
     
     
    root和普通用户都可以用mlock来锁定内存,区别是root不受ulimit下的锁定内存大小限制,而普通用户会受到影响.
     
    #include <stdio.h>
    #include <sys/mman.h>
     
    {
            int array[2048];
     
            if (mlock((const void *)array, sizeof(array)) == -1) {
                    return -1;
            }
     
                            array, sizeof(array));
     
     
            if (munlock((const void *)array, sizeof(array)) == -1) {
                    return -1;
            }
     
                            array, sizeof(array));
     
            return 0;
    gcc mlock.c -o mlock
     
    ulimit -a
    max locked memory       (kbytes, -l) unlimited
     
    ./mlock
    success to unlock stack mem at: 0xbfd94914, len=8192
     
     
    ulimit -l 1
    mlock: : Cannot allocate memory
     
    setcap cap_ipc_lock=eip /tmp/mlock
     
    ./mlock
    success to unlock stack mem at: 0xbfec1584, len=8192
     
     
     
     
     
    这个能力对普通用户有作用,如果用root用户创建共享内存(shmget),权限为600,而普通用户不能读取该段共享内存.

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    #include <sys/wait.h>
     
    {
            perror(msg);
            exit(EXIT_FAILURE);

     
    {
            key_t mykey = 12345678;
     
            const size_t region_size = sysconf(_SC_PAGE_SIZE);
            int smid = shmget(mykey, region_size, IPC_CREAT|0600);
            if(smid == -1)
     
            void *ptr;
            ptr = shmat(smid, NULL, 0);
            if (ptr == (void *) -1)
            u_long *d = (u_long *)ptr;
            *d = 0xdeadbeef;
     
            return 0;

    我们用root用户来执行本程序,创建共享内存,如下:
    ipc mem 0xdeadbeef
     
    ipcs -m
     
    key        shmid      owner      perms      bytes      nattch     status      
    0x00bc614e 458752     root      600        4096       0              
     
    修改程序,将*d = 0xdeadbeef;改为*d = 0xffffffff;
    gcc test.c -o test -lrt
     
    /tmp/test
    我们看到没有权限更改共享内存.
     
    setcap cap_ipc_owner=eip /tmp/test
     
    /tmp/test


     
     
     
     
    由于普通用户不能插入/删除内核模块,而CAP_SYS_MODULE可以帮助普通用户做到这点
     

    /sbin/modprobe nvram      


    setcap cap_sys_module=eip /sbin/modprobe
     
     
    /sbin/modprobe nvram
    nvram                   3861  0 

    setcap cap_sys_module=eip /sbin/rmmod
     
    /sbin/rmmod nvram

     
     
     

    iopl可以用于所有的65536个端口,因此ioperm相当于iopl调用的一个子集.
     
    #include <unistd.h>
    #include <sys/io.h>
     

    {
          int ret;
          char port_val;
          
          /*set r/w permission of all 65536 ports*/
          ret = iopl(3);
          if(ret < 0){
               return 0;
          }
     
          port_val = inb(PORT_ADDR);
          
          /*reverse the least significant bit */
     
          outb(port_val^0x01, PORT_ADDR);
          port_val = inb(PORT_ADDR);
          
          /*set r/w permission of  all 65536 ports*/
          
          ret = iopl(0);
          if(ret < 0){
               return 0;
          }
          return 0;

    gcc iopl.c -o iopl
     
    /tmp/iopl 

    setcap cap_sys_rawio=eip /tmp/iopl
     
    /tmp/iopl 
    Current value of port 0x3ff is : 00
    /tmp/iopl 
    Current value of port 0x3ff is : 01
     
     
     
     
     


    /usr/sbin/chroot / /bin/bash

    capset cap_sys_chroot=eip /usr/sbin/chroot
     
     
    /usr/sbin/chroot / /bin/sh

     
     
     
     


    strace -p 1

    setcap cap_sys_ptrace=eip /usr/bin/strace
     
    strace -p 1
    select(11, [10], NULL, NULL, {3, 771381}) = 0 (Timeout)
    time(NULL)                              = 1304348451
    fstat64(10, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
    select(11, [10], NULL, NULL, {5, 0})    = 0 (Timeout)
    time(NULL)                              = 1304348456
     
     
     
     
     
    二十二)CAP_SYS_PACCT 20 (允许配置进程记帐process accounting) 
     
    mkdir /home/test/log/

     
    #include <stdlib.h>
    #include <sys/acct.h>
     
    main()
            int ret;
            if(ret < 0){
               return 0;
            }
            acct(NULL);
            if(ret < 0){
               return 0;
            }
            return 0;
    gcc psacct.c -o psacct
     
    ./psacct 

    setcap cap_sys_psacct /home/test/psacct

     
    ./psacct 
    drwxr-xr-x 2 test test 4096 2011-05-02 13:28 log
    -rw-r--r-- 1 test test   64 2011-05-02 13:25 pacct
    -rw-r--r-- 1 test test  314 2011-05-02 13:31 psacct.c
     
    lastcomm -f /home/test/log/pacct 
    ls                     test     pts/0      0.03 secs Mon May  2 13:33
     
     
     
     
     


     
    setcap cap_sys_admin=eip /bin/hostname
     
    hostname test2
    test2
     
     


    #include <stdlib.h>
    #include <sys/mount.h>
    main ()
            int ret;
            if(ret < 0){
               return 0;
            }
            return 0;

    gcc mounttest.c -o mounttest
    ./mounttest 


    setcap cap_sys_admin=eip /home/test/mounttest 
     
     
    ./mounttest 
    cat /proc/mounts 
    /dev/sda1 /mnt ext3 rw,relatime,errors=remount-ro,barrier=0,data=writeback 0 0

     

    dd if=/dev/zero of=/tmp/testdb bs=10M count=1
    1+0 records out
    /sbin/mkswap /tmp/testdb
    no label, UUID=0ff46dc8-781c-4c3f-81b3-fe860f74793e
    swapon: /tmp/testdb: Operation not permitted
     
    setcap cap_sys_admin /sbin/swapon
     
    /sbin/swapon /tmp/testdb
    /sbin/swapon 
    Filename                                Type            Size    Used    Priority
    /dev/sda6                               partition       7815584 0       -1
    /tmp/testdb                             file            10236   0       -2
    /sbin/swapoff /tmp/testdb
    Filename                                Type            Size    Used    Priority
    /dev/sda6                               partition       7815584 0       -1
    ls -l /sbin/swapoff    
    lrwxrwxrwx 1 root root 6 2009-08-23 07:49 /sbin/swapoff -> swapon
     
     
     
     
     


    #include <unistd.h>
    #include <sys/reboot.h>
    {
        sync(); 
        return reboot(RB_AUTOBOOT);

    gcc reboot1.c -o reboot1
    这时系统没有重启.
     
    echo $?

    setcap cap_sys_boot=eip /home/test/reboot1
     
    reboot1
     

     
     
     

    nice -n -5 ls 

    setcap cap_sys_nice=eip /usr/bin/nice
     
    nice -n -5 ls 
    log  mnt  mount.c  mounttest  pacct  psacct  psacct.c  reboot1  reboot1.c  test
     
    renice -5 2255


     
    2255: old priority 0, new priority -5
     
    chrt -f 50  ls

    setcap  cap_sys_nice=eip  /usr/bin/chrt
     
    chrt -f 50  ls
    log  mnt  setulimit  setulimit.c
     
    taskset -p 1 2255
    sched_setaffinity: Operation not permitted

    setcap  cap_sys_nice=eip  /usr/bin/taskset
     
    taskset -p 1 2255
    pid 2255's new affinity mask: 1
     
     
     
     
     



    #include <signal.h>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <limits.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <sys/resource.h>
     
    main (int argc, char *argv[])
    int r = 0;
    struct rlimit rl;
     
    getrlimit (RLIMIT_STACK,&rl);
     
    (u_long) rl.rlim_max);
     
    rl.rlim_max = rl.rlim_max+1;
    r = setrlimit (RLIMIT_STACK, &rl);
    perror("setrlimit");
    return -1;

    printf("limit set to %ld ", (u_long) rl.rlim_max+1);
    return 0;


    ulimit -H -s 

    ./setulimit    
    setrlimit: Operation not permitted
     
    setcap cap_sys_resource=eip /home/test/setulimit 
     
    ./setulimit 
    limit set to 10485762 
     
     




    Filesystem                   blocks       soft       hard     inodes     soft     hard
      /dev/sda7                         0          3          5          0        0        0
     
    chown -R test.test /export/test/
     
    su - test
    sda7: warning, user block quota exceeded.
    dd: writing `test': Disk quota exceeded
    0+0 records out

    setcap cap_sys_resource=eip /bin/dd
     
     
    su - test
    sda7: warning, user block quota exceeded.
    3+0 records out

     
     
     
     

    date -s 2012-01-01
    Sun Jan  1 00:00:00 EST 2012
     
    setcap cap_sys_time=eip /bin/date
     
    su - test
    Sun Jan  1 00:00:00 EST 2012
    Sun Jan  1 00:00:02 EST 2012
     
     
     
     
     

    程序如下:
    #include <stdio.h>
    #include <unistd.h>
     
    {
      int r;
      r=vhangup();
      if (r){ 
      }
      return 0;


    ./vhup 

    setcap cap_sys_tty_config=eip /home/test/vhup
     
     
    ./vhup 

     
     
     

    mknod /tmp/tnod1 c 1 5


     
    mknod /tmp/tnod1 c 1 5
    ls -l /tmp/tnod1 

     
     
     

           int fcntl(int fd, int cmd, long arg);
     
    F_SETLEASE:根据下面所描述的 arg 参数指定的值来建立或者删除租约:
    F_WRLCK:设置写租约。当文件被另一个进程以读或者写的方式打开时,拥有该租约的当前进程会收到通知
    F_GETLEASE:表明调用进程拥有文件上哪种类型的锁,这需要通过返回值来确定,返回值有三种:F_RDLCK、F_WRLCK和F_UNLCK,分别表明调用进程对文件拥有读租借、写租借或者根本没有租借
    同时,内核会给拥有这个租借锁的进程发信号,告知此事。拥有此租借锁的进程会对该信号进行反馈,它可能会删除这个租借锁,也可能会减短这个租借锁的租约,从而可以使得该文件可以被其他进程所访问。
    不管对该租借锁减短租约或者干脆删除的操作是进程自愿的还是内核强迫的,只要被阻塞的系统调用还没有被发出该调用的进程解除阻塞,那么系统就会允许这个系统调用执行。

    #define _GNU_SOURCE 
     
    #include <unistd.h>
    #include <fcntl.h>
    #include <stdio.h>
    #include <sys/file.h>
    {
            int res;
     
            res = fcntl(fd, F_GETLEASE);
            switch (res) {
                    case F_RDLCK:
                            break;
                    case F_WRLCK:
                            break;
                    case F_UNLCK:
                            break;
                    default:
                            break;
            }

    {
            int fd, res;
     
            fd = open(argv[1], O_RDONLY);
            if (fd == -1) {
                    return 1;
            }
     
            res = fcntl(fd, F_SETLEASE, F_WRLCK);
            if (res == -1) {
                    return 1;
            }
     
            show_lease(fd);
     
            if (flock(fd, LOCK_SH) == -1) {
                    return 1;
            }
     
            show_lease(fd);
     
            return 0;

    gcc fcntl.c -o fcntl
     
    su - test
    Can't set lease: Permission denied
     
    普通用户可以在自己的文件上(owner)建立租借锁.
     
    setcap cap_lease=eip /tmp/fcntl
     
     
    /tmp/fcntl /etc/passwd
    Write lease
     
     
     

    setcap CAP_SETFCAP=eip /usr/sbin/setcap 
     
    setcap CAP_SETPCAP=eip /bin/ls
     
    getcap /bin/ls                

     
    CAP_AUDIT_WRITE
    CAP_MAC_OVERRIDE
    CAP_SYSLOG

     
     
    CAP_CHOWN 0 允许改变文件的所有权 
    CAP_DAC_OVERRIDE 1 忽略对文件的所有DAC访问限制 
    CAP_DAC_READ_SEARCH 2 忽略所有对读、搜索操作的限制 
    CAP_FSETID 4 确保在文件被修改后不修改setuid/setgid位
    CAP_KILL 5 允许对不属于自己的进程发送信号 
    CAP_SETGID 6 允许改变组ID 
    CAP_SETUID 7 允许改变用户ID 
    CAP_LINUX_IMMUTABLE 9 允许修改文件的不可修改(IMMUTABLE)和只添加(APPEND-ONLY)属性 
    CAP_NET_BIND_SERVICE 10 允许绑定到小于1024的端口 
    CAP_NET_BROADCAST 11 允许网络广播和多播访问(未使用) 
    CAP_NET_RAW 13 允许使用原始(raw)套接字 
    CAP_IPC_LOCK 14 允许锁定共享内存片段 
    CAP_IPC_OWNER 15 忽略IPC所有权检查 
    CAP_SYS_MODULE 16 插入和删除内核模块 
    CAP_SYS_RAWIO 17 允许对ioperm/iopl的访问 
    CAP_SYS_CHROOT 18 允许使用chroot()系统调用 
    CAP_SYS_PTRACE 19 允许跟踪任何进程 
    CAP_SYS_PACCT 20 允许配置进程记帐(process accounting) 
    CAP_SYS_BOOT 22 允许重新启动系统 
    CAP_SYS_NICE 23 允许提升优先级,设置其它进程的优先级 
    CAP_SYS_RESOURCE 24 忽略资源限制 
    CAP_SYS_TIME 25 允许改变系统时钟 
    CAP_SYS_TTY_CONFIG 26 允许配置TTY设备 
    CAP_MKNOD 27 允许使用mknod()系统调用 
    CAP_SETFCAP 31 允许在指定的程序上授权能力给其它程序
     
    man capabilities
    linux-2.6.38.5/include/linux/capability.h
  • 相关阅读:
    使你的 Google Summer of Code 建议被接收的5个技巧
    洗牌算法
    自由--永不妥协
    Google Code Jam 2014 总结
    《神经网络与深度学习》(三) 稀疏编码
    《神经网络与深度学习》(二) 常用模型之自编码器
    《神经网络与深度学习》(四) 受限玻尔兹曼机
    《神经网络与深度学习》(五) 卷积神经网络CNN及tensorflow代码实现示例
    《神经网络与深度学习》(一) 感知机、多层神经网络、BP算法、深度学习
    语义哈希(semanticHashing)
  • 原文地址:https://www.cnblogs.com/sky-heaven/p/9481317.html
Copyright © 2011-2022 走看看