NixOS / nixpkgs

Nix Packages collection & NixOS
MIT License
17.15k stars 13.42k forks source link

Responder: can't get SMB related events #255281

Open ca5ua1 opened 11 months ago

ca5ua1 commented 11 months ago

Describe the bug

Samba authentification doesn't get captured while using git version works as it should be. Samba related events just doesn't appear in console

Steps To Reproduce

Steps to reproduce the behavior:

  1. nix-shell -p responder
  2. responder -I eth0
  3. Try to open in Windows Samba share

Steps to reproduce the WORKING behavior:

  1. git clone https://github.com/lgandx/Responder; cd responder
  2. nix-shell -p python311Packages.netifaces
  3. python ./Responder.py -I eth0
  4. Try to open in Windows Samba share

Expected behavior

A clear and concise description of what you expected to happen.

➤ sudo responder -I tun0
[sudo] password for casual:
                                         __
  .----.-----.-----.-----.-----.-----.--|  |.-----.----.
  |   _|  -__|__ --|  _  |  _  |     |  _  ||  -__|   _|
  |__| |_____|_____|   __|_____|__|__|_____||_____|__|
                   |__|

           NBT-NS, LLMNR & MDNS Responder 3.1.3.0

  To support this project:
  Patreon -> https://www.patreon.com/PythonResponder
  Paypal  -> https://paypal.me/PythonResponder

  Author: Laurent Gaffie (laurent.gaffie@gmail.com)
  To kill this script hit CTRL-C

[+] Poisoners:
    LLMNR                      [ON]
    NBT-NS                     [ON]
    MDNS                       [ON]
    DNS                        [ON]
    DHCP                       [OFF]

[+] Servers:
    HTTP server                [ON]
    HTTPS server               [ON]
    WPAD proxy                 [OFF]
    Auth proxy                 [OFF]
    SMB server                 [ON]
    Kerberos server            [ON]
    SQL server                 [ON]
    FTP server                 [ON]
    IMAP server                [ON]
    POP3 server                [ON]
    SMTP server                [ON]
    DNS server                 [ON]
    LDAP server                [ON]
    RDP server                 [ON]
    DCE-RPC server             [ON]
    WinRM server               [ON]

[+] HTTP Options:
    Always serving EXE         [OFF]
    Serving EXE                [OFF]
    Serving HTML               [OFF]
    Upstream Proxy             [OFF]

[+] Poisoning Options:
    Analyze Mode               [OFF]
    Force WPAD auth            [OFF]
    Force Basic Auth           [OFF]
    Force LM downgrade         [OFF]
    Force ESS downgrade        [OFF]

[+] Generic Options:
    Responder NIC              [tun0]
    Responder IP               [10.10.15.39]
    Responder IPv6             [dead:beef:2::1125]
    Challenge set              [random]
    Don't Respond To Names     ['ISATAP']

[+] Current Session Variables:
    Responder Machine Name     [WIN-UEZ7FENPZKY]
    Responder Domain Name      [WZFQ.LOCAL]
    Responder DCE-RPC Port     [45290]

[+] Listening for events...

[!] Error starting SSL server on port 443, check permissions or other servers running.
[!] Error starting SSL server on port 5986, check permissions or other servers running.

After trying to open SMB share should appear something like this:

[SMB] NTLMv2-SSP Client   : 10.129.19.184
[SMB] NTLMv2-SSP Username : RESPONDER\Administrator
[SMB] NTLMv2-SSP Hash     : Administrator::RESPONDER:5d64ccf8db37ff6c:72DE5F7B8D26074D8BE3A74879530F21:010100000000000000B436B6DCE7D901CB31B4E99680A1770000000002000800460058004B00440001001E00570049004E002D00470054005900330037005800310035004F004100540004003400570049004E002D00470054005900330037005800310035004F00410054002E00460058004B0044002E004C004F00430041004C0003001400460058004B0044002E004C004F00430041004C0005001400460058004B0044002E004C004F00430041004C000700080000B436B6DCE7D901060004000200000008003000300000000000000001000000002000003220F5E4A1C2ED87981D863BB06DDBD9A9E78F553E5D6A85593F93B0D27D706F0A001000000000000000000000000000000000000900200063006900660073002F00310030002E00310030002E00310035002E00330039000000000000000000

