Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fuzzing Coverage Expansion #407

Merged
merged 17 commits into from
Sep 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions regress/fuzzers/zip_read_encrypted_file_fuzzer.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#include <zip.h>
#include <zipint.h>
#include <iostream>
#include <fstream>
#include <string>

#ifdef __cplusplus
extern "C"
#endif

/**
This fuzzer target simulates the process of handling encrypted files within a ZIP archive .
**/

int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{
zip_source_t* src;
zip_t* za;
zip_error_t error;
char buf[32768];
zip_int64_t i, n;
zip_file_t* f;


if ((src = zip_source_buffer_create(data, size, 0, &error)) == NULL) {
zip_error_fini(&error);
return 0;
}

if ((za = zip_open_from_source(src, 0, &error)) == NULL) {
zip_source_free(src);
zip_error_fini(&error);
return 0;
}

int file_index = zip_name_locate(za, "file", 0);

if (file_index < 0) {
std::cerr << "Failed to locate encrypted file in ZIP archive" << std::endl;
zip_close(za);
return 1;
}

zip_file_t *file = zip_fopen_index_encrypted(za, file_index, 0, "secretpassword");

if (!file) {
std::cerr << "Failed to open encrypted file for reading" << std::endl;
zip_close(za);
return 1;
}


zip_fclose(file);
zip_close(za);

return 0;
}
73 changes: 73 additions & 0 deletions regress/fuzzers/zip_read_file_fuzzer.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#include <zip.h>
#include <zipint.h>
#include <iostream>
#include <fstream>
#include <string>

std::string random_string(size_t length);

#ifdef __cplusplus
extern "C"
#endif

/**
This fuzzing target takes input data, creates a ZIP archive from it, checks the archive's consistency,
and iterates over the entries in the archive, reading data from each entry.
**/

int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{
zip_source_t* src;
zip_t* za;
zip_error_t error;
char buf[32768];
zip_int64_t i, n;
zip_file_t* f;

std::string name = random_string(20) + ".zip";

std::ofstream outfile(name, std::ios::binary);

if (outfile.is_open()) {
outfile.write(reinterpret_cast<const char*>(data), size);
outfile.close();

za = zip_open(name.c_str(), 0, NULL);
n = zip_get_num_entries(za, 0);
for (i = 0; i < n; i++) {
f = zip_fopen_index(za, i, 0);
if (f == NULL) {
continue;
}

while (zip_fread(f, buf, sizeof(buf)) > 0) {
;
}
zip_fclose(f);

}
zip_close(za);
std::remove(name.c_str());

}
else {
std::cerr << "Unable to open the file." << std::endl;
}

return 0;
}

std::string random_string(size_t length)
{
auto randchar = []() -> char {
const char charset[] =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
const size_t max_index = (sizeof(charset) - 1);
return charset[rand() % max_index];
};
std::string str(length, 0);
std::generate_n(str.begin(), length, randchar);
return str;
}
File renamed without changes.
69 changes: 69 additions & 0 deletions regress/fuzzers/zip_write_encrypt_aes256_file_fuzzer.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#include <zip.h>
#include <zipint.h>
#include <iostream>
#include <fstream>
#include <string>

std::string random_string(size_t length);

#ifdef __cplusplus
extern "C"
#endif

/**
This fuzzing target takes input data, creates a ZIP archive, load it to a buffer, adds a file to it
with AES-256 encryption and a specified password, and then closes and removes the archive.

The purpose of this fuzzer is to test security of ZIP archive handling and encryption in the libzip
by subjecting it to various inputs, including potentially malicious or malformed data of different file types.
**/

int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{
zip_source_t* src;
zip_t* za;
char buf[32768];
zip_int64_t i, n;
zip_file_t* f;

std::string path = random_string(20) + "_aes256"+ ".zip";
const char *password = random_string(20).c_str();
const char * file = random_string(20).c_str();
int error = 0;
struct zip *archive = zip_open(path.c_str(), ZIP_CREATE, &error);

if(error)
return -1;

struct zip_source *source = zip_source_buffer(archive, data, size, 0);
if(source == NULL){
printf("failed to create source buffer. %s\n",zip_strerror(archive));
return -1;
}

int index = (int)zip_file_add(archive, file, source, ZIP_FL_OVERWRITE);
if(index < 0){
printf("failed to add file to archive: %s\n",zip_strerror(archive));
return -1;
}
zip_file_set_encryption(archive, index, ZIP_EM_AES_256, password);
zip_close(archive);
std::remove(path.c_str());

return 0;
}

std::string random_string(size_t length)
{
auto randchar = []() -> char {
const char charset[] =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
const size_t max_index = (sizeof(charset) - 1);
return charset[rand() % max_index];
};
std::string str(length, 0);
std::generate_n(str.begin(), length, randchar);
return str;
}
69 changes: 69 additions & 0 deletions regress/fuzzers/zip_write_encrypt_pkware_file_fuzzer.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#include <zip.h>
#include <zipint.h>
#include <iostream>
#include <fstream>
#include <string>

std::string random_string(size_t length);

#ifdef __cplusplus
extern "C"
#endif

/**
This fuzzing target takes input data, creates a ZIP archive, load it to a buffer, adds a file to it
with traditional PKWARE encryption and a specified password, and then closes and removes the archive.

The purpose of this fuzzer is to test security of ZIP archive handling and encryption in the libzip
by subjecting it to various inputs, including potentially malicious or malformed data of different file types.
**/

