Commit Graph
4 Commits
Author SHA1 Message Date
Christiano Haesbaert 42d7e7a402 Fix multiple vulnerabilities in the resolver
This fixes some vulnerabilities in the resolver that make spoofing DNS
queries somewhat trivial due to the code failing to randomize xid, as
well as match the reply xid with the query, and the origin of the packet:

 - xid of the query was fixed at zero
 - xid from the reply was never checked
 - source address of the reply was never checked

This means anyone can flood the host with a fake reply with xid 0,
guessing the source port is trivial as it's less than 16bits (2^16 -
1024), which would cause odin to resolve a hostname to whatever an
attacker wanted.

While here also plug in two memory leaks.

Since this is CVE material, I've contacted @kelimion before hand which
instructed to put it in a PR.

There are also more bugs as the code conflates answer section,
authority section and aditional section into one, while in reality
only the anwer section should be taken into consideration.
2025-02-23 17:28:32 +01:00
Christiano Haesbaert cd53949c92 Cleanup allocated dns runtime data
While harmless, the runtime should clean up non-user allocated data.
On the same veign of: https://github.com/odin-lang/Odin/pull/4680

I'm kinda new to Odin and wrote netcat, in order to get a clean valgrind run,
one has to manually destroy dns_configuration:
https://github.com/haesbaert/learn-odin/blob/main/netcat/netcat.odin#L168-L169

While here unexport the destroy procedure and make destruction idempotent.
2025-02-09 00:26:25 +01:00
Christiano Haesbaert 605527f9db Fix some compression bugs in dns.
- A compression pointer is when the two higher bits are set, the code was
   considering only 0xC0 as a pointer, where in reality anything from 0xC0-0xFF is
   a pointer, probably went unnoticed since you need big packets to have long pointers.
 - Make sure we can access the lower byte of the pointer by checking len, the
   code was careful to not access past the first byte, but ignored the second.
 - As per RFC9267 make sure a pointer only points backwards, this one is not so
   bad, as the code had a iteration_max that ended up guarding against infinite jumps.

Lightly tested, some eyes are welcome, but these are remote DOSable.
2025-02-09 00:00:11 +01:00
Christiano Haesbaert 5699c533c6 Add net.dial_tcp_from_host{_or_endpoint} and unify them
The main motivation for this is to have sinergy with flags parsing, currently
flags for a sockaddr returns a net.Host_Or_Endpoint, but we can't just dial
from it since there isn't a variant.

Consider the following:

```
Options :: struct {
	target: net.Host_Or_Endpoint `args:"pos=0,required" usage:"host:port"`,
}

before :: proc() -> (sock: net.TCP_Socket, err: net.Network_Error) {
	opt: Options

	flags.parse_or_exit(&opt, os.args)
	switch t in opt.target {
	case net.Host:
		sock, err = net.dial_tcp(t.hostname, t.port)
	case net.Endpoint:
		sock, err = net.dial_tcp(t)
	}
	return
}

after :: proc() -> (sock: net.TCP_Socket, err: net.Network_Error) {
	opt: Options

	flags.parse_or_exit(&opt, os.args)
	sock, err = net.dial_tcp(opt.target)
	return
}

```

For completion, add dial_tcp_from_host() and define the upper functions in terms
of the newly added ones, cuts one repeated block, now:

from_hostname_and_port_string is parse + from_host_or_endpoint
from_hostname_with_port_override is parse + override + from_host_or_endpoint
from_host is to_endpoint + from_endpoint
from_host_or_endpoint is from_endpoint or from_host
2025-01-12 02:41:35 +01:00