php特性

WEB89

源代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
(?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-18 15:38:51
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/


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;
}
}

题目要求我们通过GET方式传入num变量,其中,num变量不能有0~9,否则回显no no no! 。在绕过这一层判断之后,还要求我们在intval()函数中执行的结果必须是1

查找php手册,发现intval函数的判断结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
(?php
echo intval(42); // 42
echo intval(4.2); // 4
echo intval('42'); // 42
echo intval('+42'); // 42
echo intval('-42'); // -42
echo intval(042); // 34
echo intval('042'); // 42
echo intval(1e10); // 1410065408
echo intval('1e10'); // 1
echo intval(0x1A); // 26
echo intval(42000000); // 42000000
echo intval(420000000000000000000); // 0
echo intval('420000000000000000000'); // 2147483647
echo intval(42, 8); // 42
echo intval('42', 8); // 34
echo intval(array()); // 0
echo intval(array('foo', 'bar')); // 1
?)

那么就很好解决了,当我们给intval传入一个数组,只要数组内有值存在,必然会执行结果为1
因此我们传入?num[]=a轻松得到结果


WEB90

源代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
(?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-18 16:06:11
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/


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,进行强比较时不能时num等于4476,然后对num进行转化的时候又必须等于4476
我们使用弱比较绕过,传入/?num=4476a即可获取flag

ps:如果 base 是 0,通过检测 var 的格式来决定使用的进制:
* 如果字符串包括了 “0x” (或 “0X”) 的前缀,使用 16 进制 (hex);否则,
* 如果字符串以 “0” 开始,使用 8 进制(octal);否则,
* 将使用 10 进制 (decimal)


WEB91

源代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
(?php

/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-18 16:16:09
# @link: https://ctfer.com

*/

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';
}

正则匹配修饰符如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# i 不区分(ignore)大小写;
例如: /abc/i 可以匹配 abc、aBC、Abc

# g 全局(global)匹配
* 如果不带g,正则过程中字符串从左到右匹配,找到第一个符合条件的即匹配成功,返回
* 如果带g,则字符串从左到右,找到每个符合条件的都记录下来,知道字符串结尾位置
例如:
var str = 'aaaaaaaa'
var reg1 = /a/; str.match(reg1) // 结果为:["a", index: 0, input: "aaaaaaaa"]
var reg2 = /a/g; str.match(reg2) // 结果为:["a", "a", "a", "a", "a", "a", "a", "a"]

# m 多(more)行匹配
* 若存在换行\n并且有开始^或结束$符的情况下,和g一起使用实现全局匹配,因为存在换行时默认会把换行符作为一个字符任务匹配字符串是个单行,
* g只匹配第一行,添加m之后实现多行,每个换行符之后就是开始
var str = "abcggab\nabcoab";
var preg1 = /^abc/gm; str.match(preg1) // 结果为:["abc", "abc"]
var preg2 = /ab$/gm; str.match(preg2) // 结果为:["ab", "ab"]


# s 特殊字符圆点 . 中包含换行符
默认的圆点 . 是 匹配除换行符 \n 之外的任何单字符,加上s之后, . 中包含换行符
$str = "abggab\nacbs";
$preg = "/b./s";
preg_match_all($preg, $str,$matchs);
print_r($matchs);//Array ( [0] =) Array ( [0] =) bg [1] =) b [2] =) bs ) )

# U 只匹配最近的一个字符串;不重复匹配;
$mode="/a(.*?)c/";
$preg="/a.*c/U";//这两个正则返回相同的值
$str="abcabbbcabbbbbc" ;
preg_match($mode,$str,$content); echo $content[0];//abc
preg_match($preg,$str,$content); echo $content[0];//abc
//修正符:x 将模式中的空白忽略;
//修正符:A 强制从目标字符串开头匹配;
//修正符:D 如果使用$限制结尾字符,则不允许结尾有换行;
//修正符:e 配合函数preg_replace()使用, 可以把匹配来的字符串当作正则表达式执行;

因此,第一次全局匹配,有换行的情况下也会进行逐行匹配,但是第二次,只进行了大小写匹配,这就造成了可以进行绕过,我们使用%0APHP即可顺利读取(%0A时url编码后的换行符)


WEB92

源代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
(?php

/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-18 16:29:30
# @link: https://ctfer.com

*/

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);
}
}

