Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Para um sistema de arquivos, a maioria dos trabalhos de segurança interessantes ocorre durante o processamento de IRP_MJ_CREATE. É esta etapa que deve analisar a solicitação de entrada, determinar se o chamador tem direitos apropriados para executar a operação e conceder ou negar a operação conforme apropriado. Felizmente, para desenvolvedores de sistemas de arquivos, a maioria do mecanismo de decisão é implementada dentro do Monitor de Referência de Segurança. Assim, na maioria dos casos, o sistema de arquivos só precisa chamar as rotinas apropriadas do Monitor de Referência de Segurança para determinar corretamente o acesso. O risco para um sistema de arquivos ocorre quando ele não chama essas rotinas conforme necessário e concede acesso inadequado a um chamador.
Para um sistema de arquivos padrão, como o sistema de arquivos FAT, as verificações feitas como parte do IRP_MJ_CREATE são principalmente verificações semânticas. Por exemplo, o sistema de arquivos FAT tem várias verificações para garantir que o processamento de IRP_MJ_CREATE seja permitido com base no estado do arquivo ou diretório. Essas verificações feitas pelo sistema de arquivos FAT incluem verificações para mídia de somente leitura (por exemplo, tentativas de realizar operações destrutivas de "criação", como sobrescrever, em mídia de somente leitura não são permitidas), verificações de acesso ao compartilhamento e verificações de bloqueio de oportunidade. Uma das partes mais difíceis desta análise é perceber que uma operação em um nível (o nível de arquivo, por exemplo) pode, de fato, ser desautorizada devido ao estado de um recurso de nível diferente (o nível de volume, por exemplo). Por exemplo, um arquivo pode não ser aberto se outro processo tiver bloqueado exclusivamente o volume. Os casos comuns a verificar incluiriam:
O nível de arquivo aberto é compatível com o estado do nível de volume? Deve-se respeitar o bloqueio ao nível do volume. Assim, se um processo mantém um bloqueio de nível de volume exclusivo, apenas threads dentro desse processo podem abrir arquivos. Threads de outros processos não devem ter permissão para abrir arquivos.
O nível de arquivo aberto é compatível com o estado da mídia? Certas operações "create" modificam o arquivo como parte da operação "create". Isso incluiria sobrescrever, substituir e até mesmo atualizar a última hora de acesso no arquivo. Essas operações de "criação" não são permitidas em mídia somente leitura e o último horário de acesso não é atualizado.
O nível de volume aberto é compatível com o estado do nível de arquivo? Uma abertura de volume exclusiva não será permitida se houver arquivos existentes abertos no volume. Este é um problema comum para os novos desenvolvedores porque eles tentam abrir o volume e se apercebem que ele falha. Quando isso falha, FSCTL_DISMOUNT_VOLUME pode ser usado para invalidar alças abertas e forçar uma desmontagem, permitindo acesso exclusivo ao volume recém-montado.
Além disso, os atributos de arquivo devem ser compatíveis. Um ficheiro com o atributo de leitura apenas não pode ser aberto para acesso de escrita. Observe que o acesso desejado deve ser verificado após a expansão dos direitos genéricos. Por exemplo, esta verificação dentro do sistema de ficheiros FASTFAT está na função FatCheckFileAccess (consulte o ficheiro de origem Acchksup.c das amostras do fastfat que o WDK inclui).
O exemplo de código a seguir é específico para a semântica FAT. Um sistema de arquivos que implemente DACLs também, faria uma verificação de segurança adicional usando as rotinas do Monitor de Referência de Segurança (SeAccessCheck, por exemplo.)
//
// check for a read-only Dirent
//
if (FlagOn(DirentAttributes, FAT_DIRENT_ATTR_READ_ONLY)) {
//
// Check the desired access for a read-only Dirent
// Don't allow
// WRITE, FILE_APPEND_DATA, FILE_ADD_FILE,
// FILE_ADD_SUBDIRECTORY, and FILE_DELETE_CHILD
//
if (FlagOn(*DesiredAccess, ~(DELETE |
READ_CONTROL |
WRITE_OWNER |
WRITE_DAC |
SYNCHRONIZE |
ACCESS_SYSTEM_SECURITY |
FILE_READ_DATA |
FILE_READ_EA |
FILE_WRITE_EA |
FILE_READ_ATTRIBUTES |
FILE_WRITE_ATTRIBUTES |
FILE_EXECUTE |
FILE_LIST_DIRECTORY |
FILE_TRAVERSE))) {
DebugTrace(0, Dbg, "Cannot open readonly\n", 0);
try_return( Result = FALSE );
}
Uma verificação mais sutil implementada pelo FASTFAT é garantir que o acesso solicitado pelo chamador seja algo sobre o qual o sistema de arquivos FAT esteja ciente (na função FatCheckFileAccess em Acchksup.c a partir da amostra fastfat que o WDK contém):
O exemplo de código a seguir demonstra um conceito importante para a segurança do sistema de arquivos. Verifique se o que é passado para o seu sistema de arquivos não está fora dos limites do que você espera. A abordagem conservadora e adequada do ponto de vista da segurança é que, se você não entender uma solicitação de acesso, deverá rejeitá-la.
//
// Check the desired access for the object.
// Reject what we do not understand.
// The model of file systems using ACLs is that
// they do not type the ACL to the object that the
// ACL is on.
// Permissions are not checked for consistency vs.
// the object type - dir/file.
//
if (FlagOn(*DesiredAccess, ~(DELETE |
READ_CONTROL |
WRITE_OWNER |
WRITE_DAC |
SYNCHRONIZE |
ACCESS_SYSTEM_SECURITY |
FILE_WRITE_DATA |
FILE_READ_EA |
FILE_WRITE_EA |
FILE_READ_ATTRIBUTES |
FILE_WRITE_ATTRIBUTES |
FILE_LIST_DIRECTORY |
FILE_TRAVERSE |
FILE_DELETE_CHILD |
FILE_APPEND_DATA))) {
DebugTrace(0, Dbg, "Cannot open object\n", 0);
try_return( Result = FALSE );
}
Felizmente para os sistemas de arquivos, uma vez que a verificação de segurança tenha sido feita durante o processamento inicial de criação, as verificações de segurança subsequentes são realizadas pelo gerenciador de E/S. Assim, por exemplo, o gerenciador de E/S garante que os aplicativos de modo de usuário não executem uma operação de gravação em um arquivo que foi aberto apenas para acesso de leitura. Na verdade, um sistema de ficheiros não deve tentar aplicar semânticas de apenas leitura sobre o objeto de ficheiro, mesmo que tenha sido aberto apenas para acesso de leitura, durante a rotina de despacho IRP_MJ_WRITE. Isso ocorre devido à maneira como o gerenciador de memória associa um objeto de arquivo específico a um determinado objeto de seção. A escrita subsequente dessa seção será enviada como operações IRP_MJ_WRITE sobre o objeto de arquivo, mesmo que o ficheiro tenha sido aberto em modo de leitura apenas. Em outras palavras, a imposição de acesso é feita quando um identificador de arquivo é convertido no objeto de arquivo correspondente nos pontos de entrada de serviço do sistema Nt por ObReferenceObjectByHandle.
Há dois locais adicionais dentro de um sistema de arquivos onde as verificações semânticas de segurança devem ser feitas tal como no processamento "criar":
Durante o processamento de renomeação ou ligação física.
Ao processar operações de controle do sistema de arquivos.
O processamento de alteração de nome e o processamento de controle do sistema de arquivos são discutidos nas seções subsequentes.
Observe que esta não é uma lista exaustiva de questões semânticas relacionadas com o processamento de "criar". A intenção desta seção é chamar a atenção para esses problemas para desenvolvedores de sistemas de arquivos. Todos os problemas semânticos devem ser identificados para um sistema de arquivos específico, implementados para atender à semântica específica e testados para garantir que a implementação lide com os vários casos.