- fixed path traversal vulnerability in MMS file services (LIB61850-357)

pull/410/head
Michael Zillgith 3 years ago
parent dd3e2a6870
commit 10622ba36b

@ -37,7 +37,6 @@ struct sDirectoryHandle {
DIR* handle; DIR* handle;
}; };
FileHandle FileHandle
FileSystem_openFile(char* fileName, bool readWrite) FileSystem_openFile(char* fileName, bool readWrite)
{ {

@ -82,6 +82,9 @@ mmsMsg_createExtendedFilename(const char* basepath, int bufSize, char* extendedF
LIB61850_INTERNAL FileHandle LIB61850_INTERNAL FileHandle
mmsMsg_openFile(const char* basepath, char* fileName, bool readWrite); mmsMsg_openFile(const char* basepath, char* fileName, bool readWrite);
LIB61850_INTERNAL bool
mmsMsg_isFilenameSave(const char* filename);
#endif /* (MMS_FILE_SERVICE == 1) */ #endif /* (MMS_FILE_SERVICE == 1) */
typedef struct sMmsServiceError typedef struct sMmsServiceError

@ -71,7 +71,6 @@ getFrsm(MmsConnection connection, int32_t frsmId)
return frsm; return frsm;
} }
static int32_t static int32_t
getNextFrsmId(MmsConnection connection) getNextFrsmId(MmsConnection connection)
{ {
@ -125,6 +124,15 @@ mmsClient_handleFileOpenRequest(
if (hasFileName) { if (hasFileName) {
if (mmsMsg_isFilenameSave(filename) == false) {
/* potential attack */
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: client provided unsave filename -> rejected\n");
mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_FILE_NON_EXISTENT);
}
else {
MmsFileReadStateMachine* frsm = getFreeFrsm(connection); MmsFileReadStateMachine* frsm = getFreeFrsm(connection);
if (frsm != NULL) { if (frsm != NULL) {
@ -158,6 +166,7 @@ mmsClient_handleFileOpenRequest(
else else
mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_RESOURCE_OTHER); mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_RESOURCE_OTHER);
} }
}
else else
goto exit_invalid_parameter; goto exit_invalid_parameter;

@ -570,6 +570,24 @@ mmsMsg_createExtendedFilename(const char* basepath, int bufSize, char* extendedF
#endif #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 FileHandle
mmsMsg_openFile(const char* basepath, char* fileName, bool readWrite) mmsMsg_openFile(const char* basepath, char* fileName, bool readWrite)
{ {
@ -620,7 +638,7 @@ mmsMsg_parseFileName(char* filename, uint8_t* buffer, int* bufPos, int maxBufPos
* characters. * characters.
*/ */
if (strstr(filename, "..") != NULL) { 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; return false;
} }

@ -235,8 +235,6 @@ mmsMsg_createFileOpenResponse(const char* basepath, uint32_t invokeId, ByteBuffe
response->size = bufPos; response->size = bufPos;
} }
void void
mmsServer_handleFileDeleteRequest( mmsServer_handleFileDeleteRequest(
MmsServerConnection connection, MmsServerConnection connection,
@ -266,6 +264,16 @@ mmsServer_handleFileDeleteRequest(
if (DEBUG_MMS_SERVER) if (DEBUG_MMS_SERVER)
printf("MMS_SERVER: mms_file_service.c: Delete file (%s)\n", filename); 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) { if (connection->server->fileAccessHandler != NULL) {
MmsError access = connection->server->fileAccessHandler(connection->server->fileAccessHandlerParameter, MmsError access = connection->server->fileAccessHandler(connection->server->fileAccessHandlerParameter,
connection, MMS_FILE_ACCESS_TYPE_DELETE, filename, NULL); connection, MMS_FILE_ACCESS_TYPE_DELETE, filename, NULL);
@ -344,6 +352,17 @@ mmsServer_handleFileOpenRequest(
if (hasFileName) { 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) { if (connection->server->fileAccessHandler != NULL) {
MmsError access = connection->server->fileAccessHandler(connection->server->fileAccessHandlerParameter, MmsError access = connection->server->fileAccessHandler(connection->server->fileAccessHandlerParameter,
connection, MMS_FILE_ACCESS_TYPE_OPEN, filename, NULL); connection, MMS_FILE_ACCESS_TYPE_OPEN, filename, NULL);
@ -690,6 +709,15 @@ mmsServer_handleObtainFileRequest(
if (hasSourceFileName && hasDestinationFilename) { 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 */ /* Call user to check if access is allowed */
if (connection->server->fileAccessHandler != NULL) { if (connection->server->fileAccessHandler != NULL) {
MmsError access = connection->server->fileAccessHandler(connection->server->fileAccessHandlerParameter, MmsError access = connection->server->fileAccessHandler(connection->server->fileAccessHandlerParameter,
@ -1023,6 +1051,17 @@ createFileDirectoryResponse(const char* basepath, uint32_t invokeId, ByteBuffer*
continueAfterFileName = NULL; 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); tempCurPos = addFileEntriesToResponse(basepath, buffer, tempCurPos, maxSize, directoryName, &continueAfterFileName, &moreFollows);
if (tempCurPos < 0) { if (tempCurPos < 0) {
@ -1128,6 +1167,16 @@ mmsServer_handleFileRenameRequest(
if ((strlen(currentFileName) != 0) && (strlen(newFileName) != 0)) { 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 */ /* Call user to check if access is allowed */
if (connection->server->fileAccessHandler != NULL) { if (connection->server->fileAccessHandler != NULL) {
MmsError access = connection->server->fileAccessHandler(connection->server->fileAccessHandlerParameter, MmsError access = connection->server->fileAccessHandler(connection->server->fileAccessHandlerParameter,

Loading…
Cancel
Save