but from nixpkgs version it never happens

Metadata

Please run nix-shell -p nix-info --run "nix-info -m" and paste the result.

[user@system:~]$ nix-shell -p nix-info --run "nix-info -m"
 - system: `"x86_64-linux"`
 - host os: `Linux 6.5.2-zen1, NixOS, 23.11 (Tapir), 23.11.20230908.db9208a`
 - multi-user?: `yes`
 - sandbox: `yes`
 - version: `nix-env (Nix) 2.17.0`
 - channels(root): `"nixos-23.05, nixpkgs"`
 - channels(casual): `""`
 - nixpkgs: `/nix/var/nix/profiles/per-user/root/channels/nixos`
fabaff commented 11 months ago

The latest tagged release (3.1.3.0) is shipped. While looking at the commit log of Responder there were a lot of changes in the last 12 months. We could give it a try running with one of the latest commits.

lap1nou commented 4 months ago

Hello @fabaff and @ca5ua1,

I found why it was buggy (strace -f responder -A -I $INTERFACE): image

A logs path was recently added and seems to be used at two places, in settings.py and utils.py, when capturing a hash, it try to write something in the log file and can't since NixOS store is RO, here is my quick and dirty workaround:

substituteInPlace $out/share/Responder/settings.py \
      --replace "self.LogDir = os.path.join(self.ResponderPATH, 'logs')" "self.LogDir = os.path.join('/tmp/Responder/', 'logs')"

substituteInPlace $out/share/Responder/utils.py \
      --replace "logfile = os.path.join(settings.Config.ResponderPATH, 'logs', fname)" "logfile = os.path.join('/tmp/Responder/', 'logs', fname)"

Also I spotted something else, SSL certs aren't generated by the Nix packages, which mean servers that use SSL can't be started, here is my workaround (add this under the other replace already made):

--replace "certs/responder.crt" "/tmp/Responder/certs/responder.crt" \
--replace "certs/responder.key" "/tmp/Responder/certs/responder.key"

And also generate them when we make the wrapper:

makeWrapper ${python3.interpreter} $out/bin/responder \
      --set PYTHONPATH "$PYTHONPATH:$out/bin/Responder.py" \
      --add-flags "$out/share/Responder/Responder.py" \
      --run "mkdir -p /tmp/Responder; mkdir -p /tmp/Responder/certs; openssl genrsa -out /tmp/Responder/certs/responder.key 2048; openssl req -new -x509 -days 3650 -key /tmp/Responder/certs/responder.key -out /tmp/Responder/certs/responder.crt -subj "/""

Also right now the config can't be changed since it's in the store, shouldn't we patch the script to use another path for the config and store it in /tmp/Responder/Responder.conf ?

Regards.

fabaff commented 4 months ago

Also right now the config can't be changed since it's in the store, shouldn't we patch the script to use another path for the config and store it in /tmp/Responder/Responder.conf ?

Seems like a convenient way to work around the issue. Personally, I'm not a huge fan of putting stuff in /tmpas for most people this is more or less another trash bin. Not sure how much patching would be required to use the user's home dir (in perfect world not much :wink: ).

Mag1cByt3s commented 1 month ago

@fabaff I am having the same issues.

Responder cannot listen on the SSL ports 636, 443, 5986 although these ports are not occupied.

[!] Error starting SSL server on port 636, check permissions or other servers running.
[!] Error starting SSL server on port 443, check permissions or other servers running.
[!] Error starting SSL server on port 5986, check permissions or other servers running.

I am also not seeing any SMB related events in Responder.

I tried to fix the package by doing an override like so:

