Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    86382836

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

web

passwdstealer

序文

元々はpasswdstealerです:)

テストポイントは、スプリングブートシナリオでのCVE-2024-21733の使用です。

脆弱性の基本原則の参照https://MP.Weixin.QQ.com/s?__biz=mzg2mdy2odc5ma==mid=2247484002IDX=1SN=7936818B93F22D9A656D8ED4848432C0

二度と繰り返しません。

スプリングブートシナリオでの使用

以前の分析は、Tomcat環境でのこの脆弱性の搾取には特定の条件が必要であることを示しています

タイムアウトエラーをトリガーします。これにより、Reset()がサーバー()のループ処理をトリガーするロジックを呼び出し、Tomcatが一度に複数のリクエストを処理し、漏れた機密データをエコーできるようにします。以下は、裸のスプリングブートシナリオでそれを使用する方法を見つけることです。

テスト環境:Springboot V2.6.13、Tomcatは脆弱性バージョン9.0.43に置き換えられ、ルーティングコントローラーは追加されていません。

step1トリガータイムアウト

目的は、read()を投げるioexception 21pvd0dyvaw554.pngを作成することです

リセット()をスキップして、制限の不整列を引き起こします。

上記の分析でPOCを使用するには、CLが実際の値iuzfgd4flc1555.pngを超えるCLを使用したパッケージを投稿します

AAAルートが存在せず、POSTデータがTomcatによって処理されないため、数秒で戻りません。

ここでは、投稿データを処理できるリクエストを見つける必要があります。

ここでは、MultiPart/Form-Dataを使用してデータをアップロードします。

1fjnvy0dzwr556.png

タイムアウトタイムアウトは正常にトリガーされました

step2はループ
に入ります

次に、リクエストがタイムアウト後にhttp11processor.java#service()のループをまだ入力するように、条件2を満たすようにしてください。デバッグ後、これは条件nujy1x41bgb557.pngを満たしていないことがわかりました

KeepAliveはfalseになり、コールスタックを上向きにバックトラックして理由を見つけます。

e4nvvapkwfa558.png e51rqcit0cp559.png

StatusCodeがStatusDropSconnectionにある場合、KeepAliveはfalseに設定されます

バックトラッキングを続けて、ステータスコードが500に設定されている場所を見つけてください。

qtvqackm4md560.png

追いかけて、それをトリガーしたのはservletexceptionであることがわかりますmi1qiewjnz0561.png

フォローアップを続け、最終的にトリガーされたIOExceptionがfileuploadexception tsgqajcwmlt562.pngとしてパッケージ化されたことを見つけます

ここでのIOExceptionは、実際にはDocardBodyDataのときに使い果たされました。捕まっていないので、上位に直接投げられました。ymdcx1kuod4563.png

この時点で、500の生成の理由を見つけました。500の生成からのリクエストを防ぐ方法を探してみましょう。これは、docardbodydata()をioexceptionを投げることなく、タイムアウトを引き起こす可能性があります。

最初に通常のマルチパートパッケージを使用してテストします。

ここにいくつかの境界基準があります

boundary=--- webkitformboundary7ma4ywxktrzu0gwがコンテンツタイプで設定されていると仮定します。

次に------ WebKitFormBoundary7MA4YWXKTRZU0GWは、パーツの始まりを表します(2つの最初の - )

----- webkitformboundary7ma4ywxkttrzu0gw--フォームの終わりを表します(2つは前後に追加されます - )

ここでは、頭と尾fclxhuh5frc564.pngを備えたマルチパートアップロードパッケージを構築します

彼はreadbounddary()に足を踏み入れることができることがわかりました

btobsim4nai565.png

readbounddary()をフォローアップし続けます。上記の境界基準によれば、マーカー[0]=readbyte();最後の2桁を読んでいます - またはCLRFは、境界の終わりのシンボルです。4k5kzzlg54v567.png

しかし、これを行うようにリクエストパッケージを設定した場合、つまり、境界エンドフラグはありませんか?3p5fj5k4qz0568.png

パケットは続き続け、readbyte()がデータを読み取ることができない場合(送信しなかったため)、最終的にfill()を呼び出し、fillにioexception(step1の位置)を引き起こすことがわかります。

sl5ozee0mxa569.png

現時点では、readbyte()はioExceptionを投げますが、読み取りに巻き込まれ、不正なストリームエクセプトとしてパッケージ化されます。

