網鼎杯第四場Some Web Writeup
comment出的還可以,裡面有很多小細節的坑,學習一下。HCoin就比較難受,對此型別題目無思路。
NoWafUpload
這個題目是我以前出在SCTF2018上面的簡版,不過被一些地方坑了一下。
當時一直在用python print
然後進入管道,然後再用linux的md5命令
這個時候會多出一個\x0a
,導致一直算不對,換為sys.stdout.write
輸出就好了
import zlib import hashlib import sys from struct import pack def dec_(file_): f = open(file_,'r').read() f = f[48:] tmp = '' for i in f: tmp += chr(ord(i) ^ ord("\f")) f = zlib.decompress(tmp) return f def enc_(file_): f = open(file_,'r').read() data_dec_len = pack('<Q',len(f)) f = zlib.compress(f) tmp = '' for i in f: tmp += chr(ord(i) ^ ord("\f")) m2 = hashlib.md5() m2.update(tmp) md5_ = m2.hexdigest() data_enc_len = pack('<Q',len(tmp)) enc_data = md5_ + data_dec_len + data_enc_len + tmp return enc_data #print dec_('sdfasgerwtytc.php') print enc_('test.php')
comment
git洩露
console裡面可以看到一些提示: 程式設計師GIT寫一半跑路了,都沒來得及Commit :)
藉此也聊一下git的一些工具以及它們的原理,從目前的測試工具來看,BugScanTeam團隊的GitHack應該是最穩的。
先鋪墊一下基礎,先初始化一個git init
沒有任何東西的GIT目錄
然後只git add
一個檔案,這裡並沒有git commit
在這裡要區分三個概念詞:版本庫、工作區、暫存區(stage),更詳細的內容可以看這篇文章
盜圖一張:
提交一個檔案的時候是分為git add
、git commit
兩步的
當git add
的時候,是把檔案臨時放在臨時區stage中
當git commit
當然這兩個在objects目錄都會生成一個物件檔案,來儲存資料。
可以看下當前目錄結構為如下:
├── HEAD ├── config # 存放git的一些資訊 ├── description ├── hooks ├── index ├── info │ └── exclude ├── objects # 存放物件檔案 │ ├── 0c │ │ └── 14454dd8d472ef27843ac8c86bdba161c27a03 │ ├── info │ └── pack └── refs ├── heads └── tags
其中index的內容其中就包含了一些當前版本下的檔案資訊以及對應的objects目錄下的物件檔案
對於git中的物件,推薦閱讀此文
它包含了Blob物件(用來儲存檔案內容)、Tree物件(表示內容之間的目錄層次關係)、Commit物件(相關的描述資訊)
接下來進行git commit
,多出了0c
、31
兩個目錄
物件用zlib解壓即可看到內容
f = open("14454dd8d472ef27843ac8c86bdba161c27a03","r").read()
import zlib
print zlib.decompress(f)
可以看到下面是新生成了一個tree物件、commit物件
看下commit物件內容,可以找到tree物件的一些資訊
再通過git ls-tree 31d459
檢視到tree物件裡面存放的內容,即一些目錄結構,以及對應的Blob物件的object id,也就是通過tree我們可以找到對應檔案的object id。
所以獲取原始碼的整個過程就是 commit -> tree -> blob
***
接下來我們再多新增一個檔案,進行git add
、git commit
操作
├── objects
│ ├── 0c
│ │ └── 14454dd8d472ef27843ac8c86bdba161c27a03
│ ├── 2b
│ │ └── ccc291c71cc92898645cdc8990056027108580
│ ├── 31
│ │ └── d459eb83ed7f3d9195b2bd24d4e2cbdc7e299c
│ ├── 85
│ │ └── 66ddc152da79a3e2fd4a00123aeea397e574c4
│ ├── 8e
│ │ └── 63e6627218b1e455a5ae4bc45135316cf39055
│ ├── 98
│ │ └── 0411cbd21c224e546111360d20775d62c33349
│ ├── info
│ └── pack
這下新增了2b
、85
、98
三個目錄,分別代表著blob、tree、commit
看下commit的內容
可以看到上面的tree是指向了85/66ddc1
,然後parent是指向了8e6366
的commit,也就是上一次的commit內容
下面就講下Git使用過程中的幾種情況,以及對應如何去恢復程式碼
1、當年git洩露漏洞特別火,lijiejie師傅寫了一個利用工具,流傳大江南北。
因為index是儲存工程中最新狀態的檔案,所以它就是獲取了其中的blob的objects的hash,然後去得到檔案,最後解壓得到原始碼。
對於獲取其他的分支、tag,都可以從/.git/refs/heads
、/.git/refs/tag
裡面拿到最新的commit物件id,然後就是順著這個可以爬到parent commit
假設獲取master,最新的commit的object id可以在/.git/refs/heads/master
獲取到
3、具有場景型,協同合作時,遠端程式碼有更新,即原生代碼不是最新版本。為了避免出現版本衝突可以使用git stash
將這部分暫存起來,然後便可以執行git pull
,暫存的內容便會存放到/.git/refs/stash
,此處我並未使用git commit
╭─[email protected] ~/work/tools/src_tools/test/demo/.git/refs ‹dev›
╰─$ cat stash
e0945bc49106ac493f0d8c3b32370374b2d36a28
所以通過上面的commit我們依舊能夠通過 commit -> tree -> blob
這種模式得到原始碼
4、使用了git reset --hard HEAD
回滾時候
這個時候可以獲取一下/.git/logs/HEAD
檔案,它會記錄所有歷史
比如上面便是reset之前的commit id
5、git gc
,會打包object生成pack檔案。但是有種情況便是git push失敗的時候,一般push時候會打包一下,但是失敗的時候並不會解壓出來
這個場景的話,便可以獲取/.git/objects/info/packs
得到pack檔名
使用git verfy-pack -v xxx.idx
可以看到一些內容資訊
使用git unpack-objects < xxx.pack
便可恢復
注入坑
這裡就可以找一下stash留下的object恢復一下,便可以看到原始碼
printf "\x1f\x8b\x08\x00\x00\x00\x00\x00" | cat - f569f235780f24c42b60f50d528a03f7238c80 | gunzip
比較明顯的二次注入,但是坑就在他是換行的,沒法多行註釋,一下子沒想起這個梗,一直都是#
注入導致很蛋疼。
建立一個CATEGORY
為aaa',content=user(),/*
,然後留言回覆*/#
,便可回顯注入
因為用的是mysql->query
,也可以也能用%00
截斷一下,aaa',content%3d(user()),bo_id%3d'1'%3b%00%23a
還有一種就是利用DUPLICATE KEY
,payload: ',content=database(),bo_id='1' ON DUPLICATE KEY UPDATE category='
參考文章
https://blog.csdn.net/zssureqh/article/details/53056095
https://www.cnblogs.com/lianghe01/p/5846525.html
https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/0013745374151782eb658c5a5ca454eaa451661275886c6000
https://ring0.me/2015/05/recover-code-from-corrupt-git-repo/
https://www.jianshu.com/p/fbc9eca95e26