public inbox for nncp-devel@lists.stargrave.org
Atom feed
* NNCP path traversal attack.
@ 2025-09-19  4:46 Eugene Medvedev
  2025-09-19  6:28 ` Jonathan Lane
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: Eugene Medvedev @ 2025-09-19  4:46 UTC (permalink / raw)
  To: nncp-devel

[-- Attachment #1: Type: text/plain, Size: 860 bytes --]

As it currently stands, NNCP is vulnerable to path traversal attacks with
freq and file functions: Despite the requirement for both to supply full path
in configuration, both types of packets will accept and act upon paths
containing
"..". Most obviously, this allows one to request any file NNCP has access to,
like its own configuration file with the private keys in it.
Likewise, a sent file can break out of the incoming directory in the same manner
and be written anywhere on the system that the user can write to.

The included patch is my take on dealing with this by by limiting path
traversal to
below the configured full path. It does nothing about, e.g., symlinks,
and I'm not sure anything should be done about those.

I can't claim to understand the codebase sufficiently to have caught
all the ways
this can happen, however.

-- 
Eugene Medvedev

[-- Attachment #2: traversal.patch --]
[-- Type: text/x-patch, Size: 2108 bytes --]

As it currently stands, NNCP is vulnerable to path traversal attacks with
freq and file functions: Despite the requirement for both to supply full path
in configuration, both types of packets will accept and act upon paths containing
"..". Most obviously, this allows one to request any file NNCP has access to,
like its own configuration file with the private keys in it.
Likewise, a sent file can break out of the incoming directory in the same manner
and be written anywhere on the system that the user can write to.

This patch is my take on dealing with this by by limiting path traversal to
below the configured full path. It does nothing about, e.g., symlinks,
and I'm not sure anything should be done about those.

diff -ruN nncp-8.11.0/src/toss.go nncp-8.11.0-patched/src/toss.go
--- nncp-8.11.0/src/toss.go	1970-01-01 03:00:00.000000000 +0300
+++ nncp-8.11.0-patched/src/toss.go	2025-09-18 23:26:07.988137948 +0300
@@ -312,6 +312,17 @@
 			return err
 		}
 		dir := filepath.Join(*incoming, path.Dir(dst))
+		if !strings.HasPrefix(dir, *incoming) {
+			err = errors.New("incoming path traversal")
+			ctx.LogE("rx-traversal", les, err, func(les LEs) string {
+				return fmt.Sprintf(
+					"Tossing file %s/%s (%s): %s: traversal",
+					sender.Name, pktName,
+					humanize.IBytes(pktSize), dst,
+				)
+			})
+			return err
+		}
 		if err = os.MkdirAll(dir, os.FileMode(0777)); err != nil {
 			ctx.LogE("rx-mkdir", les, err, func(les LEs) string {
 				return fmt.Sprintf(
@@ -542,11 +553,26 @@
 			)
 			return err
 		}
+		srcPath := filepath.Join(*freqPath, src)
+		if !strings.HasPrefix(srcPath, *freqPath) {
+			err = errors.New("freqing path traversal")
+			ctx.LogE(
+				"rx-no-freq", les, err,
+				func(les LEs) string {
+					return fmt.Sprintf(
+						"Tossing freq %s/%s (%s): %s -> %s",
+						sender.Name, pktName,
+						humanize.IBytes(pktSize), src, dst,
+					)
+				},
+			)
+			return err
+		}
 		if !opts.DryRun {
 			err = ctx.TxFile(
 				sender,
 				pkt.Nice,
-				filepath.Join(*freqPath, src),
+				srcPath,
 				dst,
 				sender.FreqChunked,
 				sender.FreqMinSize,

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2025-09-19 13:31 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-09-19  4:46 NNCP path traversal attack Eugene Medvedev
2025-09-19  6:28 ` Jonathan Lane
2025-09-19  6:43   ` Eugene Medvedev
2025-09-19 12:02 ` John Goerzen
2025-09-19 12:11   ` Eugene Medvedev
2025-09-19 12:04 ` John Goerzen
2025-09-19 12:31   ` Eugene Medvedev
2025-09-19 13:25 ` Sergey Matveev
2025-09-19 13:30   ` Eugene Medvedev