responder = prev.responder.overrideAttrs (oldAttrs: {

          buildInputs = oldAttrs.buildInputs or [] ++ [ pkgs.openssl ];

          postPatch = ''
            if [ -f Responder/settings.py ]; then
              substituteInPlace Responder/settings.py \
                --replace "self.LogDir = os.path.join(self.ResponderPATH, 'logs')" "self.LogDir = os.path.join('/tmp/Responder/', 'logs')"
            fi

            if [ -f Responder/utils.py ]; then
              substituteInPlace Responder/utils.py \
                --replace "logfile = os.path.join(settings.Config.ResponderPATH, 'logs', fname)" "logfile = os.path.join('/tmp/Responder/', 'logs', fname)"
            fi

            if [ -f Responder/Responder.py ]; then
              substituteInPlace Responder/Responder.py \
                --replace "certs/responder.crt" "/tmp/Responder/certs/responder.crt" \
                --replace "certs/responder.key" "/tmp/Responder/certs/responder.key"
            fi
          '';

          postBuild = ''
            mkdir -p $out/tmp/Responder/certs
            ${pkgs.openssl}/bin/openssl genrsa -out $out/tmp/Responder/certs/responder.key 2048
            ${pkgs.openssl}/bin/openssl req -new -x509 -days 3650 -key $out/tmp/Responder/certs/responder.key -out $out/tmp/Responder/certs/responder.crt -subj "/"
          '';

        });

But that does not seem to change anything.

Mag1cByt3s commented 1 month ago

so i was able to fix the issues with responder.

I came up with these fixes:

(pkgs.responder.overrideAttrs (oldAttrs: rec {
      buildInputs = oldAttrs.buildInputs or [] ++ [ pkgs.openssl pkgs.coreutils ];

      installPhase = ''
        runHook preInstall

        mkdir -p $out/bin $out/share $out/share/Responder
        cp -R . $out/share/Responder

        makeWrapper ${python3.interpreter} $out/bin/responder \
          --set PYTHONPATH "$PYTHONPATH:$out/bin/Responder.py" \
          --add-flags "$out/share/Responder/Responder.py" \
          --run "mkdir -p /tmp/Responder"

        substituteInPlace $out/share/Responder/Responder.conf \
          --replace "Responder-Session.log" "/tmp/Responder/Responder-Session.log" \
          --replace "Poisoners-Session.log" "/tmp/Responder/Poisoners-Session.log" \
          --replace "Analyzer-Session.log" "/tmp/Responder/Analyzer-Session" \
          --replace "Config-Responder.log" "/tmp/Responder/Config-Responder.log" \
          --replace "Responder.db" "/tmp/Responder/Responder.db"

        runHook postInstall

        runHook postPatch
      '';

      postInstall = ''
        wrapProgram $out/bin/responder \
          --run "mkdir -p /tmp/Responder/certs && ${pkgs.openssl}/bin/openssl genrsa -out /tmp/Responder/certs/responder.key 2048 && ${pkgs.openssl}/bin/openssl req -new -x509 -days 3650 -key /tmp/Responder/certs/responder.key -out /tmp/Responder/certs/responder.crt -subj '/'"
      '';

      postPatch = ''
        if [ -f $out/share/Responder/settings.py ]; then
          substituteInPlace $out/share/Responder/settings.py \
            --replace "self.LogDir = os.path.join(self.ResponderPATH, 'logs')" "self.LogDir = os.path.join('/tmp/Responder/', 'logs')"
        fi

        if [ -f $out/share/Responder/utils.py ]; then
          substituteInPlace $out/share/Responder/utils.py \
            --replace "logfile = os.path.join(settings.Config.ResponderPATH, 'logs', fname)" "logfile = os.path.join('/tmp/Responder/', 'logs', fname)"
        fi

        if [ -f $out/share/Responder/Responder.py ]; then
          substituteInPlace $out/share/Responder/Responder.py \
            --replace "certs/responder.crt" "/tmp/Responder/certs/responder.crt" \
            --replace "certs/responder.key" "/tmp/Responder/certs/responder.key"
        fi

        if [ -f $out/share/Responder/Responder.conf ]; then
          substituteInPlace $out/share/Responder/Responder.conf \
            --replace "certs/responder.crt" "/tmp/Responder/certs/responder.crt" \
            --replace "certs/responder.key" "/tmp/Responder/certs/responder.key"
        fi
      '';
    }))

