Commit message: More fixes for the CVE-2019-14745
CVE: CVE-2019-16718
CWE: CWE-78
Vulnerability description: In radare2 before 3.9.0, a command injection vulnerability exists in bin_symbols() in libr/core/cbin.c. By using a crafted executable file, it's possible to execute arbitrary shell commands with the permissions of the victim. This vulnerability is due to an insufficient fix for CVE-2019-14745 and improper handling of symbol names embedded in executables.

Project: radare2

static int bin_fields(RCore *r, int mode, int va) {
	RList *fields;
	RListIter *iter;
	RBinField *field;
	int i = 0;
	RBin *bin = r->bin;

	if (!(fields = r_bin_get_fields (bin))) {
		return false;
	}
	if (IS_MODE_JSON (mode)) {
		r_cons_print ("[");
	} else if (IS_MODE_RAD (mode)) {
		r_cons_println ("fs header");
	} else if (IS_MODE_NORMAL (mode)) {
		r_cons_println ("[Header fields]");
	}
	r_list_foreach (fields, iter, field) {
		ut64 addr = rva (bin, field->paddr, field->vaddr, va);

		if (IS_MODE_RAD (mode)) {
			char *n = __filterQuotedShell (field->name);
			r_name_filter (n, -1);
			r_cons_printf ("\"f header.%s 1 0x%08"PFMT64x"\"\n", n, addr);
			if (field->comment && *field->comment) {
				char *e = sdb_encode ((const ut8*)field->comment, -1);
				r_cons_printf ("CCu %s @ 0x%"PFMT64x"\n", e, addr);
				free (e);
				char *f = __filterShell (field->format);
				r_cons_printf ("Cf %d .%s @ 0x%"PFMT64x"\n", field->size, f, addr);
				free (f);
			}
			if (field->format && *field->format) {
				r_cons_printf ("pf.%s %s\n", n, field->format);
			}
			free (n);
		} else if (IS_MODE_JSON (mode)) {
			r_cons_printf ("%s{\"name\":\"%s\","
				"\"vaddr\":%"PFMT64d","
				"\"paddr\":%"PFMT64d,
				iter->p? ",": "",
				field->name,
				field->vaddr,
				field->paddr
				);
			if (field->comment && *field->comment) {
				r_cons_printf (",\"comment\":\"%s\"", field->comment);
			}
			if (field->format && *field->format) {
				r_cons_printf (",\"format\":\"%s\"", field->format);
			}
			char *o = r_core_cmd_strf (r, "pfj.%s@0x%"PFMT64x, field->format, field->vaddr);
			if (o && *o) {
				r_cons_printf (",\"pf\":%s", o);
			}
			free (o);
			r_cons_printf ("}");
		} else if (IS_MODE_NORMAL (mode)) {
			const bool haveComment = (field->comment && *field->comment);
			r_cons_printf ("0x%08"PFMT64x" 0x%08"PFMT64x" %s%s%s\n",
				field->vaddr, field->paddr, field->name,
				haveComment? "; ": "",
				haveComment? field->comment: "");
		}
		i++;
	}
	if (IS_MODE_JSON (mode)) {
		r_cons_printf ("]");
	} else if (IS_MODE_NORMAL (mode)) {
		r_cons_printf ("\n%i fields\n", i);
	}

	return true;
}

Project: radare2
File: cbin.c

static ut8 bin_reloc_size(RBinReloc *reloc) {
#define CASE(T) case R_BIN_RELOC_ ## T: return (T) / 8
	switch (reloc->type) {
		CASE(8);
		CASE(16);
		CASE(32);
		CASE(64);
	}
	return 0;
#undef CASE
}

Project: radare2
File: cbin.c

static int bin_resources(RCore *r, int mode) {
	const RBinInfo *info = r_bin_get_info (r->bin);
	if (!info || !info->rclass) {
		return false;
	}
	if (!strncmp ("pe", info->rclass, 2)) {
		bin_pe_resources (r, mode);
	} else {
		bin_no_resources (r, mode);
	}
	return true;
}

Project: radare2
File: cbin.c

static void classdump_java(RCore *r, RBinClass *c) {
	RBinField *f;
	RListIter *iter2, *iter3;
	RBinSymbol *sym;
	char *pn = strdup (c->name);
	char *cn = (char *)r_str_rchr (pn, NULL, '/');
	if (cn) {
		*cn = 0;
		cn++;
		r_str_replace_char (pn, '/', '.');
	}
	r_cons_printf ("package %s;\n\n", pn);
	r_cons_printf ("public class %s {\n", cn);
	free (pn);
	r_list_foreach (c->fields, iter2, f) {
		if (f->name && r_regex_match ("ivar","e", f->name)) {
			r_cons_printf ("  public %s %s\n", f->type, f->name);
		}
	}
	r_list_foreach (c->methods, iter3, sym) {
		const char *mn = sym->dname? sym->dname: sym->name;
		const char *ms = strstr (mn, "method.");
		if (ms) {
			mn = ms + strlen ("method.");
		}
		r_cons_printf ("  public %s ();\n", mn);
	}
	r_cons_printf ("}\n\n");
}