关于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

Echo战队第12次培训——XXE漏洞和文件包含漏洞

课件下载1 课件下载2

January 11, 2023 · 1 min · Red

Echo战队第13次培训——RCE漏洞

课件下载

January 11, 2023 · 1 min · Red