这不是第90题么?
仔细看还真有区别,第一步的强比较换成了弱比较,结合90的ps,我们直接传入8进制的4476:010574按照十进制与4476比较绕过第一个if,由于开头数字为0,所以会在intval执行中自动按照八进制数据处理和4476相等,顺利解题


WEB93

源代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
(?php

/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-18 16:32:58
# @link: https://ctfer.com

*/

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);
}
}

思路同上


WEB94

源代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
(?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-18 16:46:19
# @link: https://ctfer.com

*/

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;
}
}

查看发现第三条if语句将我们的八进制转化大法也ban了,那么我们只能另寻他法。
由于intval语句会自动取整
echo intval(4.2); // 4
那么我们可以使用4476.0来绕过,又因为进入的numif语句是和4476进行强比较,因此我们浮点数和整数自然可以绕过比较,得到答案


WEB95

源代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
(?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-18 16:53:59
# @link: https://ctfer.com

*/

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;
}
}

这道题出题人汲取了上一道题的错误,将第一个if语句换为弱比较,此时我们就不能继续使用浮点数来进行绕过。
我们知道,当我们通过GET来进行传参时,+会被视作空格处理,因此,我们可以采用八进制来成功绕过


WEB96

源代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
(?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-18 19:21:24
# @link: https://ctfer.com

*/


highlight_file(__FILE__);

if(isset($_GET['u'])){
if($_GET['u']=='flag.php'){
die("no no no");
}else{
highlight_file($_GET['u']);
}


}

要求我们引入flag.php,同时,不能让文件包含flag.php,因此我们可以使用filter协议来读取
php://filter/convert.base64-encode/resource=flag.php,将读取内容解码后,即可顺利得到flag


WEB97

源代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
(?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-18 19:36:32
# @link: https://ctfer.com

*/

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.';
}
?)

