江苏工匠杯file_include 解题记录

解题环境依旧是攻防世界的靶场 解题思路 这道题涉及到一个我自己较少接触到的知识点,就是php的转换过滤器。其实大体思路就是用convert过滤器的不同方法来尝试出被check.php拦截的关键字,达到用特殊编码输出的目的 题目分析 进来后可以看到如下界面 首先猜测flag在flag.php中 根据经验可以很容易知道,check.php里可能含有字符串过滤 先使用下面这句常规的base64编码读取 ?filename=php://filter/read=convert.base64-encode/resource=check.php 可以看到确实存在过滤的字符串,但由于check.php本身无法被查看,所以只能另寻他路 在php官网中查找到有关字符串过滤的string过滤器,可以看到有很多字符串转换的方式来读取出flag.php或是check.php中的内容,尝试官网中的第一种rot13()方法,但也同样遭到了和上面一样的拦截 所以只能把目光转向另一种过滤器,也就是转换过滤器 这种过滤器有一种特殊的方法也就是iconv 由于文中提到这种方式等同于用 iconv() 处理所有的流数据,所以点进iconv()函数的页面就能得知它的具体用处和用法 由于这里提到字符串编码,所以可以通过查询php所支持的字符串编码形式,结合暴力破解来确定可以使用哪种编码 这里就不演示burp暴力破解结果,经过测试后可行方案有多种,任选一种即可。这里我选择其中一种来构造查询语句 ?filename=php://filter//convert.iconv.SJIS*.UCS-4*/resource=check.php 结果如下 就可以看到被过滤的字符串有哪些。现在只要将check修改为flag即可

February 19, 2023 · 1 min · Red

XUJC LAB V1.0 内测

目前正在完善功能,欢迎有意向参与改进计划的联系我 首页 题目 公告 排行榜 网址:XUJC LAB

January 20, 2023 · 1 min · Red

关于POST包格式问题&&php伪协议之fitler目录要求

POST包 昨天在写一道题时要求采用POST方式提交一个值(具体是哪题给忘了,没记录),但根据要求提交cookie后发现并没有返回flag,查看了WriteUp后感觉方法并没有错,但就不知道是哪里出了问题。 直到我回想起一句忘了从哪看来的话:POST包由空行来区分head和body 经过百度后,发现确实如此,并且严格来讲是\r\n\r\n作为分隔符。可以参考下面这篇博客 网络协议学习——HTTP协议POST方法的格式 这么说来,从我上面那个包来看,只有一个空行,而即便body不需要添加也必须要用一行来表示,因此这个问题算是得到了解决 为了方便大家查阅使用,这里也附上一个POST包的模板 POST /flag.php HTTP/1.1 Host: 127.0.0.1 Content-Length: 36 Content-Type: application/x-www-form-urlencoded 可以根据自己需要来修改Content-Type、Host等属性。 php://fitler fitler方法可以结合 file_get_content()函数用来打开我们需要查看的文件,但通常情况下需要结合base64过滤器。当然,如果允许的话,不添加也是可以的。 这里主要是想记录一下resource后面跟的目录可以是相对也可以是绝对 这里也给大家一个博客参考一下 探索php://filter在实战当中的奇技淫巧

January 18, 2023 · 1 min · Red

江苏工匠杯easyphp 解题记录

今天碰到这题,感觉有很多知识点,就决定记录一下 这里我用的是攻防世界的靶场 easyphp——攻防世界 题目分析 上来就分析php代码,那就逐行看一下,可以知道最终目的是要使key1和key2都是1 发现文末有一行Emmm...,再根据上面代码推断即可知道是第一个if判断没有进入导致的 而要进入也很简单,先来看一下代码 if(isset($a) && intval($a) > 6000000 && strlen($a) <= 3) 可以看到a不能为空,同时要在字符数量小于等于3的情况下大于6000000,因此容易想到利用科学计数法。 构造第一个payload a=6e9 接着看第二个if md5推算 if(isset($b) && '8b184b' === substr(md5($b),-6,6)) 可以看到第二个if需要利用md5解码,先去看一下8b184b对应字符串。这里我们可以通过简单的Python脚本来解决这个哈希碰撞 import random import hashlib value = "8b184b" while 1: plainText = random.randint(10**11, 10**12 - 1) plainText = str(plainText) MD5 = hashlib.md5() MD5.update(plainText.encode(encoding='utf-8')) cipherText = MD5.hexdigest() if cipherText[-6:]==value : print("碰撞成功:") print("密文为:"+cipherText) print("明文为:"+plainText) break else: print("碰撞中.....") 密文:842fc2485a1faa0681f78d3e098b184b 明文:792616362347 可以得到结果。但考虑到计算量比较大,所以对代码进行一些简化,只截取8b184b这部分进行判断,不做满位拓展 import hashlib for i in range(1000000): m2 = hashlib.md5() m2.update(str(i).encode()) if m2.hexdigest()[-6:] == "8b184b": print(i) break 得到结果为53724,计算量明显缩小 ...

