- 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;
};
FileHandle
FileSystem_openFile(char* fileName, bool readWrite)
{

@ -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

@ -71,7 +71,6 @@ getFrsm(MmsConnection connection, int32_t frsmId)
return frsm;
}
static int32_t
getNextFrsmId(MmsConnection connection)
{
@ -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;

@ -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)
{
@ -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;
}

@ -235,8 +235,6 @@ mmsMsg_createFileOpenResponse(const char* basepath, uint32_t invokeId, ByteBuffe
response->size = bufPos;
}
void
mmsServer_handleFileDeleteRequest(
MmsServerConnection connection,
@ -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);
@ -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);
@ -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,
@ -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) {
@ -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,

Loading…
Cancel
Save