この時点で、私はSkippreamble関数に戻り、MalformedStreamExceptionが捕まえることを発見し、500を引き起こすためにIOExceptionを上方に投げ続けることができなくなりました。

} catch(最終的なMalformedstreamexception e){

falseを返します。この時点で、タイミングを出したが404を返したリクエストパッケージを正常に構築し、404はStatusDropSconnectionに含まれていないため、whileループを入力できます。2sriipmg5zp570.png

step3漏れecho

この手順は、トレースリクエストを使用するために直接使用できます。トレースリクエスト

xpmjia2dou4571.png

end utilization

ここでは、通常のユーザーのヘッダーにフラグを漏らすという目標を設定します。

まず、敏感な情報を内部に含むリクエスト(このリクエスト中に被害者が送信したと仮定して)を送信します。この時点で、入力バッファはこのように見えます。wcnxzmgjor0572.png

攻撃者はリクエストを送信し、通常42rz1guccdi573.pngを返します

この時点で、入力バッファ内の状況はこのようになりました。qjc5yg0r5ub574.png

最後の最も重要なステップは、攻撃者が瞑想的なマルチパートパッケージ13pcgtfwo55575.pngを送信することです

この時点で、マルチパートパッケージがタイムアウトした後、whileループに入り、パッケージの送信を継続します。したがって、Nextrequestの後、入力バッファーは完全なトレースリクエストになり、フラグは元のバッファーを上書きすることによりトレース要求のヘッダーになります。

fdqlceg4nyr576.png

最後に、フラグはトレースのエコーによって得られます。

tm2cidr02c2577.png

ここで手に入れるのはヘッダー情報ですが、実際に体を取得できます。これはもう少し面倒です。被害者パッケージの前にCLRFでいっぱいのパッケージを送信し、事前にバッファーをCLRFで満たし、トレースで要求されたヘッダーとしてボディを上書きします。

ezql

パッケージorg.example;

com.ql.util.express.defaultContextをインポートします。

com.ql.util.express.expressrunnerをインポートします。

com.ql.util.express.config.qleexpressruntrategyをインポートします。

com.sun.net.httpserver.httpserverをインポートします。

com.sun.net.httpserver.httphandlerをインポートします。

com.sun.net.httpserver.httpexchangeをインポートします。

sun.misc.base64decoderをインポートします。

java.io.ioexceptionをインポートします。

java.io.inputStreamをインポートします。

java.io.outputStreamをインポートします。

java.net.inetsocketAddressをインポートします。

java.nio.charset.standardcharsetsをインポートします。

java.util.base64をインポートします。

java.util.hashsetをインポートします。

java.util.listをインポートします。

java.util.setをインポートします。

パブリッククラスメイン{

public static void main(string [] args)throws ioexception {

int port=integer.parseint(system.getenv()。getordefault( 'port'、 '8000'));

httpserver server=httpserver.create(new inetsocketAddress(port)、0);

server.createcontext( '/'、new httphandler(){

@オーバーライド

public voidハンドル(httpexchange req)がioexceptionをスローします{

int code=200;

文字列応答;

string path=req.getRequesturi()。getPath();

if( '/ql'.equals(path)){

試す {

文字列式=getRequestBody(req);

Express=new String(base64.getDecoder()。decode(express));

ExpressRunner Runner=new ExpressRunner();

qleexpressrunstrategy.setforbidinovokesecurityRiskMethods(true);

SetString secureMethods=new Hashset();

securemethods.add( 'java.lang.integer.valueof');

qleexpressrunstrategy.setsecuremethods(securemethods);

DefaultContextString、Object Context=new DefaultContext();

応答='0';

試す {

Response=string.valueof(runner.execute(express、context、(list)null、false、false));

} catch(例外e){

System.out.println(e);

}

//string param=req.getRequesturi()。getQuery();

//response=new initialContext()。lookup(param).toString();

} catch(例外e){

e.printstacktrace();

Response=':(';

}

} それ以外{

コード=404;

応答='見つかりません';

}

req.sendresponseheaders(code、response.length());

outputStream os=req.getResponseBody();

os.write(respons.getBytes());

os.close();

}

});

server.start();

System.out.printf( ':%d%n'、portで聞くサーバー);

}

private static string getRequestBody(httpexchange Exchange)はioExceptionをスローします{

inputStream is=exchange.getRequestBody();

byte [] buffer=new byte [1024];

int bytesRead;

stringbuilder body=new StringBuilder();

while((bytesread=is.read(buffer))!=-1){

body.append(new String(Buffer、0、BytesRead、StandardCharsets.utf_8));

}

return body.toString();

}

}

単純なQL式

解決策1

ソリューション1は、実際には少し予期せぬものに偏っており、Qleexpressionの特徴を忘れています。まず、CB依存関係が付属するActiveMQ依存関係があることに気付きました。したがって、脱力化利用チェーンが確認されています。

2つ目は、脱審成をトリガーする方法です。脱派化のトリガーのための2つのアイデアは簡単ではありません。

TemplatesJndiは後者に属します。JDBCrowsetのセッターメソッドを呼び出してルックアップを押すことができます

com.sun.rowset.idbcrowsetimplをインポートします。

jdbc=new jdbcrowsetimpl();

JDBC.DATASOURCENAME='