writing logs and certs into /tmp might not be the best idea. If anyone knows a better place it would be great if we can get this upstreamed to fix the package.

Also it is important to disable the firewall otherwise you won't be able to capture anything in responder.

networking.firewall.enable = false; # This one is necessary to expose ports to the netwok. Usefull for smbserver, responder, http.server, ...
networking.nftables.enable = false; # This one is necessary to expose ports to the netwok. Usefull for smbserver, responder, http.server, ...

@ca5ua1 my fixes should also temporarily solve the issues you have with Responder until it is fixed in upstream.

@fabaff How can we improve these fixes and get them into upstream?

Also as @lap1nou already mentioned it would be a good idea to somehow make the responder.conf writable by the user so the user can temporarily change settings. E.g. this is necessary when using Responder in combination with other tools like ntlmrelayx .e.g where you need to temporarily disable the HTTP and SMB servers of responder.

Mag1cByt3s commented 1 month ago

I just turned the responder fix into an overlay:

# responder-overlay.nix
final: prev:
{
  # FIX for responder: https://github.com/NixOS/nixpkgs/issues/255281#issuecomment-2229259710
  responder-patched = prev.responder.overrideAttrs (oldAttrs: rec {
    buildInputs = oldAttrs.buildInputs or [] ++ [ prev.openssl prev.coreutils ];

    installPhase = ''
      runHook preInstall

      mkdir -p $out/bin $out/share $out/share/Responder
      cp -R . $out/share/Responder

      makeWrapper ${prev.python3.interpreter} $out/bin/responder \
        --set PYTHONPATH "$PYTHONPATH:$out/share/Responder" \
        --add-flags "$out/share/Responder/Responder.py" \
        --run "mkdir -p /tmp/Responder"

      substituteInPlace $out/share/Responder/Responder.conf \
        --replace "Responder-Session.log" "/tmp/Responder/Responder-Session.log" \
        --replace "Poisoners-Session.log" "/tmp/Responder/Poisoners-Session.log" \
        --replace "Analyzer-Session.log" "/tmp/Responder/Analyzer-Session.log" \
        --replace "Config-Responder.log" "/tmp/Responder/Config-Responder.log" \
        --replace "Responder.db" "/tmp/Responder/Responder.db"

      runHook postInstall

      runHook postPatch
    '';

    postInstall = ''
      wrapProgram $out/bin/responder \
        --run "mkdir -p /tmp/Responder/certs && ${prev.openssl}/bin/openssl genrsa -out /tmp/Responder/certs/responder.key 2048 && ${prev.openssl}/bin/openssl req -new -x509 -days 3650 -key /tmp/Responder/certs/responder.key -out /tmp/Responder/certs/responder.crt -subj '/'"
    '';

    postPatch = ''
      if [ -f $out/share/Responder/settings.py ]; then
        substituteInPlace $out/share/Responder/settings.py \
          --replace "self.LogDir = os.path.join(self.ResponderPATH, 'logs')" "self.LogDir = os.path.join('/tmp/Responder/', 'logs')"
      fi

      if [ -f $out/share/Responder/utils.py ]; then
        substituteInPlace $out/share/Responder/utils.py \
          --replace "logfile = os.path.join(settings.Config.ResponderPATH, 'logs', fname)" "logfile = os.path.join('/tmp/Responder/', 'logs', fname)"
      fi

      if [ -f $out/share/Responder/Responder.py ]; then
        substituteInPlace $out/share/Responder/Responder.py \
          --replace "certs/responder.crt" "/tmp/Responder/certs/responder.crt" \
          --replace "certs/responder.key" "/tmp/Responder/certs/responder.key"
      fi

      if [ -f $out/share/Responder/Responder.conf ]; then
        substituteInPlace $out/share/Responder/Responder.conf \
          --replace "certs/responder.crt" "/tmp/Responder/certs/responder.crt" \
          --replace "certs/responder.key" "/tmp/Responder/certs/responder.key"
      fi
    '';
  });
}
Mag1cByt3s commented 1 month ago

