Unrestricted File Download in Go Lang
Vulnerable Example
The following example is a vulnerable code example that serves files from a directory in an unsecure way:
const ROOT string = "/path/to/root/%s"
func getFileByName(file_name string) string {
path := fmt.Sprintf(ROOT, file_name)
buffer, err := ioutil.ReadFile(path)
if err != nil {
return name
}
return buffer
}
If file_name
is controlled by the user, it is possible to retrieve arbitrary files in the filesystem by means of ../
, for example:
getFileByName("../../../etc/passwd")
This results in the absolute path /path/to/root/../../../etc/passwd
, and its canonicalized form /etc/passwd
. To remediate the vulnerability, the path
variable can be safely built as follows:
path := fmt.Sprintf(ROOT, path.Base(file_name))
The previous attack would result in reading the /path/to/root/passwd
file.
Prevention
Ensure the use of user-provided values, which can be used to escape the designed directory by means of ../
is avoided. For example, the path.Base
method can be used to extract the base component of a path.