Skip to content

Commit

Permalink
Fix ANSI Escape Sequence Injection vulns via DWARF ##vuln
Browse files Browse the repository at this point in the history
* Reported by @solid-snail via huntrdev
* BountyID: 583133af-7ae6-4a21-beef-a4b0182cf82e
* Reproducer: dwarf_test_func_patched
  • Loading branch information
trufae committed Jan 6, 2023
1 parent 634219b commit 961f0e7
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 23 deletions.
13 changes: 7 additions & 6 deletions libr/anal/meta.c
Expand Up @@ -111,12 +111,13 @@ static bool meta_set(RAnal *a, RAnalMetaType type, int subtype, ut64 from, ut64
item->subtype = subtype;
item->space = space;
free (item->str);
item->str = str ? strdup (str) : NULL;
if (str && !item->str) {
if (!node) { // If we just created this
free (item);
}
return false;
if (R_STR_ISNOTEMPTY (str)) {
item->str = strdup (str);
// this breaks the `ecHw` command
// (highlights word in current instruction, which uses ansi
// r_str_ansi_strip (item->str);
} else {
item->str = NULL;
}
R_DIRTY (a);
if (!node) {
Expand Down
47 changes: 36 additions & 11 deletions libr/bin/dwarf.c
Expand Up @@ -431,6 +431,7 @@ static const ut8 *parse_line_header_source(RBinFile *bf, const ut8 *buf, const u
int i = 0;
size_t count;
const ut8 *tmp_buf = NULL;
char *fn = NULL;

if (mode == R_MODE_PRINT) {
print (" The Directory Table:\n");
Expand Down Expand Up @@ -464,10 +465,12 @@ static const ut8 *parse_line_header_source(RBinFile *bf, const ut8 *buf, const u

for (i = 0; i < 2; i++) {
while (buf + 1 < buf_end) {
const char *filename = (const char *)buf;
size_t maxlen = R_MIN ((size_t) (buf_end - buf - 1), 0xfff);
ut64 id_idx, mod_time, file_len;
size_t len = r_str_nlen (filename, maxlen);
free (fn);
fn = r_str_ndup ((const char *)buf, maxlen);
r_str_ansi_strip (fn);
size_t len = strlen (fn);

if (!len) {
buf++;
Expand Down Expand Up @@ -512,7 +515,7 @@ static const ut8 *parse_line_header_source(RBinFile *bf, const ut8 *buf, const u
}

if (hdr->file_names) {
hdr->file_names[count].name = r_str_newf("%s/%s", r_str_get (include_dir), filename);
hdr->file_names[count].name = r_str_newf("%s/%s", r_str_get (include_dir), fn);
hdr->file_names[count].id_idx = id_idx;
hdr->file_names[count].mod_time = mod_time;
hdr->file_names[count].file_len = file_len;
Expand All @@ -525,7 +528,8 @@ static const ut8 *parse_line_header_source(RBinFile *bf, const ut8 *buf, const u
}
count++;
if (mode == R_MODE_PRINT && i) {
print (" %d %" PFMT64d " %" PFMT64d " %" PFMT64d " %s\n", entry_index++, id_idx, mod_time, file_len, filename);
print (" %d %" PFMT64d " %" PFMT64d " %" PFMT64d " %s\n",
entry_index++, id_idx, mod_time, file_len, fn);
}
}
if (i == 0) {
Expand All @@ -544,6 +548,7 @@ static const ut8 *parse_line_header_source(RBinFile *bf, const ut8 *buf, const u
}

beach:
free (fn);
sdb_free (sdb);

return buf;
Expand Down Expand Up @@ -677,7 +682,6 @@ static const ut8 *parse_line_header(

static inline void add_sdb_addrline(Sdb *s, ut64 addr, const char *file, ut64 line, int mode, PrintfCallback print) {
const char *p;
char *fileline;
char offset[SDB_NUM_BUFSZ];
char *offset_ptr;

Expand Down Expand Up @@ -706,7 +710,10 @@ static inline void add_sdb_addrline(Sdb *s, ut64 addr, const char *file, ut64 li
#else
p = file;
#endif
fileline = r_str_newf ("%s|%"PFMT64d, p, line);
char *fileline = r_str_newf ("%s|%"PFMT64d, p, line);
r_str_ansi_strip (fileline);
r_str_replace_ch (fileline, '\n', 0, true);
r_str_replace_ch (fileline, '\t', 0, true);
offset_ptr = sdb_itoa (addr, 16, offset, sizeof (offset));
sdb_add (s, offset_ptr, fileline, 0);
sdb_add (s, fileline, offset_ptr, 0);
Expand Down Expand Up @@ -1666,7 +1673,15 @@ static const ut8 *parse_attr_value(const ut8 *obuf, int obuf_len,
break;
case DW_FORM_string:
value->kind = DW_AT_KIND_STRING;
value->string.content = *buf ? r_str_ndup ((const char *)buf, buf_end - buf) : NULL;
if (*buf) {
char *name = r_str_ndup ((const char *)buf, buf_end - buf);
r_str_ansi_strip (name);
r_str_replace_ch (name, '\n', 0, true);
r_str_replace_ch (name, '\t', 0, true);
value->string.content = name;
} else {
value->string.content = NULL;
}
if (value->string.content) {
buf += strlen (value->string.content) + 1;
}
Expand Down Expand Up @@ -1711,8 +1726,15 @@ static const ut8 *parse_attr_value(const ut8 *obuf, int obuf_len,
value->kind = DW_AT_KIND_STRING;
value->string.offset = dwarf_read_offset (hdr->is_64bit, &buf, buf_end);
if (debug_str && value->string.offset < debug_str_len) {
const char *ds = (const char *)(debug_str + value->string.offset);
value->string.content = strdup (ds); // r_str_ndup (ds, debug_str_len - value->string.offset);
char *ds = r_str_ndup ((const char *)(debug_str + value->string.offset), debug_str_len);
if (ds) {
r_str_ansi_strip (ds);
r_str_replace_ch (ds, '\n', 0, true);
r_str_replace_ch (ds, '\t', 0, true);
value->string.content = ds;
} else {
value->string.content = NULL;
}
} else {
value->string.content = NULL; // Means malformed DWARF, should we print error message?
}
Expand Down Expand Up @@ -1903,8 +1925,11 @@ static const ut8 *parse_die(const ut8 *buf, const ut8 *buf_end, RBinDwarfAbbrevD
// Or atleast it needs to rework becase there will be
// more comp units -> more comp dirs and only the last one will be kept
if (attribute->attr_name == DW_AT_comp_dir && is_valid_string_form) {
const char *name = attribute->string.content;
sdb_set (sdb, "DW_AT_comp_dir", name, 0);
char *name = strdup (attribute->string.content);
r_str_ansi_strip (name);
r_str_replace_ch (name, '\n', 0, true);
r_str_replace_ch (name, '\t', 0, true);
sdb_set_owned (sdb, "DW_AT_comp_dir", name, 0);
}
die->count++;
}
Expand Down
5 changes: 4 additions & 1 deletion libr/cons/hud.c
@@ -1,4 +1,4 @@
/* radare - LGPL - Copyright 2008-2021 - pancake */
/* radare - LGPL - Copyright 2008-2023 - pancake */

#include <r_cons.h>
#include <ctype.h>
Expand All @@ -9,6 +9,7 @@
R_API char *r_cons_hud_file(const char *f) {
char *s = r_file_slurp (f, NULL);
if (s) {
r_str_ansi_strip (s);
char *ret = r_cons_hud_string (s);
free (s);
return ret;
Expand All @@ -29,6 +30,7 @@ R_API char *r_cons_hud_line_string(const char *s) {
}
r_str_replace_ch (o, '\r', 0, true);
r_str_replace_ch (o, '\t', 0, true);
r_str_ansi_strip (o);
RList *fl = r_list_new ();
int i;
if (!fl) {
Expand Down Expand Up @@ -66,6 +68,7 @@ R_API char *r_cons_hud_string(const char *s) {
if (!o) {
return NULL;
}
r_str_ansi_strip (o);
r_str_replace_ch (o, '\r', 0, true);
r_str_replace_ch (o, '\t', 0, true);
RList *fl = r_list_new ();
Expand Down
5 changes: 3 additions & 2 deletions libr/core/cmd_meta.c
Expand Up @@ -539,10 +539,10 @@ static int cmd_meta_comment(RCore *core, const char *input) {
break;
case '!':
{
char *out;
const char *comment = r_meta_get_string (core->anal, R_META_TYPE_COMMENT, addr);
out = r_core_editor (core, NULL, comment);
char *out = r_core_editor (core, NULL, comment);
if (out) {
r_str_ansi_strip (out);
//r_meta_set (core->anal->meta, R_META_TYPE_COMMENT, addr, 0, out);
r_core_cmdf (core, "CC-@0x%08"PFMT64x, addr);
//r_meta_del (core->anal->meta, input[0], addr, addr+1);
Expand All @@ -560,6 +560,7 @@ static int cmd_meta_comment(RCore *core, const char *input) {
char *text;
char *nc = strdup (newcomment);
r_str_unescape (nc);
r_str_ansi_strip (nc);
if (comment) {
text = malloc (strlen (comment) + strlen (newcomment) + 2);
if (text) {
Expand Down
2 changes: 1 addition & 1 deletion libr/core/cmd_print.c
@@ -1,4 +1,4 @@
/* radare - LGPL - Copyright 2009-2022 - pancake */
/* radare - LGPL - Copyright 2009-2023 - pancake */

#include <r_core.h>
#include <limits.h>
Expand Down
6 changes: 4 additions & 2 deletions libr/util/str.c
Expand Up @@ -1957,14 +1957,16 @@ R_API size_t r_str_ansi_nlen(const char *str, size_t slen) {
}

// remove ansi escape codes from string, decolorizing it
// TODO : optimize by just using two counter variables instead of strcpy()
R_API size_t r_str_ansi_strip(char *str) {
size_t i = 0;
while (str[i]) {
size_t chlen = __str_ansi_length (str + i);
if (chlen > 1) {
r_str_cpy (str + i + 1, str + i + chlen);
r_str_cpy (str + i, str + i + chlen);
} else {
i++;
}
i++;
}
return i;
}
Expand Down
52 changes: 52 additions & 0 deletions test/db/cmd/dwarf
@@ -1,3 +1,55 @@
NAME="ansi injection via dwarf"
FILE=bins/elf/dwarf_test_func_patched
ARGS=-AA
CMDS=<<EOF
CL
xc
EOF
EXPECT=<<EOF
file: /_test.c
line: 5
addr: 0x00001159
file: /_test.c
line: 11
addr: 0x00001184
file: /_test.c
line: 6
addr: 0x00001165
file: /_test.c
line: 11
addr: 0x00001186
file: /_test.c
line: 9
addr: 0x00001170
file: /_test.c
line: 8
addr: 0x00001168
file: /_test.c
line: 4
addr: 0x00001149
file: /_test.c
line: 10
addr: 0x0000117f
- offset - 6061 6263 6465 6667 6869 6A6B 6C6D 6E6F 0123456789ABCDEF comment
0x00001060 f30f 1efa 31ed 4989 d15e 4889 e248 83e4 ....1.I..^H..H.. ; rip ; [16] -r-x section size 294 named .text ; arg3
0x00001070 f050 5445 31c0 31c9 488d 3de9 0000 00ff .PTE1.1.H.=.....
0x00001080 1553 2f00 00f4 662e 0f1f 8400 0000 0000 .S/...f.........
0x00001090 488d 3d79 2f00 0048 8d05 722f 0000 4839 H.=y/..H..r/..H9 ; sym.deregister_tm_clones
0x000010a0 f874 1548 8b05 362f 0000 4885 c074 09ff .t.H..6/..H..t..
0x000010b0 e00f 1f80 0000 0000 c30f 1f80 0000 0000 ................
0x000010c0 488d 3d49 2f00 0048 8d35 422f 0000 4829 H.=I/..H.5B/..H) ; sym.register_tm_clones
0x000010d0 fe48 89f0 48c1 ee3f 48c1 f803 4801 c648 .H..H..?H...H..H
0x000010e0 d1fe 7414 488b 0505 2f00 0048 85c0 7408 ..t.H.../..H..t.
0x000010f0 ffe0 660f 1f44 0000 c30f 1f80 0000 0000 ..f..D..........
0x00001100 f30f 1efa 803d 052f 0000 0075 2b55 4883 .....=./...u+UH. ; sym.__do_global_dtors_aux
0x00001110 3de2 2e00 0000 4889 e574 0c48 8b3d e62e =.....H..t.H.=..
0x00001120 0000 e819 ffff ffe8 64ff ffff c605 dd2e ........d.......
0x00001130 0000 015d c30f 1f00 c30f 1f80 0000 0000 ...]............
0x00001140 f30f 1efa e977 ffff fff3 0f1e fa55 4889 .....w.......UH. ; sym.frame_dummy ; dbg._func ; void _func(char * msg);
0x00001150 e548 83ec 1048 897d f848 8b45 f848 89c7 .H...H.}.H.E.H.. ; arg1 ; const char *s
EOF
RUN

NAME="open companion file for macho dwarf"
FILE=bins/mach0/dwarf/a.out
CMDS=<<EOF
Expand Down

0 comments on commit 961f0e7

Please sign in to comment.