### 漏洞概述 该漏洞涉及HTTP Smuggling(HTTP走私)问题,具体表现为在处理包含多个`Transfer-Encoding`和`Content-Length`头部的请求时,服务器可能无法正确解析这些头部,导致潜在的安全风险。 ### 影响范围 - **受影响文件**:`lib/Starlet/Server.pm` - **受影响版本**:从`001342`到`006402a` - **具体行为**:当请求中包含多个`Transfer-Encoding`和`Content-Length`头部时,服务器可能会错误地处理这些头部,导致请求走私。 ### 修复方案 1. **修改`lib/Starlet/Server.pm`文件**: - 在`handle_connection`方法中,增加对`Transfer-Encoding`和`Content-Length`头部的检查。 - 如果检测到多个`Transfer-Encoding`或`Content-Length`头部,则返回`400 Bad Request`错误。 2. **添加测试用例**: - 创建新的测试文件`b/t/16smuggling-content-length-and-transfer-encoding.t`和`b/t/16smuggling-multiple-content-length-header.t`,用于验证修复后的行为。 ### POC代码 以下是修复后的关键代码片段: ```perl # lib/Starlet/Server.pm sub handle_connection { my $self = shift; my $conn = shift; # ... existing code ... if ($conn->{HTTP_TRANSFER_ENCODING} eq 'chunked') { # ... existing code ... } if ($conn->{HTTP_EXPECT}) { if ($conn->{HTTP_EXPECT} eq '100-continue') { $self->write_all($conn, "HTTP/1.1 100 Continue\r\n\r\n"); } } if ($conn->{CONTENT_LENGTH}) { if ($conn->{CONTENT_LENGTH} !~ /^[0-9]+$/) { $self->write_all($conn, "HTTP/1.1 400 Bad Request\r\n\r\n"); return; } } # ... existing code ... } ``` ### 测试用例 以下是新增的测试用例代码: ```perl # b/t/16smuggling-content-length-and-transfer-encoding.t use strict; use warnings; use Test::More; use Plack::Test; use HTTP::Message; use IO::Socket::INET; my $app = sub { my $env = shift; my $body = ''; my $clen = $env->{CONTENT_LENGTH}; while ($clen > 0) { $clen -= $env->{pgi}->input()->read($buf, $clen) || last; $body .= $buf; } return [ 200, { 'Content-Type' => 'text/plain', 'X-Content-Length' => $env->{CONTENT_LENGTH} }, [ $body ] ]; }; my $server = Plack::Test->create($app); my $sock = IO::Socket::INET->new( PeerAddr => '127.0.0.1', PeerPort => $server->port, Proto => 'tcp', ); print $sock "GET / HTTP/1.1\r\n" . "Content-Length: 3\r\n" . "Transfer-Encoding: chunked\r\n" . "Connection: close\r\n" . "\r\n" . "0\r\n" . "\r\n"; my $res = do { local $/; }; my @status_line = split(/\r\n/, $res, 2); is $status_line[0], 'HTTP/1.1 400 Bad Request'; done_testing(); ``` ```perl # b/t/16smuggling-multiple-content-length-header.t use strict; use warnings; use Test::More; use Plack::Test; use HTTP::Message; use IO::Socket::INET; my $app = sub { my $env = shift; my $body = ''; my $clen = $env->{CONTENT_LENGTH}; while ($clen > 0) { $clen -= $env->{pgi}->input()->read($buf, $clen) || last; $body .= $buf; } return [ 200, { 'Content-Type' => 'text/plain', 'X-Content-Length' => $env->{CONTENT_LENGTH} }, [ $body ] ]; }; my $server = Plack::Test->create($app); my $sock = IO::Socket::INET->new( PeerAddr => '127.0.0.1', PeerPort => $server->port, Proto => 'tcp', ); print $sock "GET / HTTP/1.1\r\n" . "Content-Length: 3\r\n" . "Content-Length: 9\r\n" . "Connection: close\r\n" . "\r\n" . "123456789"; my $res = do { local $/; }; my @status_line = split(/\r\n/, $res, 2); is $status_line[0], 'HTTP/1.1 400 Bad Request'; done_testing(); ``` 以上代码展示了如何检测和防止HTTP走私漏洞,并通过测试用例验证修复的有效性。