本题需要我们进行md5的绕过,对于md5的比较,有以下几点;

  • 1.弱比较(==):
    若两个字符串的md5值都是0e开头,而且后面全是数字,那么使用这两个字符串的md5值比较的话就会得到相等的结果,例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    s878926199a
    0e545993274517709034328855841020
    s155964671a
    0e342768416822451524974117254469
    s214587387a
    0e848240448830537924465865611904
    s214587387a
    0e848240448830537924465865611904
    s878926199a
    0e545993274517709034328855841020
    s1091221200a
    0e940624217856561557816327384675
    s1885207154a
    0e509367213418206700842008763514
    s1502113478a
    0e861580163291561247404381396064
    s1885207154a
    0e509367213418206700842008763514
    s1836677006a
    0e481036490867661113260034900752
    s155964671a
    0e342768416822451524974117254469
    s1184209335a
    0e072485820392773389523109082030
    s1665632922a
    0e731198061491163073197128363787
    s1502113478a
    0e861580163291561247404381396064
    s1836677006a
    0e481036490867661113260034900752
    s1091221200a
    0e940624217856561557816327384675
    s155964671a
    0e342768416822451524974117254469
    s1502113478a
    0e861580163291561247404381396064
    s155964671a
    0e342768416822451524974117254469
    s1665632922a
    0e731198061491163073197128363787
    s155964671a
    0e342768416822451524974117254469
    s1091221200a
    0e940624217856561557816327384675
    s1836677006a
    0e481036490867661113260034900752
    s1885207154a
    0e509367213418206700842008763514
    s532378020a
    0e220463095855511507588041205815
    s878926199a
    0e545993274517709034328855841020
    s1091221200a
    0e940624217856561557816327384675
    s214587387a
    0e848240448830537924465865611904
    s1502113478a
    0e861580163291561247404381396064
    s1091221200a
    0e940624217856561557816327384675
    s1665632922a
    0e731198061491163073197128363787
    s1885207154a
    0e509367213418206700842008763514
    s1836677006a
    0e481036490867661113260034900752
    s1665632922a
    0e731198061491163073197128363787
    s878926199a
    0e545993274517709034328855841020
    240610708
    0e462097431906509019562988736854
    314282422
    0e990995504821699494520356953734
    571579406
    0e972379832854295224118025748221
    903251147
    0e174510503823932942361353209384
    1110242161
    0e435874558488625891324861198103
    1320830526
    0e912095958985483346995414060832
    1586264293
    0e622743671155995737639662718498
    2302756269
    0e250566888497473798724426794462
    2427435592
    0e067696952328669732475498472343
    2653531602
    0e877487522341544758028810610885
    3293867441
    0e471001201303602543921144570260
    3295421201
    0e703870333002232681239618856220
    3465814713
    0e258631645650999664521705537122
    3524854780
    0e507419062489887827087815735195
    3908336290
    0e807624498959190415881248245271
    4011627063
    0e485805687034439905938362701775
    4775635065
    0e998212089946640967599450361168
    4790555361
    0e643442214660994430134492464512
    5432453531
    0e512318699085881630861890526097
    5579679820
    0e877622011730221803461740184915
    5585393579
    0e664357355382305805992765337023
    6376552501
    0e165886706997482187870215578015
    7124129977
    0e500007361044747804682122060876
    7197546197
    0e915188576072469101457315675502
    7656486157
    0e451569119711843337267091732412
    QLTHNDT
    0e405967825401955372549139051580
    QNKCDZO
    0e830400451993494058024219903391
    EEIZDOI
    0e782601363539291779881938479162
    TUFEPMC
    0e839407194569345277863905212547
    UTIPEZQ
    0e382098788231234954670291303879
    UYXFLOI
    0e552539585246568817348686838809
    IHKFRNS
    0e256160682445802696926137988570
    PJNPDWY
    0e291529052894702774557631701704
    ABJIHVY
    0e755264355178451322893275696586
    DQWRASX
    0e742373665639232907775599582643
    DYAXWCA
    0e424759758842488633464374063001
    GEGHBXL
    0e248776895502908863709684713578
    GGHMVOE
    0e362766013028313274586933780773
    GZECLQZ
    0e537612333747236407713628225676
    NWWKITQ
    0e763082070976038347657360817689
    NOOPCJF
    0e818888003657176127862245791911
    MAUXXQC
    0e478478466848439040434801845361
    MMHUWUV
    0e701732711630150438129209816536

  • 2.强比较(===):
    在 PHP5 和 PHP7 中,当两个 md5 进行比较时,若参数是不同的数组,那么 == 和 === 比较的结果均为 True

  • 3.其他情况
    只能进行md5的碰撞了:
    利用 fastcoll 进行 md5 碰撞,可以生成两个字面值不同但 md5 相同的文件
    使用方法:将空文件拖在exe上即可

本题使用数组绕过即可


WEB98

源代码如下;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
(?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-18 21:39:27
# @link: https://ctfer.com

*/

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__);

