Add fix and example for openat path traversion

This commit is contained in:
lazymio
2022-01-24 15:15:34 +01:00
parent bba26a53b5
commit 6d0fc4a818
6 changed files with 37 additions and 11 deletions
+15
View File
@@ -0,0 +1,15 @@
// gcc -static ~/qiling/examples/src/linux/path_traverse.c -g -O0 -o ~/qiling/examples/rootfs/x8664_linux/bin/path_traverse_static
// https://www.kalmarunionen.dk/writeups/2022/rwctf/qlaas/
#include <fcntl.h>
#include <unistd.h>
int main(){
char buf[4096];
int fd = openat(1, "/etc/passwd", O_RDONLY);
ssize_t len = read(fd, buf, sizeof(buf));
write(1, buf, len);
fd = openat(1, "/etc/passwd_link", O_RDONLY);
len = read(fd, buf, sizeof(buf));
write(1, buf, len);
}
+1 -4
View File
@@ -95,14 +95,11 @@ class QlFsMapper:
def mapping_count(self):
return len(self._mapping)
def open_ql_file(self, path, openflags, openmode, dir_fd=None):
def open_ql_file(self, path, openflags, openmode):
if self.has_mapping(path):
self.ql.log.info(f"mapping {path}")
return self._open_mapping_ql_file(path, openflags, openmode)
else:
if dir_fd:
return ql_file.open(path, openflags, openmode, dir_fd=dir_fd)
real_path = self.ql.os.path.transform_to_real_path(path)
return ql_file.open(real_path, openflags, openmode)
+4 -2
View File
@@ -133,8 +133,10 @@ class QlPathManager:
if os.path.islink(real_path):
link_path = Path(os.readlink(real_path))
if not link_path.is_absolute():
real_path = Path(os.path.join(os.path.dirname(real_path), link_path))
real_path = self.convert_path(self.ql.rootfs, os.path.dirname(real_path), link_path)
if os.path.islink(real_path):
real_path = self.transform_to_real_path(real_path)
# resolve multilevel symbolic link
if not os.path.exists(real_path):
+7 -4
View File
@@ -4,6 +4,7 @@
#
import os
from pathlib import Path
from qiling import Qiling
from qiling.const import QL_OS, QL_ARCH
@@ -101,11 +102,13 @@ def ql_syscall_openat(ql: Qiling, fd: int, path: int, flags: int, mode: int):
fd = ql.unpacks(ql.pack(fd))
if 0 <= fd < NR_OPEN:
dir_fd = ql.os.fd[fd].fileno()
else:
dir_fd = None
fobj = ql.os.fd[fd]
# ql_file object or QlFsMappedObject
if hasattr(fobj, "fileno") and hasattr(fobj, "name"):
if not Path.is_absolute(Path(file_path)):
file_path = Path(fobj.name) / Path(file_path)
ql.os.fd[idx] = ql.os.fs_mapper.open_ql_file(file_path, flags, mode, dir_fd)
ql.os.fd[idx] = ql.os.fs_mapper.open_ql_file(file_path, flags, mode)
regreturn = idx
except QlSyscallError as e:
+9
View File
@@ -1091,6 +1091,15 @@ class ELFTest(unittest.TestCase):
self.assertEqual([0x1000 + 11, 0x2000 + 11, 0x3000 + 43], ql.mem.search(b"\x09\x53(\x0f|\x1a|\x04)[^\x0d]"))
del ql
def test_elf_linux_x8664_path_traversion(self):
mock_stdout = pipe.SimpleOutStream(sys.stdout.fileno())
ql = Qiling(["../examples/rootfs/x8664_linux/bin/path_traverse_static"], "../examples/rootfs/x8664_linux", verbose=QL_VERBOSE.DEBUG, stdout=mock_stdout)
ql.run()
self.assertTrue("root\n" not in ql.os.stdout.read().decode("utf-8"))
del ql
if __name__ == "__main__":
unittest.main()