Skip to content
Permalink
Browse files Browse the repository at this point in the history
- fixed path traversal vulnerability in MMS file services (LIB61850-357)
  • Loading branch information
mzillgith committed Oct 7, 2022
1 parent dd3e2a6 commit 10622ba
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 25 deletions.
1 change: 0 additions & 1 deletion hal/filesystem/linux/file_provider_linux.c
Expand Up @@ -37,7 +37,6 @@ struct sDirectoryHandle {
DIR* handle;
};


FileHandle
FileSystem_openFile(char* fileName, bool readWrite)
{
Expand Down
3 changes: 3 additions & 0 deletions src/mms/inc_private/mms_common_internal.h
Expand Up @@ -82,6 +82,9 @@ mmsMsg_createExtendedFilename(const char* basepath, int bufSize, char* extendedF
LIB61850_INTERNAL FileHandle
mmsMsg_openFile(const char* basepath, char* fileName, bool readWrite);

LIB61850_INTERNAL bool
mmsMsg_isFilenameSave(const char* filename);

#endif /* (MMS_FILE_SERVICE == 1) */

typedef struct sMmsServiceError
Expand Down
51 changes: 30 additions & 21 deletions src/mms/iso_mms/client/mms_client_files.c
Expand Up @@ -71,7 +71,6 @@ getFrsm(MmsConnection connection, int32_t frsmId)
return frsm;
}


static int32_t
getNextFrsmId(MmsConnection connection)
{
Expand Down Expand Up @@ -125,38 +124,48 @@ mmsClient_handleFileOpenRequest(

if (hasFileName) {

MmsFileReadStateMachine* frsm = getFreeFrsm(connection);
if (mmsMsg_isFilenameSave(filename) == false) {
/* potential attack */

if (frsm != NULL) {
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: client provided unsave filename -> rejected\n");

MmsOutstandingCall obtainFileCall = mmsClient_getMatchingObtainFileRequest(connection, filename);
mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_FILE_NON_EXISTENT);
}
else {
MmsFileReadStateMachine* frsm = getFreeFrsm(connection);

if (obtainFileCall) {
if (frsm != NULL) {

if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: file open is matching obtain file request for file %s\n", filename);
MmsOutstandingCall obtainFileCall = mmsClient_getMatchingObtainFileRequest(connection, filename);

obtainFileCall->timeout = Hal_getTimeInMs() + connection->requestTimeout;
}
if (obtainFileCall) {

FileHandle fileHandle = mmsMsg_openFile(MmsConnection_getFilestoreBasepath(connection), filename, false);
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: file open is matching obtain file request for file %s\n", filename);

if (fileHandle != NULL) {
obtainFileCall->timeout = Hal_getTimeInMs() + connection->requestTimeout;
}

frsm->fileHandle = fileHandle;
frsm->readPosition = filePosition;
frsm->frsmId = getNextFrsmId(connection);
frsm->obtainRequest = obtainFileCall;
FileHandle fileHandle = mmsMsg_openFile(MmsConnection_getFilestoreBasepath(connection), filename, false);

if (fileHandle != NULL) {

frsm->fileHandle = fileHandle;
frsm->readPosition = filePosition;
frsm->frsmId = getNextFrsmId(connection);
frsm->obtainRequest = obtainFileCall;

mmsMsg_createFileOpenResponse(MmsConnection_getFilestoreBasepath(connection),
invokeId, response, filename, frsm);
}
else
mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_FILE_NON_EXISTENT);

mmsMsg_createFileOpenResponse(MmsConnection_getFilestoreBasepath(connection),
invokeId, response, filename, frsm);
}
else
mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_FILE_NON_EXISTENT);

mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_RESOURCE_OTHER);
}
else
mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_RESOURCE_OTHER);
}
else
goto exit_invalid_parameter;
Expand Down
20 changes: 19 additions & 1 deletion src/mms/iso_mms/common/mms_common_msg.c
Expand Up @@ -570,6 +570,24 @@ mmsMsg_createExtendedFilename(const char* basepath, int bufSize, char* extendedF
#endif
}

bool
mmsMsg_isFilenameSave(const char* filename)
{
if (filename)
{
if (strstr(filename, ".."))
return false;

if (strstr(filename, "./"))
return false;

return true;
}
else {
return false;
}
}

