mirror of
https://github.com/qilingframework/qiling.git
synced 2026-10-12 02:21:40 +00:00
Add fix and example for openat path traversion
This commit is contained in:
+1
-1
Submodule examples/rootfs updated: a489ff519f...149041a153
@@ -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
@@ -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
@@ -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):
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user