?)
  • 在这里,首先我们要介绍一下php的三元运算符:
    1
    2
    (语句一)?(语句二):(语句三);
    //这句三元语句表示,当语句一的结果为真时,执行语句二;否则,执行语句三
    当然,三元运算符也可以叠加运算,多个执行语句可以使用用字符串运算符号(“.”)连接起来,各执行语句用小角括号包围起来以表明它是一个独立而完整的执行语句
    1
    2
    (语句一)?(语句二).(语句二.二):(语句三).(语句三.二);
    //这句三元语句表示,当语句一的结果为真时,执行语句二、二.二;否则,执行语句三、三.三
    当然,三元运算符也可以进行嵌套操作,但因为嵌套后代码可读性下降,代码后期维护成本增加,故此不做讨论
  • 其次,我们要介绍一下php的传值引用
      1. 变量的引用赋值: $a = &$b
      1. 函数调用时的引用参数传递
        1. 早期php是在调用时通过&符号传递引用类型的变量, 比如: func(&$arg);
        1. 后来, 函数的引用类型参数被规定为需要在函数声明时定义, 比如: function func(&$arg);
          注: 引用声明时定义引用类型参数后, 运行时引用参数传递被废弃, 需要在php.ini中增加allow_call_time_pass_reference来开启.
      1. 函数返回引用类型, 这种应用方式需要声明函数时, 在函数名前增加&符号, 并且, 在调用时, 要用引用赋值方式
  • 带入本题进行查看,$_GET?$_GET=&$_POST:'flag';如果有GET存在,那么他将会引用POST的值,然后highlight_file($_GET['HTTP_FLAG']=='flag'?$flag:__FILE__);最后的对比又有和flag的对比,因此我们只要在$_GET给一个flag的参数,然后再$_POST中给一个HTTP_FLAG=flag即可

WBE99

源代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-18 22:36:12
# @link: https://ctfer.com

*/

highlight_file(__FILE__);
$allow = array();
for ($i=36; $i < 0x36d; $i++) {
array_push($allow, rand(1,$i));
}
if(isset($_GET['n']) && in_array($_GET['n'], $allow)){
file_put_contents($_GET['n'], $_POST['content']);
}

?>

先介绍几个函数:

    1. array_push() 将 array 当成一个栈,并将传入的变量压入 array 的末尾。array 的长度将根据入栈变量的数目增加。
    1. rand( int $min, int $max)生成一个随机的[min,max]之间的整数
    1. file_put_contents( string $filename, mixed $data[, int $flags = 0[, resource $context]] ) — 将一个字符串写入文件
    • filename:要被写入数据的文件名。
    • data要写入的数据。类型可以是 string,array 或者是 stream 资源(如上面所说的那样)。
    • 如果 data 指定为 stream 资源,这里 stream 中所保存的缓存数据将被写入到指定文件中,这种用法就相似于使用 stream_copy_to_stream() 函数。
    • 参数 data 可以是数组(但不能为多维数组),这就相当于 file_put_contents($filename, join(‘’, $array))。
      本题要通过最后一句来进行flag的读取,file_put_contents()会将GET的作为文件名,将POST的content写入n中,因此我们只需要传入n=1.php,然后再content中传入我们想执行的php代码即可,最后访问1.php即可得到flag

WBE100

源代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 <?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-21 22:10:28
# @link: https://ctfer.com

*/

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");
}
}
}
?>

  • is_numeric — 检测变量是否为数字或数字字符串,如果是数字或者数字字符串返回TURE,否则返回FALSE
  • php运算符优先级:因为赋值运算的优先级比AND和OR的高,所以先赋值;比&&和||的低,所以逻辑运算符先执行,先逻辑运算,再赋值
  • var_dump — 打印变量的相关信息

payload:?v1=1&v2=var_dump($ctfshow)&v3=;成功读取
$flag_is_281084bd0x2dfbc20x2d490f0x2db7d10x2d9bcfb1fdc203注意此时flag需要将后面那一串字符串中的0x2d转为-后,包上ctfshow后提交


web101

源代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-22 00:26:48
# @link: https://ctfer.com

*/

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("/\\\\|\/|\~|\`|\!|\@|\#|\\$|\%|\^|\*|\)|\-|\_|\+|\=|\{|\[|\"|\'|\,|\.|\;|\?|[0-9]/", $v2)){
if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\\$|\%|\^|\*|\(|\-|\_|\+|\=|\{|\[|\"|\'|\,|\.|\?|[0-9]/", $v3)){
eval("$v2('ctfshow')$v3");
}
}

}

?>

