Compare commits

..

1 Commits

Author SHA1 Message Date
Pterodactyl CI
3c116c190c bump version for release 2023-02-08 02:19:24 +00:00
5 changed files with 18 additions and 138 deletions

View File

@@ -1,13 +1,5 @@
# Changelog # Changelog
## v1.7.5
### Fixed
* CVE-2023-32080
## v1.7.4
### Fixed
* CVE-2023-25168
## v1.7.3 ## v1.7.3
### Fixed ### Fixed
* CVE-2023-25152 * CVE-2023-25152

View File

@@ -381,9 +381,10 @@ func (fs *Filesystem) TruncateRootDirectory() error {
// Delete removes a file or folder from the system. Prevents the user from // Delete removes a file or folder from the system. Prevents the user from
// accidentally (or maliciously) removing their root server data directory. // accidentally (or maliciously) removing their root server data directory.
func (fs *Filesystem) Delete(p string) error { func (fs *Filesystem) Delete(p string) error {
wg := sync.WaitGroup{}
// This is one of the few (only?) places in the codebase where we're explicitly not using // This is one of the few (only?) places in the codebase where we're explicitly not using
// the SafePath functionality when working with user provided input. If we did, you would // the SafePath functionality when working with user provided input. If we did, you would
// not be able to delete a file that is a symlink pointing to a location outside the data // not be able to delete a file that is a symlink pointing to a location outside of the data
// directory. // directory.
// //
// We also want to avoid resolving a symlink that points _within_ the data directory and thus // We also want to avoid resolving a symlink that points _within_ the data directory and thus
@@ -400,65 +401,25 @@ func (fs *Filesystem) Delete(p string) error {
return errors.New("cannot delete root server directory") return errors.New("cannot delete root server directory")
} }
st, err := os.Lstat(resolved) if st, err := os.Lstat(resolved); err != nil {
if err != nil {
if !os.IsNotExist(err) { if !os.IsNotExist(err) {
fs.error(err).Warn("error while attempting to stat file before deletion") fs.error(err).Warn("error while attempting to stat file before deletion")
return err
} }
} else {
// The following logic is used to handle a case where a user attempts to if !st.IsDir() {
// delete a file that does not exist through a directory symlink. fs.addDisk(-st.Size())
// We don't want to reveal that the file does not exist, so we validate } else {
// the path of the symlink and return a bad path error if it is invalid. wg.Add(1)
go func(wg *sync.WaitGroup, st os.FileInfo, resolved string) {
// The requested file or directory doesn't exist, so at this point we defer wg.Done()
// need to iterate up the path chain until we hit a directory that
// _does_ exist and can be validated.
parts := strings.Split(filepath.Dir(resolved), "/")
// Range over all the path parts and form directory paths from the end
// moving up until we have a valid resolution, or we run out of paths to
// try.
for k := range parts {
try := strings.Join(parts[:(len(parts)-k)], "/")
if !fs.unsafeIsInDataDirectory(try) {
break
}
t, err := filepath.EvalSymlinks(try)
if err == nil {
if !fs.unsafeIsInDataDirectory(t) {
return NewBadPathResolution(p, t)
}
break
}
}
// Always return early if the file does not exist.
return nil
}
// If the file is not a symlink, we need to check that it is not within a
// symlinked directory that points outside the data directory.
if st.Mode()&os.ModeSymlink == 0 {
ep, err := filepath.EvalSymlinks(resolved)
if err != nil {
if !os.IsNotExist(err) {
return err
}
} else if !fs.unsafeIsInDataDirectory(ep) {
return NewBadPathResolution(p, ep)
}
}
if st.IsDir() {
if s, err := fs.DirectorySize(resolved); err == nil { if s, err := fs.DirectorySize(resolved); err == nil {
fs.addDisk(-s) fs.addDisk(-s)
} }
} else { }(&wg, st, resolved)
fs.addDisk(-st.Size())
} }
}
wg.Wait()
return os.RemoveAll(resolved) return os.RemoveAll(resolved)
} }

View File

