黑客
登录
客服
网络安全,渗透测试

GEEKPWN2020-云安全挑战赛决赛-baby_kernel题解

日期:2020/11/11 10:39:08

GEEKPWN2020-云安全挑战赛决赛-baby_kernel题解

前言

上周参加了酷炫的GEEKPWN大会,比赛时未能解出这道题目,因为是bpf相关的洞,之前也有一点了解,赛后七哥不厌其烦地给我指导,最终成功解出,非常感谢sunichi师傅的帮助。本文相关文件在这里

漏洞挖掘

附件里贴心地给了source源码和linux-5.8.6的源码,我们拿beyond compare比较一下两个项目文件夹,可以找到不同的文件,拿vscode比较一下具体地文件,即可看到diff的结果.可以看到在verifier.c文件中的scalar_min_max_add函数中缺失了溢出检查。

具体看一下此处的代码和调用,只跟到check_alu_op就差不多了,因为之前我们分析bpf漏洞的时候知道核心检查函数do_check中会调用此函数。因此最后的漏洞调用链为:do_check->check_alu_op->adjust_reg_min_max_vals->adjust_scalar_min_max_vals->scalar_min_max_add

//verifier.c
static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env,
                      struct bpf_insn *insn,
                      struct bpf_reg_state *dst_reg,
                      struct bpf_reg_state src_reg)
{
    switch (opcode) {
    case BPF_ADD:
        ret = sanitize_val_alu(env, insn);
        if (ret < 0) {
            verbose(env, "R%d tried to add from different pointers or scalars\n", dst);
            return ret;
        }
        scalar32_min_max_add(dst_reg, &src_reg);
        scalar_min_max_add(dst_reg, &src_reg);
        dst_reg->var_off = tnum_add(dst_reg->var_off, src_reg.var_off);
        break;
        //...
    }
}
//
static int adjust_reg_min_max_vals(struct bpf_verifier_env *env,
                   struct bpf_insn *insn)
{
    //...
    return adjust_scalar_min_max_vals(env, insn, dst_reg, *src_reg);
}
//
/* check validity of 32-bit and 64-bit arithmetic operations */
static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
{
    //...
    else {  /* all other ALU ops: and, sub, xor, add, ... */

        if (BPF_SRC(insn->code) == BPF_X) {
            if (insn->imm != 0 || insn->off != 0) {
                verbose(env, "BPF_ALU uses reserved fields\n");
                return -EINVAL;
            }
            /* check src1 operand */
            err = check_reg_arg(env, insn->src_reg, SRC_OP);
            if (err)
                return err;
        } else {
            if (insn->src_reg != BPF_REG_0 || insn->off != 0) {
                verbose(env, "BPF_ALU uses reserved fields\n");
                return -EINVAL;
            }
        }

        /* check src2 operand */
        err = check_reg_arg(env, insn->dst_reg, SRC_OP);
        if (err)
            return err;

        if ((opcode == BPF_MOD || opcode == BPF_DIV) &&
            BPF_SRC(insn->code) == BPF_K && insn->imm == 0) {
            verbose(env, "div by zero\n");
            return -EINVAL;
        }

        if ((opcode == BPF_LSH || opcode == BPF_RSH ||
             opcode == BPF_ARSH) && BPF_SRC(insn->code) == BPF_K) {
            int size = BPF_CLASS(insn->code) == BPF_ALU64 ? 64 : 32;

            if (insn->imm < 0 || insn->imm >= size) {
                verbose(env, "invalid shift %d\n", insn->imm);
                return -EINVAL;
            }
        }

        /* check dest operand */
        err = check_reg_arg(env, insn->dst_reg, DST_OP_NO_MARK);
        if (err)
            return err;

        return adjust_reg_min_max_vals(env, insn);
    }
}

最新教程

最新文章

推荐文章

热门文章

黑客技术 黑客软件 黑客教程 黑客书籍

关于我们 | 免责声明 | 学员守则 | 广告服务 | 联系我们

©2013-2021 xf1433.com 版权所有

本站资源仅供用于学习和交流,请遵循相关法律法规