攻防世界新手模式例题(Web)

PHP2

首先我们查看页面,查看前端代码

发现均没有什么有效信息,由题目可知,此问题与php相关,于是我们可以看一下他的index.php文件

查看时用?index.phps

补充知识:phps文件就是php的源代码文件,通常用于提供给用户(访问者)查看php代码,因为用户无法直接通过Web浏览器看到php文件的内容,所以需要用phps文件代替。

得到了php源码,判断此处应该是代码审计问题。

这一段代码表明,经过url解码后的id不能等于admin,否则将会直接退出

而这一段代码表名,经过一次urldecode解码后的内容要等于admin

于是我们可以将admin经过两次url加密,这样便可以绕过第一次比较,经过第二次解码后得到flag

补充知识:urlencode()与urldecode()函数

urlencode():原理就是首先把中文字符转换为十六进制,然后在每个字符前面加上一个标识符%,一般用在url链接地址编码

urldecode():与上述函数原理相反用于解码已编码的URL字符串,其原理就是把十六进制字符串转化为字符

浏览器在接受url时,会首先进行一次urldecode的解码

easyupload

显然是一个文件上传问题,我们开始用应对白名单的绕过

首先上传.user.ini的文件(因为是上传头像,所以必定只能放过image类型的文件)

我们在此处直接上两个绕过,一个是通过抓包改变content-type

另一个是在文件内容前加上GIF89a,绕过对文件内容的检测

一句话木马同样采用上述绕过方式

最后通过中国蚁剑连接,得到flag文件

easyphp

首先我们通过页面判断,此题为一个代码审计问题

通过这段代码我们可以得知要想得到flag,要使key1,key2同时非零

然后我们在上边找给key赋值的操作

补充知识:isset()函数用于检查一个变量是否已经设置并且非null,返回true或false。

intval()函数用于将一个变量转换为整数类型。

如果参数是一个整数或者一个字符串表示的整数(比如"123"),则直接返回这个整数值。

如果参数是一个浮点数,则返回它的整数部分(即向下取整)。

如果参数是一个字符串,但不是一个有效的整数表示(比如"abc"),则返回0。

如果参数是一个布尔值,true会被转换为1,false会被转换为0。

如果参数是一个数组或者对象,则返回0。

如果参数是null,则返回0。

也就是说我们要同时满足a有值,a转变为整数类型后值要大于6000000,并且a的字符串长度要小于等于3

显然第二三个条件是相反的,此处但我们可以通过科学计数法写。比如9e9(此处考察在低版本php中科学计数法的长度是按字符串来算的),则我们便绕过了第一个限制

补充知识:

在PHP中,substr()函数用于返回字符串的一部分。它的语法如下:

substr(string $string, int $start, ?int $length = null): string

其中:

$string 是要处理的字符串;

$start 是要截取的起始位置,如果是负数,表示从字符串末尾开始计算;

$length 是可选的参数,表示要截取的长度。如果未指定,则截取从起始位置到字符串末尾的所有字符。

在PHP中,字符串从末尾算起第一个字符的索引是-1。

所以我们要使b经过md编码后的倒数六个字符依次为8b184b

此时我们要通过脚本暴力破解

补充知识:

m = hashlib.md5(): 创建一个 MD5 哈希对象 m,但此时还没有对任何数据进行哈希计算。

m.update(str.encode('utf-8')): 将输入的字符串 str 转换为字节编码(UTF-8 编码),然后更新哈希对象 m,将这个字节编码添加到哈希对象的内部缓冲区中。

return m.hexdigest(): 计算哈希对象 m 中所有输入的哈希值,并以十六进制字符串的形式返回结果。这里的hexdigest()方法会返回一个32位的十六进制字符串,表示MD5哈希值。

跑出来的结果是53724,于是我们绕过了第二个条件判断

此时我们已经使key1的的值为真

补充知识:

jason_decode(): 用于将 JSON 格式的字符串转换为 PHP 变量。它接受一个 JSON 格式的字符串作为参数,然后返回对应的 PHP 变量。如果转换失败,会返回 null

is_array(): 用于判断一个变量是否是数组。如果变量是数组,则返回 true,否则返回 false

is_numeric(): 用于判断一个变量是否是数字或数字字符串。如果变量是数字或数字字符串,则返回 true,否则返回 false

count(): 用于统计数组中的元素个数,或者统计对象中的属性个数。它接受一个数组或对象作为参数,返回其元素个数。

die(): 用于输出一条消息并终止脚本的执行。通常用于在程序中发现错误或异常情况时,输出错误信息并停止程序的执行。

第一个绕过,首先满足c是一个数组,并且键m对应的值不是数字,同时还要大于2022,可以写成2022c进行绕过

补充知识:php的弱类型比较,php的数字与字符串比较的时候会自动进行解析其会将字符串从第一个非数字处截断,将截断前的字符串当作数字进行比较。

第二个绕过,满足键n对应的是一个含有两个元素的数组,且第一个元素也是数组

"n":[ [] ,0]

补充知识:php中数组的形式大概是(“键名”=>"值")这样的形式,此处写作{ },是因为它进行了json形式解码

最终payload:

fileclude

首先判断是白盒的代码审计

关键是这个include函数

所以首先要这样构建?file1=php://filter/read=convert.base64-encode/resource=flag.php

让flag.php文件以base64编码的形式显示到屏幕上

第二个便是需要绕过,file2=php://input这里采用简单的写入,利用bp抓包

使file_get_contents()返回的值为“hello ctf”

最后得到base64编码的flag

解密得到flag

上一篇:14:00面试,14:06就出来了,问的问题过于变态了。。。


下一篇:总结mac下解决matplotlib中文显示问题的几种方法