Hi,
I set up fuzzing for the barcode generation and found a few bugs in different barcode generations. This Ticket is focussing on the EAN creation, because only a few ASCII characters input are enough to trigger the bug.
You can either input "55++15" into the qt-ui or use my reproducer.
This little reprocuder triggers the bug:
#include <zint.h>
#include <string>
int main() {
std::string input = "55++15";
struct zint_symbol *my_symbol;my_symbol = ZBarcode_Create();
my_symbol->symbology = BARCODE_EANX;
ZBarcode_Encode_and_Buffer(my_symbol, (unsigned char *) input.c_str(), input.size() , 0);
ZBarcode_Delete(my_symbol);
return 0;
}
Link against the current libzint.so as generated by cmake and the segfault will occur.
When compiled with address sanitizer, the following stacktrace will be printed:
/home/c/.local/share/code-intelligence/projects/project-4905718a-4da1-11ea-bbe0-8c1645a161cb/libfuzzer/address/backend/upcean.c:331:24: runtime error: index -1 out of bounds for type 'const char *[4]'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /home/c/.local/share/code-intelligence/projects/project-4905718a-4da1-11ea-bbe0-8c1645a161cb/libfuzzer/address/backend/upcean.c:331:24 in
/home/c/.local/share/code-intelligence/projects/project-4905718a-4da1-11ea-bbe0-8c1645a161cb/libfuzzer/address/backend/upcean.c:331:24: runtime error: null pointer passed as argument 2, which is declared to never be null
/usr/include/string.h:122:14: note: nonnull attribute specified here
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /home/c/.local/share/code-intelligence/projects/project-4905718a-4da1-11ea-bbe0-8c1645a161cb/libfuzzer/address/backend/upcean.c:331:24 in
AddressSanitizer:DEADLYSIGNAL
=================================================================
==18211==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x7f77850ea5a1 bp 0x7ffe4ef2c1f0 sp 0x7ffe4ef2b9a8 T0)
==18211==The signal is caused by a READ memory access.
==18211==Hint: address points to the zero page.
#0 0x7f77850ea5a0 /build/glibc-OTsEL5/glibc-2.27/string/../sysdeps/x86_64/multiarch/strlen-avx2.S:59
#1 0x47edaf in strcpy /tmp/final/llvm.src/projects/compiler-rt/lib/asan/asan_interceptors.cc:429:22
#2 0x7f7786599893 in add_on /home/c/.local/share/code-intelligence/projects/project-4905718a-4da1-11ea-bbe0-8c1645a161cb/libfuzzer/address/backend/upcean.c:331:9
#3 0x7f77865971cb in eanx /home/c/.local/share/code-intelligence/projects/project-4905718a-4da1-11ea-bbe0-8c1645a161cb/libfuzzer/address/backend/upcean.c:881:13
#4 0x7f7786554046 in reduced_charset /home/c/.local/share/code-intelligence/projects/project-4905718a-4da1-11ea-bbe0-8c1645a161cb/libfuzzer/address/backend/library.c
#5 0x7f7786549e1b in ZBarcode_Encode /home/c/.local/share/code-intelligence/projects/project-4905718a-4da1-11ea-bbe0-8c1645a161cb/libfuzzer/address/backend/library.c:1205:20
#6 0x7f778655228f in ZBarcode_Encode_and_Buffer /home/c/.local/share/code-intelligence/projects/project-4905718a-4da1-11ea-bbe0-8c1645a161cb/libfuzzer/address/backend/library.c:1392:20
#7 0x4c57c2 in main (/home/c/.local/share/code-intelligence/projects/project-4905718a-4da1-11ea-bbe0-8c1645a161cb/libfuzzer/address/demo/poc+0x4c57c2)
#8 0x7f7784f7db96 in __libc_start_main /build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310
#9 0x41b6b9 in _start (/home/c/.local/share/code-intelligence/projects/project-4905718a-4da1-11ea-bbe0-8c1645a161cb/libfuzzer/address/demo/poc+0x41b6b9)
I will create bug reports for the other barcodes when I have some time in the next days. In order to trigger them the input needs to contain some non-printable characters so I don't think they are as significant as the EAN one.
Affected barcodes are AUSPOST family, CODEONE, DOTCODE, VIN and CODABLOCKF
Best regards,
Chris
Hi Chris,
Thank you for finding this and taking the time to let us know. I have added a check to the UPC/EAN code to throw an error if more than one + character is included in the input data.
I look forward to seeing what else you find!
Robin.
Hi Robin,
Another bug, that I found in the Australian Post family of barcodes can be triggered when inputting the following byte sequence:
0x41 0x00 0x00 0x00, an uppercase A followed by 3 null bytes. This will lead to a heap buffer read overflow:If you want to support OSS-Fuzz integration, the static libary version needs to be integrated by you. For better conforming OSS-Fuzz rules you could also check in the fuzz target at a fitting location in the project itself (like libpng is doing here: https://github.com/glennrp/libpng/tree/libpng16/contrib/oss-fuzz).
Zint might even be eligible for an integration reward by Google: https://opensource.googleblog.com/2017/05/oss-fuzz-five-months-later-and.html
But I don't know exactly how they deem projects to be eligible.
Best regards,
Chris
Last edit: Christian Hartlage 2022-03-23
CODABLOCKF crashes due to a read global buffer overflow with input
0x1c,0x1c,0x49DOTCODE crashes due to a read-dynamic-stack-buffer-overflow with input
0x28,0x87,0x27:So, I debugged some of the crashes and it seems they only have potential to crash libzint when compiled with address sanitizer.
Last edit: Christian Hartlage 2022-03-23
Dear Christian,
thank you for the repot. I just want to say, that examining the report is on my todo-List.
Thank you,
Harald
Dear Harald,
we also fuzzed the zint library and found some more bugs. All files to reproduce the bugs are in the attachment and you can trigger every bug with the zint command line tool
if you compile it with address sanitizer (-DZINT_SANITIZE=TRUE). All line numbers are from zint-2.7.1
telepent.c - telepen()
In telepen.c
63 char dest[512]; /*14 + 30 * 14 + 14 + 14 + 1 ~ 512 */the dest array is too small because the biggest element in41 static char *TeleTable[]is 16 byte.I think the best solution is to increase thedest[] buffer. (If I calculate it correct
111 char dest[1024];should be large enough)library.c - ZBarcode_Encode()
If you execute zint with an empty file you get a valid buffer of size zero in library.c
1457 buffer = (unsigned char *) malloc(fileLen * sizeof (unsigned char));and then you call995 in_length = (int)ustrlen(source);on that buffer of size zero. Maybe you can return a ZINT_ERROR after1444 fileLen = ftell(file);if the file size is zero.maxicode.c - maxi_text_process()
I think the problem is this part of the code in maxicode.c
in line 454 you check
i <= 143but in line 443 you accesscharacter[i + 5]this overflows ifi >= 139code1.c - c1_encode()
this error occurs in the do while loop in c1_encode()
the check of
sp < lengthin line 1020 is not enough because there are lot ofsource[sp + i](and source[sp + 1|2]) accesses which will overflow ifsp + i >= lengthaztec.c - aztec_text_process()
in aztec.c the memory allocated at lines 139-141
is not freed if you return at line 724 this should be easy to fix, i think you can free all three buffers before line 724
library.c - ZBarcode_Encode_File()
here its the same again the buffer allocated at line 1454 is not freed if you return at line 1469
i think the same can happen at line 1472
dotcode.c
in line 1096 if masked_array[i] is >= 113 memory is read outside of dot_patterns[113]
codeword_array is generated by dotcode_encode_message() at line 1298 in dotcode()
masked_codeword_array is generated by apply_mask() at line 1423 in dotcode()
If the codeword_array should not contain values >= 113 the error is in dotcode_encode_message() (poc creates codeword_array[395] == 233)
If the codeword_array can contain values >= 113 the error is in apply_mask() at 1220 => asked_codeword_array[j + 1] = codeword_array[j] % 113;
pdf417.c - pdf417() / micro_pdf417()
this bug happens with
./zint -b55(pdf417) and./zint -b84(micro_pdf417), maybe the root of this bug is in pdf417_enc(). I tried to understand the problem, but there happens a lot and I didn't get it, sorry.there is another bug in pdf417.c maybe this is related
aztec.c -aztec_text_process()
If I understand it right length in bin_append() and bin_append_posn() is the length of the data you append and not the max length of the buffer
and the bug is in aztec_text_process() where you should guarantee that a call of bin_append() can't overflow your binary_string
I hope this helps you,
Nico
Thank you for finding the time to test Zint so thoroughly. After much effort (mostly from Git Lost) I think all of these bugs have now been sorted out. If Chris or Nico could could please confirm this then I think it would be a relief to close this ticket!
I tested the gitlost-zint 22354a81f12af9f9b68fae4fb48bac8bee93d698 version and run all my test cases and found one more in the dotcode.c. I didn't reported it previously because I thought it was a duplicate of the other dotcode bug. Sorry for that.
This bug is strange I can trigger it only if I compile zint with gcc (version 9.3.0) and asan, with clang and asan I can't reproduce it. The inputs are in the attachment. All inputs trigger the same bug at different locations. Its always an access to codeword_array[array_length] with a too large array_length.
All other bugs are fixed in my opinion, thanks for the replay and your work done here.
Thanks very much Nico, [f51499] should address the DOTCODE
codearrayoverflow.Related
Commit: [f51499]
Last edit: Git Lost 2020-03-31
Yes fr1499 fixed it, I think this ticket can be closed
Git-Lost has confirmed that all found bugs are fixed.
Cudos to all bug-hunters,
Harald
Hi Zint Team,
Snyk CLI indicates after processing a vulnerability check that "CVE-2020-9385" is still present. Can you give a short information that "CVE-2020-9385" is fixed in ZINT 2.10.9? Or do we have to update to 2.13.x?
Thank you very much!
Best regards
Stefan
Links
Last edit: Stf Ortm 2024-02-12
Hi Stefan, the bugs mentioned in this ticket should have been fixed with zint 2.8.0. Test cases were added for all the issues mentioned.
The attached PNGs don't show what the input data is that triggers the NULL pointer dereference, so it's hard to tell if the same issues are being tested.
Could you supply the input data that you're testing with? Thanks, Martin
P.S. Please note regardless that only the latest version of zint, 2.13.0, is supported, so it would be best if you would run your tests against it.
Hi Git Lost,
Thank you for the quick response.
I downloaded ZINT 2.13 from commit f312cdf6304df567b5c68de0338d1869c0869e6f.
The file backend\zintconfig.h contains the following version information:
ZINT_VERSION_MAJOR 2
ZINT_VERSION_MINOR 13
ZINT_VERSION_RELEASE 0
ZINT_VERSION_BUILD 9
After running the latest version of Snyk, the vulnerability was indicated again.
This can be a false positive, because Snyk checks the fingerprints of the files again a database.
Maybe the Snyk scanner fails because the fingerprints of the 2.10.x are identical to 2.13.x files because these files had no errors in the past and used identical in the latest version.
Unfortunately, I cannot recognize which files are problematic, therefore I attach the commands and JSON output.
It would be nice if you could have a look inside the files.
Do you also use a vulnerability check tool or could you give a hint?
Thank you!
Stefan
Last edit: Stf Ortm 2024-02-14
Hi Stefan, thanks for attachments but I don't see any information there that could help me determine what the input data is that leads to the vulnerability.
I don't know anything about Snyk, which it appears I need to sign up for to use, which I do not wish to do. Even if I did it would appear from the "commands.png" attachment that all it would do is dump the overview at https://security.snyk.io/vuln/SNYK-UNMANAGED-ZINT-2380686 in JSON format ("vulnerabilities.json"), which gives no details about how to reproduce the issue.
You mention files, but I don't know what they are. Are they data files that Snyk references in its database? Can they be downloaded or accessed in any way?
Re vulnerability check tool, no, zint does not use such a tool, whose existence is news to me.
Zint has a large test suite, the bulk of which is located in "test_XXX.c" files in "backend/tests" in the project directory. For instance the first issue on this ticket concerning EAN and the input "55++15" is tested for at https://sourceforge.net/p/zint/code/ci/master/tree/backend/tests/test_upcean.c#l991
Regards, Martin
Hi Martin,
I did a static analysis yesterday to find references to vulnerable .c/.h files. The result (including the commandlines and the list of scanned files) is attached. There are some suggestions included but there is no hint of an open or existing CVE in 2.13.9.
This CVE is therefore solved for me and from my point of view ticket 181 should remain closed.
Thank you for your patience and time.
Best regards,
Stefan
Hi Stefan, thanks for the analysis. The only ones that seem fully relevant to me are the 2 "Dereference of a NULL Pointer" issues which should be fixed by commit [f0d890].
The "Improper Null Termination" ones seem on looking at each instance to be false positives, and the "Potential buffer overflow from usage of unsafe function" ones result from zint using
strcpy(),sprintf(), etc which I've no plans to replace, although this might change in the future (OpenBSD for one changed their linker to issue an unsuppressible warning when these are used which is irritating).Thanks, Martin
Related
Commit: [f0d890]