January 18, 2023 · 1 min · Red

SSRF之gopher协议使用与URL编码转换问题

前两天在写一道cthub上的一道SSRF题,其中题目提示到使用post请求以及一些提示 自己尝试没法写出来后,就去网上找write up 但是找出来的write up大多不尽人意,尤其是在下面几个问题的解释上十分混乱 gopher协议在提交post请求时的编码规定 为什么要对post请求进行URL编码多次 到底要编码几次 一生要强的我就决定试试能不能自己搞懂 分析 我就以下面三篇博客作为引例记录一下 CTFhub-ssrf-POST请求 CTFHUB-SSRF-POST请求(小宇特详解) CTFHub-技能树-SSRF POST请求 如果需要看正确解题步骤可以参考第一篇博客,这里我主要分析一下其中的正确原理 第一篇博客中认为URL编码两次即可,其中他的提交条件和理由为: 在index.php页面提交 因为gopher提交post本身需要进行URL编码,并且curl进行请求发送之前会进行URL解码,所以需要进行两次编码 浏览器为Chrome 第二篇博客中认为URL编码需要编码三次,其中他的提交条件和理由为: 在302.php页面使用BP进行提交 具体为什么需要进行三次编码的原因没有说明 浏览器为Firefox 第三篇博客中认为URL编码需要编码两次,其中他的提交条件和理由为: 在index.php页面提交 具体为什么需要进行两次编码的原因没有说明 浏览器不明 三篇博客相同之处在于都有提到换行符%0d%0a的转换,但具体是为什么而转换,除了第一篇稍微提到以外,另外两篇并没有提及。 有趣的是,第三篇的题面和前两篇似乎并不一样,第二篇在过程中并不能正常访问302.php,而最后拿到flag时根据所给截图来看,靶机也已经过期销毁。而我自己去使用他所提供的方法时,发现也是404。 为了解决这个疑惑,我还到ctfhub官方群上问了一下 解决 接下来我就从gopher协议格式、php编码自动转换两个方面来介绍一下 Gopher协议原理和限制介绍 这篇博客同样是从SSRF的角度,来介绍gopher协议,里面清楚地提到了将换行符转换成%0d%0a是gopher协议本身规定,并非像第一篇题解说的是因为“windows和linux之间的不同”。而且两次编码转换的原因也在这篇文中有提到,原因就是在curl_exce()函数调用前就已经存在解码,而发送gopher协议需要对请求方式进行URL编码才能正常发送,所以才需要两次。更多关于gopher协议使用的具体内容可以参考一下这篇博客。 既然两次编码问题得到了解决,那么解码是在哪里发生的呢?如果单看上面这篇博客也还是不能得到这个问题的最终答案。 因此又经过的大量的查阅后,我又发现了这篇博客 http请求(GET/POST)时,url/参数编码的过程分析 答主提到了由于php在使用$_GET等接收方式储存前会按照URL规范对URL进行处理,因此我们可以理解成每在不同文件中使用$_GET等方式接收各种提交时php都会对其进行一次解码。 而为了证明这一点,我也进行了一次测试,来看看在php中是不是真的 实验 先来看一下我构造的php代码 <?php error_reporting(0); print_r($_REQUEST['url']);echo "<br/>"; print_r($_GET['url']);echo "<br/>"; print_r($_POST['url']);echo "<br/>"; $ch=$_GET['url']; $r=curl_init($ch); print_r($r); //print_r($r); ?> 首先我模拟一个跟那道ctfhub上的题目差不多payload的gopher协议,先将原文直接在这个页面发起一个假gopher请求看一下URL从浏览器传入php的结果 可以看到显示内容确实和输入的一样,但浏览器已经进行了一次编码。接着将浏览器编码完的POST请求部分复制下来到在线编码器上再编码一次并提交 可以看到,传入一个php文件后确实只对URL进行了一次解码。接下来将index.php改为具有重定向功能,并继续构造flag.php index.php <?php $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $_REQUEST['url']); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_exec($ch); curl_close($ch); ?> flag.php <?php print_r($_REQUEST['url']); ?> 因为URL地址栏不允许输入太长的内容,所以这里我就只在在线转码器中转换了这一句:Content-Type: application/x-www-form-urlencoded 结果如图 因此就能得到上面总结的结论 ...

January 13, 2023 · 1 min · Red