FileHandle
mmsMsg_openFile(const char* basepath, char* fileName, bool readWrite)
{
Expand Down Expand Up @@ -620,7 +638,7 @@ mmsMsg_parseFileName(char* filename, uint8_t* buffer, int* bufPos, int maxBufPos
* characters.
*/
if (strstr(filename, "..") != NULL) {
mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_FILENAME_SYNTAX_ERROR);
mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_FILE_NON_EXISTENT);
return false;
}

Expand Down
53 changes: 51 additions & 2 deletions src/mms/iso_mms/server/mms_file_service.c
Expand Up @@ -235,8 +235,6 @@ mmsMsg_createFileOpenResponse(const char* basepath, uint32_t invokeId, ByteBuffe
response->size = bufPos;
}



void
mmsServer_handleFileDeleteRequest(
MmsServerConnection connection,
Expand Down Expand Up @@ -266,6 +264,16 @@ mmsServer_handleFileDeleteRequest(
if (DEBUG_MMS_SERVER)
printf("MMS_SERVER: mms_file_service.c: Delete file (%s)\n", filename);

if (mmsMsg_isFilenameSave(filename) == false)
{
if (DEBUG_MMS_SERVER)
printf("MMS_SERVER: remote provided unsave filename -> rejected\n");

mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_FILE_NON_EXISTENT);

return;
}

if (connection->server->fileAccessHandler != NULL) {
MmsError access = connection->server->fileAccessHandler(connection->server->fileAccessHandlerParameter,
connection, MMS_FILE_ACCESS_TYPE_DELETE, filename, NULL);
Expand Down Expand Up @@ -344,6 +352,17 @@ mmsServer_handleFileOpenRequest(

if (hasFileName) {

if (mmsMsg_isFilenameSave(filename) == false) {
/* potential attack */

if (DEBUG_MMS_CLIENT)
printf("MMS_SERVER: remote provided unsave filename -> rejected\n");

mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_FILE_NON_EXISTENT);

return;
}

if (connection->server->fileAccessHandler != NULL) {
MmsError access = connection->server->fileAccessHandler(connection->server->fileAccessHandlerParameter,
connection, MMS_FILE_ACCESS_TYPE_OPEN, filename, NULL);
Expand Down Expand Up @@ -690,6 +709,15 @@ mmsServer_handleObtainFileRequest(

if (hasSourceFileName && hasDestinationFilename) {

if (mmsMsg_isFilenameSave(destinationFilename) == false) {
/* potential attack */

if (DEBUG_MMS_SERVER)
printf("MMS_SERVER: remote provided unsave filename -> rejected\n");

goto exit_invalid_parameter;
}

/* Call user to check if access is allowed */
if (connection->server->fileAccessHandler != NULL) {
MmsError access = connection->server->fileAccessHandler(connection->server->fileAccessHandlerParameter,
Expand Down Expand Up @@ -1023,6 +1051,17 @@ createFileDirectoryResponse(const char* basepath, uint32_t invokeId, ByteBuffer*
continueAfterFileName = NULL;
}

if ((directoryName && mmsMsg_isFilenameSave(directoryName) == false) ||
(continueAfterFileName && mmsMsg_isFilenameSave(continueAfterFileName) == false))
{
if (DEBUG_MMS_SERVER)
printf("MMS_SERVER: remote provided unsave filename -> rejected\n");

mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_FILE_NON_EXISTENT);

return;
}

tempCurPos = addFileEntriesToResponse(basepath, buffer, tempCurPos, maxSize, directoryName, &continueAfterFileName, &moreFollows);

if (tempCurPos < 0) {
Expand Down Expand Up @@ -1128,6 +1167,16 @@ mmsServer_handleFileRenameRequest(

if ((strlen(currentFileName) != 0) && (strlen(newFileName) != 0)) {

if ((mmsMsg_isFilenameSave(currentFileName) == false) || (mmsMsg_isFilenameSave(newFileName) == false))
{
if (DEBUG_MMS_SERVER)
printf("MMS_SERVER: remote provided unsave filename -> rejected\n");

mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_FILE_NON_EXISTENT);

return;
}

/* Call user to check if access is allowed */
if (connection->server->fileAccessHandler != NULL) {
MmsError access = connection->server->fileAccessHandler(connection->server->fileAccessHandlerParameter,
Expand Down

0 comments on commit 10622ba

Please sign in to comment.