I have the following summarized pseudo code in C89 from an ssh server library that provide only access to things like git‑shell (/bin/bash
is replaced with the program to run, so it’s not possible to do something else) :
struct _raw_uncapped_ssh_string { // no limit on the size of the string;
uint32_t len;
char non_null_terminated_string[]; // by protocol design it have a minimum length of 1
};
typedef struct _raw_uncapped_ssh_string raw_ssh_string;
union buffer {
void * uncapped_zlib_decompressed_network_data;
// yes, the size is uncapped, so it’s possible to put 4Gb of
// data in it that would be copied later into memory. zlib
// allow easily to turn some Mb in Gb of data, but it’s not
// the point of the question.
raw_ssh_string st;
};
get_command (compressed_network_data) {
size_t len;
char * command;
buffer string=uncompress_to_buffer(compressed_network_data);
len=ntohl(string.st.len)+1;
command=malloc(len+1);
command[len]=0;
// here’s the point, both the string length and content as
// well it’s supplied size is controlled by the attacker.
memcpy(command,string.st.data,len);
return command;
}
Here’s how the command is executed later (the stringcommand
is unchanged afterget_command()
).
const char *args[]={"/bin/bash",command,NULL}; // /bin/bash isn’t the shell, it has been replaced by git‑shell.
// redirect the program output to the network.
dup2(stdin, 0);
dup2(stdout,1);
dup2(stdout,2);
close(stdin);
close(stdout);
//if this return execution failed and print an error message
return execv(args[0],(char * const *)args); // I don’t know which is the system, so I can’t know about the libc behaviour.
I can’t domemcpy(command,string.st.data,0)
since the third member ofmemcpy
has a minimum size of 1, and in my context,size_t
uses a 64 bit integer, I can’t perform a buffer overflow, since there islen
.
All I can do is to setlen
to a value larger than the one allocated tostring.st.data
. This is a buffer underflow enabling me to read unallocated memory.
I can read the server memory, however, I can’t see what sensitive data a public ssh server can hold (in my case the list of users that can perform ssh is public).
So does a buffer underflow onmemcpy
allow remote code execution ?
command[len] = 0
then that is a buffer overflow, since the max index for a buffer of lengthlen
islen-1
. Alternatively, if the actual code does amalloc(len+1)
instead of amalloc(len)
, then you can make a massive buffer overflow by setting thelen
value to0xFFFFFFFF
.len+1
so the setting to 0 should be valid.string.st.len
to ‑1.