Skip to content

Commit 961f0e7

Browse files
authored
Fix ANSI Escape Sequence Injection vulns via DWARF ##vuln
* Reported by @solid-snail via huntrdev * BountyID: 583133af-7ae6-4a21-beef-a4b0182cf82e * Reproducer: dwarf_test_func_patched
1 parent 634219b commit 961f0e7

7 files changed

Lines changed: 107 additions & 23 deletions

File tree

libr/anal/meta.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -111,12 +111,13 @@ static bool meta_set(RAnal *a, RAnalMetaType type, int subtype, ut64 from, ut64
111111
item->subtype = subtype;
112112
item->space = space;
113113
free (item->str);
114-
item->str = str ? strdup (str) : NULL;
115-
if (str && !item->str) {
116-
if (!node) { // If we just created this
117-
free (item);
118-
}
119-
return false;
114+
if (R_STR_ISNOTEMPTY (str)) {
115+
item->str = strdup (str);
116+
// this breaks the `ecHw` command
117+
// (highlights word in current instruction, which uses ansi
118+
// r_str_ansi_strip (item->str);
119+
} else {
120+
item->str = NULL;
120121
}
121122
R_DIRTY (a);
122123
if (!node) {

libr/bin/dwarf.c

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,7 @@ static const ut8 *parse_line_header_source(RBinFile *bf, const ut8 *buf, const u
431431
int i = 0;
432432
size_t count;
433433
const ut8 *tmp_buf = NULL;
434+
char *fn = NULL;
434435

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

465466
for (i = 0; i < 2; i++) {
466467
while (buf + 1 < buf_end) {
467-
const char *filename = (const char *)buf;
468468
size_t maxlen = R_MIN ((size_t) (buf_end - buf - 1), 0xfff);
469469
ut64 id_idx, mod_time, file_len;
470-
size_t len = r_str_nlen (filename, maxlen);
470+
free (fn);
471+
fn = r_str_ndup ((const char *)buf, maxlen);
472+
r_str_ansi_strip (fn);
473+
size_t len = strlen (fn);
471474

472475
if (!len) {
473476
buf++;
@@ -512,7 +515,7 @@ static const ut8 *parse_line_header_source(RBinFile *bf, const ut8 *buf, const u
512515
}
513516

514517
if (hdr->file_names) {
515-
hdr->file_names[count].name = r_str_newf("%s/%s", r_str_get (include_dir), filename);
518+
hdr->file_names[count].name = r_str_newf("%s/%s", r_str_get (include_dir), fn);
516519
hdr->file_names[count].id_idx = id_idx;
517520
hdr->file_names[count].mod_time = mod_time;
518521
hdr->file_names[count].file_len = file_len;
@@ -525,7 +528,8 @@ static const ut8 *parse_line_header_source(RBinFile *bf, const ut8 *buf, const u
525528
}
526529
count++;
527530
if (mode == R_MODE_PRINT && i) {
528-
print (" %d %" PFMT64d " %" PFMT64d " %" PFMT64d " %s\n", entry_index++, id_idx, mod_time, file_len, filename);
531+
print (" %d %" PFMT64d " %" PFMT64d " %" PFMT64d " %s\n",
532+
entry_index++, id_idx, mod_time, file_len, fn);
529533
}
530534
}
531535
if (i == 0) {
@@ -544,6 +548,7 @@ static const ut8 *parse_line_header_source(RBinFile *bf, const ut8 *buf, const u
544548
}
545549

546550
beach:
551+
free (fn);
547552
sdb_free (sdb);
548553

549554
return buf;
@@ -677,7 +682,6 @@ static const ut8 *parse_line_header(
677682

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

@@ -706,7 +710,10 @@ static inline void add_sdb_addrline(Sdb *s, ut64 addr, const char *file, ut64 li
706710
#else
707711
p = file;
708712
#endif
709-
fileline = r_str_newf ("%s|%"PFMT64d, p, line);
713+
char *fileline = r_str_newf ("%s|%"PFMT64d, p, line);
714+
r_str_ansi_strip (fileline);
715+
r_str_replace_ch (fileline, '\n', 0, true);
716+
r_str_replace_ch (fileline, '\t', 0, true);
710717
offset_ptr = sdb_itoa (addr, 16, offset, sizeof (offset));
711718
sdb_add (s, offset_ptr, fileline, 0);
712719
sdb_add (s, fileline, offset_ptr, 0);
@@ -1666,7 +1673,15 @@ static const ut8 *parse_attr_value(const ut8 *obuf, int obuf_len,
16661673
break;
16671674
case DW_FORM_string:
16681675
value->kind = DW_AT_KIND_STRING;
1669-
value->string.content = *buf ? r_str_ndup ((const char *)buf, buf_end - buf) : NULL;
1676+
if (*buf) {
1677+
char *name = r_str_ndup ((const char *)buf, buf_end - buf);
1678+
r_str_ansi_strip (name);
1679+
r_str_replace_ch (name, '\n', 0, true);
1680+
r_str_replace_ch (name, '\t', 0, true);
1681+
value->string.content = name;
1682+
} else {
1683+
value->string.content = NULL;
1684+
}
16701685
if (value->string.content) {
16711686
buf += strlen (value->string.content) + 1;
16721687
}
@@ -1711,8 +1726,15 @@ static const ut8 *parse_attr_value(const ut8 *obuf, int obuf_len,
17111726
value->kind = DW_AT_KIND_STRING;
17121727
value->string.offset = dwarf_read_offset (hdr->is_64bit, &buf, buf_end);
17131728
if (debug_str && value->string.offset < debug_str_len) {
1714-
const char *ds = (const char *)(debug_str + value->string.offset);
1715-
value->string.content = strdup (ds); // r_str_ndup (ds, debug_str_len - value->string.offset);
1729+
char *ds = r_str_ndup ((const char *)(debug_str + value->string.offset), debug_str_len);
1730+
if (ds) {
1731+
r_str_ansi_strip (ds);
1732+
r_str_replace_ch (ds, '\n', 0, true);
1733+
r_str_replace_ch (ds, '\t', 0, true);
1734+
value->string.content = ds;
1735+
} else {
1736+
value->string.content = NULL;
1737+
}
17161738
} else {
17171739
value->string.content = NULL; // Means malformed DWARF, should we print error message?
17181740
}
@@ -1903,8 +1925,11 @@ static const ut8 *parse_die(const ut8 *buf, const ut8 *buf_end, RBinDwarfAbbrevD
19031925
// Or atleast it needs to rework becase there will be
19041926
// more comp units -> more comp dirs and only the last one will be kept
19051927
if (attribute->attr_name == DW_AT_comp_dir && is_valid_string_form) {
1906-
const char *name = attribute->string.content;
1907-
sdb_set (sdb, "DW_AT_comp_dir", name, 0);
1928+
char *name = strdup (attribute->string.content);
1929+
r_str_ansi_strip (name);
1930+
r_str_replace_ch (name, '\n', 0, true);
1931+
r_str_replace_ch (name, '\t', 0, true);
1932+
sdb_set_owned (sdb, "DW_AT_comp_dir", name, 0);
19081933
}
19091934
die->count++;
19101935
}

libr/cons/hud.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* radare - LGPL - Copyright 2008-2021 - pancake */
1+
/* radare - LGPL - Copyright 2008-2023 - pancake */
22

33
#include <r_cons.h>
44
#include <ctype.h>
@@ -9,6 +9,7 @@
99
R_API char *r_cons_hud_file(const char *f) {
1010
char *s = r_file_slurp (f, NULL);
1111
if (s) {
12+
r_str_ansi_strip (s);
1213
char *ret = r_cons_hud_string (s);
1314
free (s);
1415
return ret;
@@ -29,6 +30,7 @@ R_API char *r_cons_hud_line_string(const char *s) {
2930
}
3031
r_str_replace_ch (o, '\r', 0, true);
3132
r_str_replace_ch (o, '\t', 0, true);
33+
r_str_ansi_strip (o);
3234
RList *fl = r_list_new ();
3335
int i;
3436
if (!fl) {
@@ -66,6 +68,7 @@ R_API char *r_cons_hud_string(const char *s) {
6668
if (!o) {
6769
return NULL;
6870
}
71+
r_str_ansi_strip (o);
6972
r_str_replace_ch (o, '\r', 0, true);
7073
r_str_replace_ch (o, '\t', 0, true);
7174
RList *fl = r_list_new ();

libr/core/cmd_meta.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -539,10 +539,10 @@ static int cmd_meta_comment(RCore *core, const char *input) {
539539
break;
540540
case '!':
541541
{
542-
char *out;
543542
const char *comment = r_meta_get_string (core->anal, R_META_TYPE_COMMENT, addr);
544-
out = r_core_editor (core, NULL, comment);
543+
char *out = r_core_editor (core, NULL, comment);
545544
if (out) {
545+
r_str_ansi_strip (out);
546546
//r_meta_set (core->anal->meta, R_META_TYPE_COMMENT, addr, 0, out);
547547
r_core_cmdf (core, "CC-@0x%08"PFMT64x, addr);
548548
//r_meta_del (core->anal->meta, input[0], addr, addr+1);
@@ -560,6 +560,7 @@ static int cmd_meta_comment(RCore *core, const char *input) {
560560
char *text;
561561
char *nc = strdup (newcomment);
562562
r_str_unescape (nc);
563+
r_str_ansi_strip (nc);
563564
if (comment) {
564565
text = malloc (strlen (comment) + strlen (newcomment) + 2);
565566
if (text) {

libr/core/cmd_print.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* radare - LGPL - Copyright 2009-2022 - pancake */
1+
/* radare - LGPL - Copyright 2009-2023 - pancake */
22

33
#include <r_core.h>
44
#include <limits.h>

libr/util/str.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1957,14 +1957,16 @@ R_API size_t r_str_ansi_nlen(const char *str, size_t slen) {
19571957
}
19581958

19591959
// remove ansi escape codes from string, decolorizing it
1960+
// TODO : optimize by just using two counter variables instead of strcpy()
19601961
R_API size_t r_str_ansi_strip(char *str) {
19611962
size_t i = 0;
19621963
while (str[i]) {
19631964
size_t chlen = __str_ansi_length (str + i);
19641965
if (chlen > 1) {
1965-
r_str_cpy (str + i + 1, str + i + chlen);
1966+
r_str_cpy (str + i, str + i + chlen);
1967+
} else {
1968+
i++;
19661969
}
1967-
i++;
19681970
}
19691971
return i;
19701972
}

test/db/cmd/dwarf

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,55 @@
1+
NAME="ansi injection via dwarf"
2+
FILE=bins/elf/dwarf_test_func_patched
3+
ARGS=-AA
4+
CMDS=<<EOF
5+
CL
6+
xc
7+
EOF
8+
EXPECT=<<EOF
9+
file: /_test.c
10+
line: 5
11+
addr: 0x00001159
12+
file: /_test.c
13+
line: 11
14+
addr: 0x00001184
15+
file: /_test.c
16+
line: 6
17+
addr: 0x00001165
18+
file: /_test.c
19+
line: 11
20+
addr: 0x00001186
21+
file: /_test.c
22+
line: 9
23+
addr: 0x00001170
24+
file: /_test.c
25+
line: 8
26+
addr: 0x00001168
27+
file: /_test.c
28+
line: 4
29+
addr: 0x00001149
30+
file: /_test.c
31+
line: 10
32+
addr: 0x0000117f
33+
- offset - 6061 6263 6465 6667 6869 6A6B 6C6D 6E6F 0123456789ABCDEF comment
34+
0x00001060 f30f 1efa 31ed 4989 d15e 4889 e248 83e4 ....1.I..^H..H.. ; rip ; [16] -r-x section size 294 named .text ; arg3
35+
0x00001070 f050 5445 31c0 31c9 488d 3de9 0000 00ff .PTE1.1.H.=.....
36+
0x00001080 1553 2f00 00f4 662e 0f1f 8400 0000 0000 .S/...f.........
37+
0x00001090 488d 3d79 2f00 0048 8d05 722f 0000 4839 H.=y/..H..r/..H9 ; sym.deregister_tm_clones
38+
0x000010a0 f874 1548 8b05 362f 0000 4885 c074 09ff .t.H..6/..H..t..
39+
0x000010b0 e00f 1f80 0000 0000 c30f 1f80 0000 0000 ................
40+
0x000010c0 488d 3d49 2f00 0048 8d35 422f 0000 4829 H.=I/..H.5B/..H) ; sym.register_tm_clones
41+
0x000010d0 fe48 89f0 48c1 ee3f 48c1 f803 4801 c648 .H..H..?H...H..H
42+
0x000010e0 d1fe 7414 488b 0505 2f00 0048 85c0 7408 ..t.H.../..H..t.
43+
0x000010f0 ffe0 660f 1f44 0000 c30f 1f80 0000 0000 ..f..D..........
44+
0x00001100 f30f 1efa 803d 052f 0000 0075 2b55 4883 .....=./...u+UH. ; sym.__do_global_dtors_aux
45+
0x00001110 3de2 2e00 0000 4889 e574 0c48 8b3d e62e =.....H..t.H.=..
46+
0x00001120 0000 e819 ffff ffe8 64ff ffff c605 dd2e ........d.......
47+
0x00001130 0000 015d c30f 1f00 c30f 1f80 0000 0000 ...]............
48+
0x00001140 f30f 1efa e977 ffff fff3 0f1e fa55 4889 .....w.......UH. ; sym.frame_dummy ; dbg._func ; void _func(char * msg);
49+
0x00001150 e548 83ec 1048 897d f848 8b45 f848 89c7 .H...H.}.H.E.H.. ; arg1 ; const char *s
50+
EOF
51+
RUN
52+
153
NAME="open companion file for macho dwarf"
254
FILE=bins/mach0/dwarf/a.out
355
CMDS=<<EOF

0 commit comments

Comments
 (0)