在本题中,可以看到v2和v3都被过滤的比较狠,所以我们需要使用反射类来进行本题的求解

    1. 什么是反射
      反射在每个面向对象的编程语言中都存在,它的主要目的就是在运行时分析类或者对象的状态,导出或提取出关于类、方法、属性、参数等的详细信息,包括注释。 反射是操纵面向对象范型中元模型的 API,可用于构建复杂,可扩展的应用。反射在日常的 Web 开发中其实用的不多,更多的是在偏向底层一些的代码中,比如说框架的底层中依赖注入、对象池、动态代理、自动获取插件列表、自动生成文档以及一些设计模式等等,都会大量运用到反射技术。
      PHP 的反射 API 很多,但是常用的一般都是 ReflectionClass 和 ReflectionMethod
    1. ReflectionClass
      它可以用来获取类的信息:
      • ReflectionClass::getMethods 获取方法的数组
      • ReflectionClass::getName 获取类名
      • ReflectionClass::hasMethod 检查方法是否已定义
      • ReflectionClass::hasProperty 检查属性是否已定义
      • ReflectionClass::isAbstract 检查类是否是抽象类(abstract)
      • ReflectionClass::isFinal 检查类是否声明为 final
      • ReflectionClass::isInstantiable 检查类是否可实例化
      • ReflectionClass::newInstance 从指定的参数创建一个新的类实例
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        42
        43
        44
        45
         <?php
        class hacker{
        public $hackername = "yn8rt";
        const yn8rt='nb666';
        public function show(){
        echo $this->name,'<br>';
        }
        }
        //有这么一个hacker类,假设我们不知道这个类是干什么用的,我们需要知道类里面的信息,这时候就需要用到ReflectionClass来对类进行反射
        //现在我可以通过反射来获取这个类中的方法,属性,常量

        //通过反射获取类的信息

        $reflection = new ReflectionClass('hacker');//实例化反射对象,映射hacker类的信息
        $consts = $reflection->getConstants();//获取所有常量
        $props = $reflection->getProperties();//获取所有属性
        $methods = $reflection->getMethods();//获取所有方法
        var_dump($consts);
        var_dump($props);
        var_dump($methods);
        ?>

        返回值:
        array(1) {
        ["yn8rt"]=>
        string(5) "nb666"
        }
        array(1) {
        [0]=>
        &object(ReflectionProperty)#2 (2) {
        ["name"]=>
        string(10) "hackername"
        ["class"]=>
        string(6) "hacker"
        }
        }
        array(1) {
        [0]=>
        &object(ReflectionMethod)#3 (2) {
        ["name"]=>
        string(4) "show"
        ["class"]=>
        string(6) "hacker"
        }
        }
        ** 如果没有指定方法的话,就会像题目中默认输出很多东西:
        * 1.常量 Contants
        * 2.属性 Property Names
        * 3.方法 Method Names静态
        * 4.属性 Static Properties
        * 5.命名空间 Namespace
        * 6.Person类是否为final或者abstract
        * 7.Person类是否有某个方法
      1. ReflectionMethod
        它主要是针对方法的反射:
      • ReflectionMethod::invoke 执行
      • ReflectionMethod::invokeArgs 带参数执行
      • ReflectionMethod::isAbstract 判断方法是否是抽象方法
      • ReflectionMethod::isConstructor 判断方法是否是构造方法
      • ReflectionMethod::isDestructor 判断方法是否是析构方法
      • ReflectionMethod::isFinal 判断方法是否定义 final
      • ReflectionMethod::isPrivate 判断方法是否是私有方法
      • ReflectionMethod::isProtected 判断方法是否是保护方法 (protected)
      • ReflectionMethod::isPublic 判断方法是否是公开方法
      • ReflectionMethod::isStatic 判断方法是否是静态方法
      • ReflectionMethod::setAccessible 设置方法是否访问

因此我们可以构造payload:?v1=1&v2=echo new ReflectionClass&v3=;,但是! 这个题目只能取出出来35位flag,最后一位需要我们使用爆破才可以得到(十六进制)


web102

源代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php

