发出不带正斜杠的 HTTP 请求

问题描述 投票:0回答:3

我在 Apache 访问日志中发现了一个奇怪的 HTTP 请求:

“获取 www.example.com HTTP/1.0”

使用浏览器(Waterfox、Firefox 或 Chrome(按顺序))或 PuTTY/cURL|终端如何重现此 HTTP 请求?最好是

localhost
,因为我可以实时看到日志。

我做了一些阅读,显然 cURL 只能发出绝对 URL 请求。我也无法通过 Waterfox 的“网络”面板中的“编辑并重新发送”来重现此情况。此请求触发了一些我希望在系统中修复的小错误。

apache http url curl
3个回答
4
投票

在终端中执行任何请求都非常容易

你可以

  • 在端口 80 上使用 telnet
    telnet 127.0.0.1 80
    。然后你必须编写请求(你可能需要快速输入,服务器可能会因为结尾行错误而拒绝你 代替 )
  • 要绕过 telnet 限制,您可以首先使用简单的
    printf
    :
  • 编写您的请求
# regular HTTP query
printf 'GET / HTTP/1.0\r\nHost: www.example.com\r\n\r\n'
# or the 'absolute url' mode
printf 'GET www.example.com HTTP/1.0\r\n\r\n'
# or even the official absolute uri mode, I think that's the correct one
printf 'GET http://www.example.com/ HTTP/1.0\r\n\r\n'

但是

printf
echo
是一样的,有特殊的字符处理(如
\r\n
)。所以你必须复制结果并将其粘贴到telnet。

我更喜欢使用

netcat
(有时称为
nc
)来管理 tcp/ip 套接字连接而不是 telnet,并使用管道将 printf 结果直接放入 tcp/ip 套接字(如果您需要 https,您将拥有使用 openssl_client 而不是 netcat)。那是:

printf 'GET www.example.com HTTP/1.0\r\n\r\n' | nc -q 3 127.0.0.1 80
# or
printf 'GET http://www.example.com/ HTTP/1.0\r\n\r\n' | nc -q 3 127.0.0.1 80

这就是您的低技术浏览器。优点是能够编写任何类型的错误查询。 RFC 中存在用于代替第一个标头中的位置的绝对 url,以处理与非常旧的 HTTP 0.9 的兼容性:

# HTTP 0.9
printf 'GET www.example.com/foo/bar \r\n' | nc -q 3 127.0.0.1 80

在此请求中,要使用的正确 VirtualHost 是来自该位置的虚拟主机,而不是来自 Host 标头的虚拟主机:

# regular HTTP query
printf 'GET http://www.vhost2.com/foo HTTP/1.0\r\nHost: www.vhost1.com\r\n\r\n' |\
  nc -q 3 127.0.0.1 80

这是 2013 年 James Kettle 的 Host 头球攻击的基础。因此,我建议您有效跟踪小事件并修复它们。学习如何在服务器中注入任何特殊的 URL 总是好的。

您也可以使用curl发送精心设计的请求,但根据定义,真正的浏览器和命令行浏览器往往会避免发送精心设计的请求。

在处理大量此类服务时,在跟踪哪个服务器或代理发生故障时,从终端跟踪 HTTP 服务器的真实响应也非常有效。学习如何在 tcp 套接字中进行 HTTP 通信,无需使用curl,这非常有用。


0
投票

首先安装Telnet。

然后将以下内容复制并粘贴到终端窗口中:

telnet localhost 80

GET www.example.com HTTP/1.0

按 Enter 两次。

这就是我的访问日志中的样子:

::1 - - [30/Oct/2020:23:37:28 -0700] "GET www.example.com HTTP/1.0" 400 310

您也可以使用 PHP 来完成此操作。这是我创建的一个名为 test.php 的文件:

<?php
$fp = stream_socket_client("tcp://localhost:80", $errno, $errstr, 30) or die("$errstr ($errno)");
$request = "GET www.example.com HTTP/1.0\r\n\r\n";
$written = 0;
do {
    $bytes = fwrite($fp, substr($request, $written)) or die('fwrite error');
    $written+= $bytes;
}
while ($written!==strlen($request));
fclose($fp) or die('fclose error');
echo 'Request sent successfully';
exit;

上面做了同样的事情,只是使用 PHP 来完成。使用上述文本创建一个 PHP 文件,将浏览器指向该文件,它应该显示“请求发送成功”,然后检查您的访问日志。

编辑:

如果您需要使用 TLS,请尝试以下操作。再次保存为 test.php 并将浏览器指向此文件:

$fp = fsockopen("tls://localhost", 443, $errno, $errstr, 30) or die("$errstr ($errno)");
$request = "GET www.example.com HTTP/1.0\r\n\r\n";
$written = 0;
do {
    $bytes = fwrite($fp, substr($request, $written)) or die('fwrite error');
    $written+= $bytes;
}
while ($written!==strlen($request));
while (!feof($fp)) {
    echo fgets($fp, 128);
}
fclose($fp) or die('fclose error');
echo 'Request sent successfully';
exit;

0
投票

您可以使用curl(在某种程度上)发布精心设计的请求。 Curl 不验证方法(-X、--request 或 CURLOPT_CUSTOMREQUEST)。因此你可以使用“换行注入”。

这里是我通过 HTTP 发送代理请求的示例,我指示 apache 充当反向代理,为我启动 TLS(当我需要某些 anciet 服务器上的软件能够与仅接受最近的服务器进行通信时,我使用此技术TLS 版本)。

请注意,示例使用

bash
语法来正确插入
CR
LF
字符。

$ curl -v -X "$(echo -en 'GET https://target.domain/actual/path HTTP/1.1\r\nX-Ignore-Injection:' )" my.apache.proxy.example:8080/ignored/path
* Trying 1.2.3.4:8080...
* Connected to my.apache.proxy.example (1.2.3.4) port 8080 (#0)
> GET https://target.domain/actual/path HTTP/1.1
> X-Ignore-Injection: /ignored/path HTTP/1.1
> Host: my.apache.proxy.example:8080
> User-Agent: curl/7.83.0
> Accept: */*
...
© www.soinside.com 2019 - 2024. All rights reserved.