lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


It was thus said that the Great David F once stated:
> On 19/03/17 02:27 AM, Kat Kioo wrote:
> 
> > In general you should just remove the functions at compile time instead
> > of removing at runtime in the vm. Another thing that you might consider a
> > security ossue is your makesafeph function. In general it is not as simple
> > as a few regex replaces.  
> 
> Not really sure how to imagine the first part. Sounds complicated.
> 
> makeSafePath does not use regex. It checks for a relative path that
> escapes its parent directory (".."), if it doesn't the user dir is
> prefixed and the result returned. I tried finding out if there is anything
> else special going on with paths under windows, but the best I could find
> was a msdn article that didn't reveal anything new. When fed with an
> absolute path the function should return an invalid path. I'll probably do
> check for that and just return nil.

  It looks like your running your code under Windows, which has a several
issues that Unix (Linux, Mac OS-X) does not have.  

  First off, you don't check for drive letters at the start of the file
name.  Second, there are certain file names that should be checked for and
rejected [1], like CON (or con or con.txt or con.any_extension_really). 
Now, assuming a filename doesn't contain a drive letter or contains a device
name, if it starts with a '/' or a '\', it can be rejected for being a full
path:

	if pathname:match "^[\\/]" then error() end

otherwise it's a relative name.  You can break it apart on the path
separator, looking at each segment and applying some logic.  Here, I
accumulate each segment (assuming a relative path without device names and
using a '/' for a path separator) in a table.  For ".." (parent directory) I
remove the last recently added segment; for anything other than "." I add it
("." is "current directory" and can be ignored):

	local function normalize(path)
	  local acc = {}
	  for segment in path:gmatch("[^/]+") do
	    if segment == ".." then
	      table.remove(acc)
	    else if segment ~= "." then
	      table.insert(acc,segment)
	    end
	  end
	
	  return table.concat(acc,'/')
	end

Trying it:

	print(normalize("../../../../../../../etc/passwd"))
	print(normalize(".././.././here/../be/../dragons"))

	etc/passwd
	dragons

Then you can just prepend on the "root" directory.

  -spc

[1]	https://support.microsoft.com/en-us/help/74496/ms-dos-device-driver-names-cannot-be-used-as-file-names