mirror of
https://github.com/elicpeter/nyx.git
synced 2026-06-09 19:45:13 +02:00
54 lines
1.8 KiB
Ruby
54 lines
1.8 KiB
Ruby
# Phase 08 (Track J.6) — Ruby raw-socket HEADER_INJECTION vuln fixture.
|
|
#
|
|
# Writes the response status line and headers directly to the wire via
|
|
# `socket.write`, bypassing the framework-level CRLF validator that
|
|
# Rack / Sinatra / Rails would otherwise interpose. A payload carrying
|
|
# `\r\nSet-Cookie: ...` splits the single Set-Cookie header into two on
|
|
# the wire, producing the canonical smuggled-second-header shape that
|
|
# `ProbeKind::HeaderWireFrame` is designed to catch.
|
|
#
|
|
# The harness (`src/dynamic/lang/ruby.rs::emit_header_injection_harness`)
|
|
# detects the `TCPServer.new` token in this file and routes through the
|
|
# tier-(b) wire-frame branch: bind a loopback `TCPServer` via
|
|
# `create_server`, accept one client (`run_once`), issue one raw
|
|
# `GET / HTTP/1.0` from the harness, read the bytes the fixture wrote
|
|
# to the response socket up to the CRLF-CRLF boundary, and emit them
|
|
# as a `ProbeKind::HeaderWireFrame` record.
|
|
require 'socket'
|
|
|
|
# Bytes go straight onto the wire with no encoding pass. The harness
|
|
# installs the cookie value before booting the accept loop, mirroring
|
|
# the JS `setCookieValue` and Python `Handler.cookie_value =` setters.
|
|
$nyx_cookie_value = String.new(encoding: 'BINARY')
|
|
|
|
def set_cookie_value(value)
|
|
$nyx_cookie_value = value.respond_to?(:b) ? value.b : value.to_s.b
|
|
end
|
|
|
|
def create_server
|
|
TCPServer.new('127.0.0.1', 0)
|
|
end
|
|
|
|
def run_once(server)
|
|
socket = server.accept
|
|
begin
|
|
socket.recv(4096)
|
|
rescue StandardError
|
|
# ignore client-side read errors
|
|
end
|
|
body = "ok\n".b
|
|
raw = String.new(encoding: 'BINARY')
|
|
raw << "HTTP/1.0 200 OK\r\n".b
|
|
raw << "Content-Length: #{body.bytesize}\r\n".b
|
|
raw << "Set-Cookie: ".b
|
|
raw << $nyx_cookie_value
|
|
raw << "\r\n\r\n".b
|
|
raw << body
|
|
socket.write(raw)
|
|
ensure
|
|
begin
|
|
socket.close if socket
|
|
rescue StandardError
|
|
# ignore close errors
|
|
end
|
|
end
|