我在 ssh 服务器库中总结了以下 C89 中的伪代码,这些代码仅提供对 git-shell 之类的访问(/bin/bash
已替换为要运行的程序,因此无法执行其他操作) :
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;
}
以下是稍后执行命令的方式(字符串command
在 之后未更改get_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.
我不能这样做,memcpy(command,string.st.data,0)
因为第三个成员的memcpy
最小大小为 1,并且在我的上下文中,size_t
使用 64 位整数,我无法执行缓冲区溢出,因为存在len
.
我所能做的就是设置len
一个大于分配给string.st.data
. 这是一个缓冲区下溢,使我能够读取未分配的内存。
我可以读取服务器内存,但是,我看不到公共 ssh 服务器可以保存哪些敏感数据(在我的情况下,可以执行 ssh 的用户列表是公开的)。
那么缓冲区下溢是否memcpy
允许远程代码执行?