Security hardening - guard against directory traversal attack in identifiers

master 0.0.2
Ashley N. 2023-09-04 11:34:56 -04:00
parent d5db6b1e2f
commit cde4b36854
2 changed files with 14 additions and 5 deletions

View File

@ -1,7 +1,7 @@
use std::{error::Error, fs::File, io::Read, convert::TryInto, collections::HashMap}; use std::{error::Error, fs::File, io::Read, convert::TryInto, collections::HashMap};
use flate2::read::ZlibDecoder; use flate2::read::ZlibDecoder;
use linked_hash_set::LinkedHashSet; use linked_hash_set::LinkedHashSet;
use crate::reskit::{utility::{get_string, get_u8, skip, get_u32, get_i8, get_i32, get_u16, get_i16, print_info}, soundtrack::types::{SampleFormat, PsgEnvelope, Note, Sample, PsgSettings, PatternRow, Effect, DcsgChannelMode, NoiseType, Instrument, InstrumentType, Fm2612Operator, Fm2612Settings, Channel, CombinedAssets}}; use crate::reskit::{utility::{get_string, get_u8, skip, get_u32, get_i8, get_i32, get_u16, get_i16, print_info, sanitize_string}, soundtrack::types::{SampleFormat, PsgEnvelope, Note, Sample, PsgSettings, PatternRow, Effect, DcsgChannelMode, NoiseType, Instrument, InstrumentType, Fm2612Operator, Fm2612Settings, Channel, CombinedAssets}};
const DMF_MAGIC_NUMBER: &'static str = ".DelekDefleMask."; const DMF_MAGIC_NUMBER: &'static str = ".DelekDefleMask.";
const DMF_SUPPORTED_VERSION: u8 = 27; const DMF_SUPPORTED_VERSION: u8 = 27;
@ -101,10 +101,10 @@ impl DmfModule {
}; };
let song_name_len = get_u8( bytes.by_ref() )?; let song_name_len = get_u8( bytes.by_ref() )?;
print_info( &format!( "Song name:\t{}", get_string( bytes.by_ref(), song_name_len.into() )? ) ); print_info( &format!( "Song name:\t{}", sanitize_string( get_string( bytes.by_ref(), song_name_len.into() )? ) ) );
let song_author_len = get_u8( bytes.by_ref() )?; let song_author_len = get_u8( bytes.by_ref() )?;
print_info( &format!( "Song author:\t{}", get_string( bytes.by_ref(), song_author_len.into() )? ) ); print_info( &format!( "Song author:\t{}", sanitize_string( get_string( bytes.by_ref(), song_author_len.into() )? ) ) );
// Burn 2 bytes, don't care about the highlight patterns // Burn 2 bytes, don't care about the highlight patterns
skip( bytes.by_ref(), 2 ); skip( bytes.by_ref(), 2 );
@ -182,7 +182,7 @@ impl DmfModule {
for i in 0..instrument_count { for i in 0..instrument_count {
let name_len = get_u8( bytes.by_ref() )?; let name_len = get_u8( bytes.by_ref() )?;
let name = get_string( bytes.by_ref(), name_len.into() )?; let name = sanitize_string( get_string( bytes.by_ref(), name_len.into() )? );
print_info( &format!( "Instrument {}:\t{}", i, name ) ); print_info( &format!( "Instrument {}:\t{}", i, name ) );
@ -654,7 +654,7 @@ impl DmfModule {
for i in 0..num_samples { for i in 0..num_samples {
let sample_size = get_u32( bytes.by_ref() )?; let sample_size = get_u32( bytes.by_ref() )?;
let sample_name_chars = get_u8( bytes.by_ref() )?; let sample_name_chars = get_u8( bytes.by_ref() )?;
let name = get_string( bytes.by_ref(), sample_name_chars.into() )?; let name = sanitize_string( get_string( bytes.by_ref(), sample_name_chars.into() )? );
let rate = match get_u8( bytes.by_ref() )? { let rate = match get_u8( bytes.by_ref() )? {
1 => 8000, 1 => 8000,
2 => 11025, 2 => 11025,

View File

@ -39,6 +39,15 @@ impl< Type: Copy > Iterator for Ring< Type > {
} }
/**
* Protect against directory traversal attacks when using identifiers inside of files
*/
pub fn sanitize_string( string: String ) -> String {
string
.replace( "../", "_" )
.replace( "..\\", "_" )
}
pub fn symbol_to_pascal( filename: &str ) -> String { pub fn symbol_to_pascal( filename: &str ) -> String {
filename filename
.replace( "/", "_" ) .replace( "/", "_" )