@@ -508,80 +508,6 @@ func TestFilesystem_Delete(t *testing.T) {
} }
}) })
g.It("deletes a symlink but not it's target within the root directory", func() {
// Symlink to a file inside the root directory.
err := os.Symlink(filepath.Join(rfs.root, "server/source.txt"), filepath.Join(rfs.root, "server/symlink.txt"))
g.Assert(err).IsNil()
// Delete the symlink itself.
err = fs.Delete("symlink.txt")
g.Assert(err).IsNil()
// Ensure the symlink was deleted.
_, err = os.Lstat(filepath.Join(rfs.root, "server/symlink.txt"))
g.Assert(err).IsNotNil()
// Ensure the symlink target still exists.
_, err = os.Lstat(filepath.Join(rfs.root, "server/source.txt"))
g.Assert(err).IsNil()
})
g.It("does not delete files symlinked outside of the root directory", func() {
// Create a file outside the root directory.
err := rfs.CreateServerFileFromString("/../source.txt", "test content")
g.Assert(err).IsNil()
// Create a symlink to the file outside the root directory.
err = os.Symlink(filepath.Join(rfs.root, "source.txt"), filepath.Join(rfs.root, "/server/symlink.txt"))
g.Assert(err).IsNil()
// Delete the symlink. (This should pass as we will delete the symlink itself, not it's target)
err = fs.Delete("symlink.txt")
g.Assert(err).IsNil()
// Ensure the file outside the root directory still exists.
_, err = os.Lstat(filepath.Join(rfs.root, "source.txt"))
g.Assert(err).IsNil()
})
g.It("does not delete files symlinked through a directory outside of the root directory", func() {
// Create a directory outside the root directory.
err := os.Mkdir(filepath.Join(rfs.root, "foo"), 0o755)
g.Assert(err).IsNil()
// Create a file inside the directory that is outside the root.
err = rfs.CreateServerFileFromString("/../foo/source.txt", "test content")
g.Assert(err).IsNil()
// Symlink the directory that is outside the root to a file inside the root.
err = os.Symlink(filepath.Join(rfs.root, "foo"), filepath.Join(rfs.root, "server/symlink"))
g.Assert(err).IsNil()
// Delete a file inside the symlinked directory.
err = fs.Delete("symlink/source.txt")
g.Assert(err).IsNotNil()
g.Assert(IsErrorCode(err, ErrCodePathResolution)).IsTrue()
// Ensure the file outside the root directory still exists.
_, err = os.Lstat(filepath.Join(rfs.root, "foo/source.txt"))
g.Assert(err).IsNil()
})
g.It("returns an error when trying to delete a non-existent file symlinked through a directory outside of the root directory", func() {
// Create a directory outside the root directory.
err := os.Mkdir(filepath.Join(rfs.root, "foo2"), 0o755)
g.Assert(err).IsNil()
// Symlink the directory that is outside the root to a file inside the root.
err = os.Symlink(filepath.Join(rfs.root, "foo2"), filepath.Join(rfs.root, "server/symlink"))
g.Assert(err).IsNil()
// Delete a file inside the symlinked directory.
err = fs.Delete("symlink/source.txt")
g.Assert(err).IsNotNil()
g.Assert(IsErrorCode(err, ErrCodePathResolution)).IsTrue()
})
g.AfterEach(func() { g.AfterEach(func() {
rfs.reset() rfs.reset()

View File

@@ -447,6 +447,7 @@ func (ip *InstallationProcess) Execute() (string, error) {
"compress": "false", "compress": "false",
}, },
}, },
Privileged: true,
NetworkMode: container.NetworkMode(config.Get().Docker.Network.Mode), NetworkMode: container.NetworkMode(config.Get().Docker.Network.Mode),
UsernsMode: container.UsernsMode(config.Get().Docker.UsernsMode), UsernsMode: container.UsernsMode(config.Get().Docker.UsernsMode),
} }

View File

@@ -1,3 +1,3 @@
package system package system
var Version = "1.7.5" var Version = "1.7.3"