int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{
zip_source_t* src;
zip_t* za;
char buf[32768];
zip_int64_t i, n;
zip_file_t* f;

std::string path = random_string(20) + "_pkware"+ ".zip";
const char *password = random_string(20).c_str();
const char * file = random_string(20).c_str();
int error = 0;
struct zip *archive = zip_open(path.c_str(), ZIP_CREATE, &error);

if(error)
return -1;

struct zip_source *source = zip_source_buffer(archive, data, size, 0);
if(source == NULL){
printf("failed to create source buffer. %s\n",zip_strerror(archive));
return -1;
}

int index = (int)zip_file_add(archive, file, source, ZIP_FL_OVERWRITE);
if(index < 0){
printf("failed to add file to archive: %s\n",zip_strerror(archive));
return -1;
}
zip_file_set_encryption(archive, index, ZIP_EM_TRAD_PKWARE,/* Password to encrypt file */ password);
zip_close(archive);
std::remove(path.c_str());

return 0;
}

std::string random_string(size_t length)
{
auto randchar = []() -> char {
const char charset[] =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
const size_t max_index = (sizeof(charset) - 1);
return charset[rand() % max_index];
};
std::string str(length, 0);
std::generate_n(str.begin(), length, randchar);
return str;
}
35 changes: 30 additions & 5 deletions regress/ossfuzz.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,43 @@
# This script is meant to be run by
# https://github.com/google/oss-fuzz/blob/master/projects/libzip/Dockerfile


mkdir build
cd build
cmake -DBUILD_SHARED_LIBS=OFF -DENABLE_GNUTLS=OFF -DENABLE_MBEDTLS=OFF -DENABLE_OPENSSL=OFF -DBUILD_TOOLS=OFF -DENABLE_LZMA=OFF ..
cmake -DBUILD_SHARED_LIBS=OFF -DENABLE_GNUTLS=OFF -DENABLE_MBEDTLS=OFF -DENABLE_OPENSSL=ON -DBUILD_TOOLS=OFF -DENABLE_LZMA=OFF -DHAVE_CRYPTO=ON ..
make -j$(nproc)

$CXX $CXXFLAGS -std=c++11 -I. -I../lib \
$SRC/libzip/regress/zip_read_fuzzer.cc \
$SRC/libzip/regress/fuzzers/zip_read_fuzzer.cc \
-o $OUT/zip_read_fuzzer \
$LIB_FUZZING_ENGINE $SRC/libzip/build/lib/libzip.a -lz
$LIB_FUZZING_ENGINE $SRC/libzip/build/lib/libzip.a -lz -v -lssl -lcrypto

$CXX $CXXFLAGS -std=c++11 -I. -I../lib \
$SRC/libzip/regress/fuzzers/zip_write_encrypt_aes256_file_fuzzer.cc \
-o $OUT/zip_write_encrypt_aes256_file_fuzzer \
$LIB_FUZZING_ENGINE $SRC/libzip/build/lib/libzip.a -lz -v -lssl -lcrypto

find $SRC/libzip/regress -name "*.zip" | \
$CXX $CXXFLAGS -std=c++11 -I. -I../lib \
$SRC/libzip/regress/fuzzers/zip_write_encrypt_pkware_file_fuzzer.cc \
-o $OUT/zip_write_encrypt_pkware_file_fuzzer \
$LIB_FUZZING_ENGINE $SRC/libzip/build/lib/libzip.a -lz -v -lssl -lcrypto

$CXX $CXXFLAGS -std=c++11 -I. -I../lib \
$SRC/libzip/regress/fuzzers/zip_read_encrypted_file_fuzzer.cc \
-o $OUT/zip_read_encrypted_archive_fuzzer \
$LIB_FUZZING_ENGINE $SRC/libzip/build/lib/libzip.a -lz -v -lssl -lcrypto

$CXX $CXXFLAGS -std=c++11 -I. -I../lib \
$SRC/libzip/regress/fuzzers/zip_read_file_fuzzer.cc \
-o $OUT/zip_read_file_fuzzer \
$LIB_FUZZING_ENGINE $SRC/libzip/build/lib/libzip.a -lz -v -lssl -lcrypto

find $SRC/libzip/regress -name "*zip" -not -name "*fuzzer_seed_corpus*" | \
xargs zip $OUT/zip_read_fuzzer_seed_corpus.zip

cp $SRC/libzip/regress/zip_read_fuzzer.dict $OUT/
cp $SRC/libzip/regress/zip_write_encrypt_aes256_file_fuzzer_seed_corpus.zip $OUT/
cp $SRC/libzip/regress/zip_write_encrypt_aes256_file_fuzzer_seed_corpus.zip $OUT/zip_write_encrypt_pkware_file_fuzzer_seed_corpus.zip
cp $SRC/libzip/regress/zip_read_encrypted_file_fuzzer_seed_corpus.zip $OUT/

cp $SRC/libzip/regress/zip_read_fuzzer.dict $OUT/
cp $OUT/zip_read_fuzzer_seed_corpus.zip $OUT/zip_read_file_fuzzer_seed_corpus.zip
Binary file not shown.
Binary file not shown.
Loading