/*
# -*- coding: utf-8 -*-
# @Author: atao
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-23 20:59:43

*/


highlight_file(__FILE__);
$v1 = $_POST['v1'];
$v2 = $_GET['v2'];
$v3 = $_GET['v3'];
$v4 = is_numeric($v2) and is_numeric($v3);
if($v4){
$s = substr($v2,2);
$str = call_user_func($v1,$s);
echo $str;
file_put_contents($v3,$str);
}
else{
die('hacker');
}
?>

题目中含有以下几个函数:
* 1. substr — 返回字符串的子串string substr( string $string, int $start[, int $length] )
* 2. call_user_func — 把第一个参数作为回调函数调用mixed call_user_func( callable $callback[, mixed $parameter[, mixed $...]] )
* 3. file_put_contents — 将一个字符串写入文件int file_put_contents( string $filename, mixed $data[, int $flags = 0[, resource $context]] )
本题是一个特殊的构造,在php语句$v4 = is_numeric($v2) and is_numeric($v3)中,我们要保证v2是数字才能继续运行下去(由于=的优先级高于and,因此v3任意可控),而从底下call_user_func()中我们可以知道,v1和s都是可控的。由于题目版本是php7,因此is_numberic只能识别带e的字符串,从而引出了我们这道题目特殊的构造手段:

  • 1.使用<?=\cat *`;作为恶意代码,使用base64加密后,得到PD89YGNhdCAqYDs=由于等于号为补位符号,因此可以删去,使用bin2hex得到5044383959474e6864434171594473,为一个只有字母e的数字字符串,因此这串字符可以通过is_numeric的检测顺利传入 最终payload:?v2=215044383959474e6864434171594473&v3=php://filter/write=convert.base64-decode/resource=1.phpPOST:v1=hex2bin`

web103

源代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?php

/*
# -*- coding: utf-8 -*-
# @Author: atao
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-23 21:03:24

*/


highlight_file(__FILE__);
$v1 = $_POST['v1'];
$v2 = $_GET['v2'];
$v3 = $_GET['v3'];
$v4 = is_numeric($v2) and is_numeric($v3);
if($v4){
$s = substr($v2,2);
$str = call_user_func($v1,$s);
echo $str;
if(!preg_match("/.*p.*h.*p.*/i",$str)){
file_put_contents($v3,$str);
}
else{
die('Sorry');
}
}
else{
die('hacker');
}

?>

上一问payload还可以打通


web104

源代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php

/*
# -*- coding: utf-8 -*-
# @Author: atao
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-28 22:27:20

*/


highlight_file(__FILE__);
include("flag.php");

if(isset($_POST['v1']) && isset($_GET['v2'])){
$v1 = $_POST['v1'];
$v2 = $_GET['v2'];
if(sha1($v1)==sha1($v2)){
echo $flag;
}
}
?>

做了半天发现出不来,结果是v1 v2地址放反了
没难度,直接传俩相同的即可
某些特殊的字符加密之后以0e开,php会将其当作科学计数法处理从而判定相等

1
2
3
4
5
6
10932435112: 0e07766915004133176347055865026311692244
aaroZmOk: 0e66507019969427134894567494305185566735
aaK1STfY: 0e76658526655756207688271159624026011393
aaO8zKZF: 0e89257456677279068558073954252716165668
aa3OFF9m: 0e36977786278517984959260394024281014729
0e1290633704: 0e19985187802402577070739524195726831799

web105

源代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php

/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-28 22:34:07

*/

highlight_file(__FILE__);
include('flag.php');
error_reporting(0);
$error='你还想要flag嘛?';
$suces='既然你想要那给你吧!';
foreach($_GET as $key => $value){
if($key==='error'){
die("what are you doing?!");
}
$$key=$$value;
}foreach($_POST as $key => $value){
if($value==='flag'){
die("what are you doing?!");
}
$$key=$$value;
}
if(!($_POST['flag']==$flag)){
die($error);
}
echo "your are good".$flag."\n";
die($suces);

?>