cve-2017-7494 分析

== Subject:     Remote code execution from a writable share.
== CVE ID#:     CVE-2017-7494
== Versions:    All versions of Samba from 3.5.0 onwards.
== Summary:     Malicious clients can upload and cause the smbd server
==              to execute a shared library from a writable share.


通过观察 github 提交记录,确定产生漏洞位置。

5  source3/rpc_server/srv_pipe.c
 @@ -481,6 +481,11 @@ bool is_known_pipename(const char *pipename, struct ndr_syntax_id *syntax)
  	NTSTATUS status;
 +	if (strchr(pipename, '/')) {
 +		DEBUG(1, ("Refusing open on pipe %s\n", pipename));
 +		return false;
 +	}
  	if (lp_disable_spoolss() && strequal(pipename, "spoolss")) {
  		DEBUG(10, ("refusing spoolss access\n"));
  		return false;

使用 MSF PoC 复现该漏洞:

调试 SMB 对 is_known_pipename 下断电,触发漏洞:



#11 0x00007f815c4390c1 in __dlopen (
    file=file@entry=0x7f816b8f7950 "/home/shares/anonymous/",
    mode=mode@entry=2) at dlopen.c:87
#12 0x00007f81618f2eab in load_module (
    path=path@entry=0x7f816b8f7950 "/home/shares/anonymous/",
    is_probe=is_probe@entry=true, handle_out=handle_out@entry=0x7fff6f529168)
    at ../lib/util/modules.c:40
#13 0x00007f81618f30f9 in do_smb_load_module (
    subsystem=subsystem@entry=0x7f816a026d0d "rpc",
    module_name=module_name@entry=0x7f816b8f7950 "/home/shares/anonymous/", is_probe=is_probe@entry=true) at ../lib/util/modules.c:188
#14 0x00007f81618f34fe in smb_probe_module (
    subsystem=subsystem@entry=0x7f816a026d0d "rpc",
    module=module@entry=0x7f816b8f7950 "/home/shares/anonymous/")
    at ../lib/util/modules.c:228
#15 0x00007f8169ef3037 in is_known_pipename (
    pipename=pipename@entry=0x7f816b8f7950 "/home/shares/anonymous/",
    syntax=syntax@entry=0x7fff6f529230) at ../source3/rpc_server/srv_pipe.c:488


status = smb_probe_module("rpc", pipename);

smb_probe_moduledo_smb_load_module 会调用 load_module 加载 so 文件并执行 init_module_fn 方法

init_module_fn load_module(const char *path, bool is_probe, void **handle_out)
	void *handle;
	void *init_fn;
	char *error;

	/* This should be a WAF build, where modules should be built
	 * with no undefined symbols and are already linked against
	 * the libraries that they are loaded by */
	handle = dlopen(path, RTLD_NOW);

	/* This call should reset any possible non-fatal errors that
	   occurred since last call to dl* functions */
	error = dlerror();

	if (handle == NULL) {
		int level = is_probe ? 5 : 0;
		DEBUG(level, ("Error loading module '%s': %s\n", path, error ? error : ""));
		return NULL;

	init_fn = (init_module_fn)dlsym(handle, SAMBA_INIT_MODULE);

	/* we could check dlerror() to determine if it worked, because
           dlsym() can validly return NULL, but what would we do with
           a NULL pointer as a module init function? */

	if (init_fn == NULL) {
		DEBUG(0, ("Unable to find %s() in %s: %s\n",
			  SAMBA_INIT_MODULE, path, dlerror()));
		DEBUG(1, ("Loading module '%s' failed\n", path));
		return NULL;

	if (handle_out) {
		*handle_out = handle;

	return (init_module_fn)init_fn;

构建包含 SAMBA_INIT_MODULE 的函数的动态链接库即可进行exploit。