Trend Micro Discovers Android Vulnerability that Can Lead to Exposure of Device Memory Content
We have discovered a vulnerability in the integrated Android debugger Debuggerd that can be used to expose the contents of the device’s memory in devices running Ice Cream Sandwich to Lollipop.
A specially crafted ELF (Executable and Linkable Format) file can crash the debugger and expose the memory content via tombstone files and corresponding logd log files. This information can be used in denial of service attacks, as well as to help bypass ASLR for arbitrary code execution. By itself, the vulnerability cannot be used for code execution. However, the information leaked here may be combined with other flaws for that purpose.
This vulnerability can be exploited by a malicious or repackaged app downloaded onto the device, although the impact would be relatively limited (as no code execution is possible by itself). No malicious code can be executed if this vulnerability is exploited. This vulnerability is present from Android 4.0 (Ice Cream Sandwich) up to Lollipop (5.x). However, the vulnerability has been resolved in the next version, Android M.
Vulnerability Description
The root cause of the vulnerability is that Debuggerd will use sym->st_name as an offset for a string copy command without any error checking. This value can be easily controlled by the malformed ELF file in such a way that if the offset value points to inaccessible memory, Debuggerd will crash. Repeated crashes would cause a denial-of-service attack; it would disable other normal crashes which cannot be connected to Debuggerd anymore. A carefully designed offset will cause Debuggerd will expose the corresponding memory contents to related dump and log files.
For Android 5.0-5.1:, the vulnerability can be found in external/libunwind/src/elfxx.c:
126 for (sym = symtab;
127 sym < symtab_end;
128 sym = (Elf_W (Sym) *) ((char *) sym + syment_size))
129 {
130 if (ELF_W (ST_TYPE) (sym->st_info) == STT_FUNC
131 && sym->st_shndx != SHN_UNDEF)
132 {
133 if (tdep_get_func_addr (as, sym->st_value, &val) < 0)
134 continue;
135 if (sym->st_shndx != SHN_ABS)
136 val += load_offset;
137 Debug (16, "0x%016lx info=0x%02x %s\n",
138 (long) val, sym->st_info, strtab + sym->st_name);
139
140 /* ANDROID support update */
141 if ((Elf_W (Addr)) (ip - val) < *min_dist
142 && (Elf_W (Addr)) (ip - val) < sym->st_size)
143 /* End of ANDROID update */
144 {
145 *min_dist = (Elf_W (Addr)) (ip - val);
146 strncpy (buf, strtab + sym->st_name, buf_len); //the address st_name may be easily controlled by malformed ELF
147 buf[buf_len - 1] = '';
148 ret = (strlen (strtab + sym->st_name) >= buf_len
149 ? -UNW_ENOMEM : 0);
150 }
151 }
152 }
To reproduce the vulnerability, an ELF file whose main function directly crashes can be used. This can be done by modifying the symbol offset. After the ELF is embedded into an APK, the former will be executed in a loop. This will trigger the vulnerability, as seen below:
Figure 1. Trigger of vulnerability
Similar issues are also found in older versions of Android (specifically, 4.x versions such as Ice Cream Sandwich, Jelly Bean, and KitKat). These do not use the libunwind third-party library. In Android 4.0:, the vulnerability is in system/core/debuggerd/symbol_table.c:
155 int j = 0;
156 if (dynsym_idx != -1) {
157 // …and populate them
158 for(i = 0; i < dynnumsyms; i++) {
159 if(dynsyms[i].st_shndx != SHN_UNDEF) {
160 table->symbols[j].name = strdup(dynstr + dynsyms[i].st_name);//st_name is not carefully checked before using
161 table->symbols[j].addr = dynsyms[i].st_value;
162 table->symbols[j].size = dynsyms[i].st_size;
163 XLOG2(“name: %s, addr: %x, size: %x\n”,
164 table->symbols[j].name, table->symbols[j].addr, table->symbols[j].size);
165 j++;
166 }
167 }
168 }
169
170 if (sym_idx != -1) {
171 // …and populate them
172 for(i = 0; i < numsyms; i++) {
173 if((syms[i].st_shndx != SHN_UNDEF) &&
174 (strlen(str+syms[i].st_name)) &&
175 (syms[i].st_value != 0) && (syms[i].st_size != 0)) {
176 table->symbols[j].name = strdup(str + syms[i].st_name);//st_name is not checked before using
177 table->symbols[j].addr = syms[i].st_value;
178 table->symbols[j].size = syms[i].st_size;
179 XLOG2(“name: %s, addr: %x, size: %x\n”,
180 table->symbols[j].name, table->symbols[j].addr, table->symbols[j].size);
181 j++;
182 }
183 }
184 }
In Android 4.1-4.4, the vulnerability is in system/core/libcorkscrew/symbol_table.c:
150 size_t symbol_index = 0;
151 if (dynsym_idx != -1) {
152 // …and populate them
153 for (int i = 0; i < dynnumsyms; i++) {
154 if (dynsyms[i].st_shndx != SHN_UNDEF) {
155 table->symbols[symbol_index].name = strdup(dynstr + dynsyms[i].st_name);//st_name is not checked before using
156 table->symbols[symbol_index].start = dynsyms[i].st_value;
157 table->symbols[symbol_index].end = dynsyms[i].st_value + dynsyms[i].st_size;
158 ALOGV(” [%d] ‘%s’ 0x%08x-0x%08x (DYNAMIC)”,
159 symbol_index, table->symbols[symbol_index].name,
160 table->symbols[symbol_index].start, table->symbols[symbol_index].end);
161 symbol_index += 1;
162 }
163 }
164 }
165
166 if (sym_idx != -1) {
167 // …and populate them
168 for (int i = 0; i < numsyms; i++) {
169 if (syms[i].st_shndx != SHN_UNDEF
170 && str[syms[i].st_name]
171 && syms[i].st_value
172 && syms[i].st_size) {
173 table->symbols[symbol_index].name = strdup(str + syms[i].st_name);//st_name is type of uint32_t not be checked
174 table->symbols[symbol_index].start = syms[i].st_value;
175 table->symbols[symbol_index].end = syms[i].st_value + syms[i].st_size;
176 ALOGV(” [%d] ‘%s’ 0x%08x-0x%08x”,
177 symbol_index, table->symbols[symbol_index].name,
178 table->symbols[symbol_index].start, table->symbols[symbol_index].end);
179 symbol_index += 1;
180 }
181}
182 }
Figure 2. Memory exposure snapshot
We first reported this vulnerability to Google on April 27 of this year; they acknowledged the issue the following day and assigned it a low severity rating. A fix was included in the Android Open Source Project (AOSP) code on May 15.
Post from: Trendlabs Security Intelligence Blog – by Trend Micro
Trend Micro Discovers Android Vulnerability that Can Lead to Exposure of Device Memory Content