I optimized the responder overlay to use more sane locations to store logs and certs (no tmp anymore).

Also I placed the Responder.conf into /etc/responder/ where it is located on other linux distributions and made it writable by the user.

On top of that i fixed a bug in my overlay that was resetting the Responder.conf on flake rebuilds and startup of responder.

Here is the final overlay:

# responder-overlay.nix
final: prev:
{
  # FIX for responder: https://github.com/NixOS/nixpkgs/issues/255281#issuecomment-2244250577
  responder-patched = prev.responder.overrideAttrs (oldAttrs: rec {
    buildInputs = oldAttrs.buildInputs or [] ++ [ prev.openssl prev.coreutils ];

    installPhase = ''
      runHook preInstall

      mkdir -p $out/bin $out/share/Responder
      cp -R . $out/share/Responder

      makeWrapper ${prev.python3.interpreter} $out/bin/responder \
        --set PYTHONPATH "$PYTHONPATH:$out/share/Responder" \
        --add-flags "$out/share/Responder/Responder.py" \
        --run "mkdir -p /var/lib/responder"

      substituteInPlace $out/share/Responder/Responder.conf \
        --replace-quiet "Responder-Session.log" "/var/lib/responder/Responder-Session.log" \
        --replace-quiet "Poisoners-Session.log" "/var/lib/responder/Poisoners-Session.log" \
        --replace-quiet "Analyzer-Session.log" "/var/lib/responder/Analyzer-Session.log" \
        --replace-quiet "Config-Responder.log" "/var/lib/responder/Config-Responder.log" \
        --replace-quiet "Responder.db" "/var/lib/responder/Responder.db"

      runHook postInstall

      runHook postPatch
    '';

    postInstall = ''
      wrapProgram $out/bin/responder \
        --run "mkdir -p /var/lib/responder/certs && ${prev.openssl}/bin/openssl genrsa -out /var/lib/responder/certs/responder.key 2048 && ${prev.openssl}/bin/openssl req -new -x509 -days 3650 -key /var/lib/responder/certs/responder.key -out /var/lib/responder/certs/responder.crt -subj '/'" \
        --run "mkdir -p /etc/responder && if [ ! -f /etc/responder/Responder.conf ]; then cp $out/share/Responder/Responder.conf /etc/responder/Responder.conf && chmod +w /etc/responder/Responder.conf; fi"
    '';

    postPatch = ''
      if [ -f $out/share/Responder/settings.py ]; then
        substituteInPlace $out/share/Responder/settings.py \
          --replace-quiet "self.LogDir = os.path.join(self.ResponderPATH, 'logs')" "self.LogDir = os.path.join('/var/lib/responder', 'logs')" \
          --replace-quiet "os.path.join(self.ResponderPATH, 'Responder.conf')" "'/etc/responder/Responder.conf'"
      fi

      if [ -f $out/share/Responder/utils.py ]; then
        substituteInPlace $out/share/Responder/utils.py \
          --replace-quiet "logfile = os.path.join(settings.Config.ResponderPATH, 'logs', fname)" "logfile = os.path.join('/var/lib/responder', 'logs', fname)"
      fi

      if [ -f $out/share/Responder/Responder.py ]; then
        substituteInPlace $out/share/Responder/Responder.py \
          --replace-quiet "certs/responder.crt" "/var/lib/responder/certs/responder.crt" \
          --replace-quiet "certs/responder.key" "/var/lib/responder/certs/responder.key"
      fi

      if [ -f $out/share/Responder/Responder.conf ]; then
        substituteInPlace $out/share/Responder/Responder.conf \
          --replace-quiet "certs/responder.crt" "/var/lib/responder/certs/responder.crt" \
          --replace-quiet "certs/responder.key" "/var/lib/responder/certs/responder.key"
      fi
    '';
  });
}