@gnothiseauton No decompilation or heavy reverse engineering is necessary in this case, as Samba is open source.
As noted by CVE - CVE-2007-2447 the vulnerable versions are 3.0.0 through 3.0.25rc3. You can find most of those old versions at Index of /pub/samba/stable. I happened to grab 3.0.20.
It’s a fairly big project, so instead of crawling through all the files by hand:
root@kali:/media/sf_shared/samba-3.0.20# grep -R "map script" *
-*- snip -*-
source/lib/username.c: /* first try the username map script */
-*- snip -*-
Taking a look at that file, we see this:
/* first try the username map script */
if ( *cmd ) {
char **qlines;
pstring command;
int numlines, ret, fd;
pstr_sprintf( command, "%s \"%s\"", cmd, user );
DEBUG(10,("Running [%s]\n", command));
ret = smbrun(command, &fd);
DEBUGADD(10,("returned [%d]\n", ret));
So it’s just putting the supplied username onto the end of a command string (cmd in this case is /etc/samba/scripts/mapusers.sh as set by the config file) and then tossing that into smbrun(). Okay, so where’s smbrun()?
root@kali:/media/sf_shared/samba-3.0.20# grep -R "smbrun(" *
-*- snip -*-
source/lib/smbrun.c:This is a utility function of smbrun().
source/lib/smbrun.c:int smbrun(char *cmd, int *outfd)
-*- snip -*-
That function just does a bunch of process/permissions housekeeping, and then right at the very bottom:
execl("/bin/sh","sh","-c",cmd,NULL);
/* not reached */
exit(82);
return 1;
Browsing through the code above this, it’s very clear that the cmd variable is never sanitized. So user (our input) gets put directly into cmd, then cmd gets tossed directly into execl(), giving us command execution via:
sh -c /etc/samba/scripts/mapusers.sh "our_input_here"
Note: I actually messed up the quotation marks in my previous post, but it doesn’t even matter because of how straightforward this vulnerability is.
If you take a look at a newer, fixed version of Samba you’ll instead see that smbrun() is now just a wrapper function which calls smbrun_internal() with the sanitize argument set to True. What’s that do? Well, back to the execl() call:
const char *newcmd = sanitize ? escape_shell_string(cmd) : cmd;
if (!newcmd) {
exit(82);
}
execl("/bin/sh","sh","-c",newcmd,NULL);
Easy peasy. Two greps and some patience and anyone could stumble on dumb vulnerabilities like this. 