C#: evitando a Injeção de SQL

A Injeção de SQL, ou em inglês SQL Injection, é uma vulnerabilidade que permite que algum usuário malicioso possa executar uma instrução em SQL dentro da aplicação, aproveitando uma brecha em uma consulta que permita acesso ao banco de dados.

Para demonstrar um exemplo desta vulnerabilidade, vamos criar um banco de dados de vendas, onde temos nossa tabela de usuários com alguns informações.

Abra o Visual Studio Code, e crie uma pasta chamada EvitandoAInjecaoDeSQL, e dentro dela outra chamada src. Em EvitandoAInjecaoDeSQL crie uma solução usando o comando dotnet new sln e logo em seguida abra a pasta src, adicione e logo abra um nova pasta chamada EvitandoAInjecaoDeSQL.Web e adicione um projeto do tipo MVC usando o comando dotnet new mvc, volte até a pasta EvitandoAInjecaoDeSQL e adicone o projeto na solução usando o comando  dotnet sln add .\src\EvitandoAInjecaoDeSQL.Web\EvitandoAInjecaoDeSQL.Web.csproj.

Adicione um controller na pasta Controllers do projeto de MVC chamado ContaController.cs e uma view chamada Login.cshtml na pasta Views/Conta.

A tela de login deve ser semelhante a esta, após abrir o site e digitar uma senha válida:

O nosso site está funcionando, então agora vamos aplicar o SQL Injection para verificar a vulnerabilidade. Como vimos, o campo usuário e senha só efetua login se for digitado um nome de usuário e uma senha correta. Mas vamos tentar burlar isto.

Para entdenr o que acontece no lado do banco de dados ao digitar o usuário e senha da captura de tela, vamos analisar a intrução SQL montada pelo aplicativo:

Se executarmos a instrução acima no SQL Server, temos o resultado 1, que é a informação que permite que o sistema permita o acesso.

Mas esta instrução é facilmente alterada usando alguns caracteres de ‘ (apóstrofo), fazendo a consulta ficar assim:

Que retorna um valor positivo, mesmo sem informar a senha.

Mas como isto é possível sem editar o SQL que está no código? Simples, pois a forma a instrução foi montada, permite que seja alterada, pois o SELECT é uma concatenação dos campos que são enviados no post e a o corpo da instrução, o C# não sabe o que é filtro e o que é comando de banco, ele monta primeiro uma string e depois executa no banco. Sendo assim, vamos recriar esta consulta direto no campo de senha.

Antes, tente digitar uma senha errada, para conferir se formulário está funcionando e acessando os dados corretamente.

Agora vamos explorar a vulnerabilidades, digitando no campo de senha ‘ OR ‘1’ = ‘1 e clique em login.

E acabamos de ser invadidos por uma falha bem simples no site, pois é possivel “editar” a instrução SQL antes de enviar. Este tipo de falha, pode ser tão grave que é até pode permitir acessar e alterar informações do próprio sistema operacional, dependendo da configuração do banco de dados.

Mas como consertamos este caso específico? A solução a seguir vai resolver este tipo de abertura, mas há outros tipos de falahas que podem precisar uma solução mais avançada. O que vamos fazer é passar parâmetros para o banco de dados em vez de montar todo o sql de uma vez, para isso, em vez de usar uma concatenação, mas nomer estes dados usando um @ (arroba antes) antes, então, para isto, vou comentar o código vulnerável do arquivo ContaController.cs e adicionar a forma mais segura, como segue:

Com isto, temos um código mais seguro. Outra solução, seria usar frameworks ORM, como Entity Framework ou NHibernate.

O projeto completo está disponível no meu GitHub:

https://github.com/tiagopariz/EvitandoAInjecaoDeSQL

Obrigado e um bom dia a todos.

 

Entity Framework: migrations com vários projetos e bancos de dados

Quando trabalhamos com soluções grandes, onde há vários projetos e cada um tem sua própria base de dados, assim como seu próprio versionamento usando Migrations do Entity Framework, fica meio complicado ficar alterando o Set as startup project e o Default Project na janela do Package Manager Console. Então, o ideal é apontar os projetos de configuração e dados na mesma linha de comando do Add-Migration e Update-Database.

Atualizando o banco de dados

Quando abrimos uma projeto que já tem migrations, precisamos atualizar o banco de dados, e para isso usamos o comando Update-Database. Mas podemos ser mais específico, e não precisar escolher nada em tela para que ele saiba onde achar a Connection String e Contexto, usando o comando abaixo.

Update-Database

Este comando atualiza o banco de dados com a ultima versão das migrations registradas, assim como roda algum Seed que pode popular tabelas.

-ProjectName

Nome do projeto onde está a configuração das entidades que representam os objetos do banco de dados, ou os DbSets.

-StartUpProjectName

O projeto que contém a Connection String para conexão com o banco de dados.

-ConfigurationTypeName

Nome completo, incluindo as namespaces, da entidade de configuração das migrations. Este arquivo é aquele que é gerado automaticamente ao usar o comando Enable-Migrations para ativar as migrações.

-Verbose

Este parâmetro exibe na tela todas as alterações efetuadas, assim como configurações definidas nos parâmetros anteriores.

Adicionando uma nova migração

Após atualizar o banco de dados, fazer as alterações nos objetos de domínio, precisamos adicionar a migração para depois enviar ao banco de dados as alterações versionadas, e novamente, é preciso que não precisemos definir o projeto de inicialização e dados. Para isso, use o comando a seguir:

Além dos parâmetros -ProjectName, -StartUpProjectName e -ConfigurationTypeName que já foram explicados no tópico anterior, precisamos incluir o parâmetro -Name e definir um nome que identifique qual alteração será feita no banco de dados.

Após adicionar a migration, só é preciso digitar o comando Update-Database com os parâmetros corretos.

VB.NET MVC: traduzindo do C# as aulas do Cleyton Ferrari

Cleyton Ferrari foi um dos primeiros profissionais de desenvolvimento C# brasileiros que fez um curso bem estruturado sobre MVC e Entity Framework, explicando nos detalhes como funcionava cada elemento, e melhor, tudo gratuito no Youtube.

Na época eu trabalhava com VB.NET, e por isso eu precisei traduzir o projeto didático dele para a linguagem que eu usava. Foi uma tarefa com dois ganhos, o primeiro que serviu para eu treinar meu C# que ainda era bem básico e segundo para entender a fundo o conceito do MVC e ORM com Entity Framework.

Não havia me preocupado em criar um post em 2013, e mal sabia usar o GitHub, mas guardei os fontes lá, e eles existem até hoje, por isso resolvi escrever para registrar isso aqui. Mas antes de entrar no meu repositório você quiser conferir os cursos dele, que apesar de ser feito para o ASP.NET MVC 3 ainda é bem válido:

E acesse aqui os projetos traduzido para VB.NET:

https://github.com/tiagopariz/CleytonFerrari

 

OpenCover: analisando e automatizando a cobertura de código

Cobertura de código é essencial para sabermos o quanto estamos investindo na qualidade do nosso projeto. Para isso, até temos recursos nativos na IDE do Visual Studio, mas apenas na edição Enterprise. Mas nem tudo está perdido para quem não tem acesso à edições “premium” do VS! Podemos substituir tranquilamente pelo OpenCover, que atende a este necessidade com grande eficiência e elegância. E isso veremos no projeto de exemplo que iremos montar com o Visual Studio 2017 e o NUnit.

Observação: o OpenCover atende outras plataformas de testes, inclusive a nativa da Microsoft, irei o Usar o NUnit apenas por escolha própria, fique a vontade para integrar com a ferramente que convir.

Crie a solução dos projetos

Crie uma solução vazia chamada CodeCoverage, e inclua três Solution Folders chamadas Domain, Presentation e Tests. na pasta Tests, inclua mais duas subpastas chamadas Domain e Presentation, que serão os testes específicos de cada camada.

Projeto de domínio

Crie um projeto do tipo Class Library chamado CodeCoverage.Domain dentro da pasta Domain, e dentro do projeto inclua outra pasta chamada Entities. Nesta pasta inclua três classes chamadas State, City e Person, pois estas classes que serão analisadas pelo OpenCover, afim de gerar um relatório com o percentual de cobertura por testes unitários. A seguir o código de cada uma delas:

Classe de estados

Classe de cidades

Classe de pessoas

Projeto de Console

O projeto de console, será a nossa camada de apresentação, onde vamos trabalhar com DTOs, que são representações dos dados das nossas classes de domínio. Para isso, na pasta Presentation da solução, adicione um projeto do tipo Console Application chamado CodeCoverage.Prompt, e dentro do projeto inclua um pasta chamada Dto. Onde residirão as 3 classes de dados que serão a StateDto, CityDto e a PersonDto, como segue:

DTO de estado

DTO de cidades

DTO de pessoa

Edite a classe Program.cs e crie o método  que faz os mapeamento entre o Domínio e DTO e o código que exibe os dados em tela.

Observação: não é intenção deste artigo explicar como funciona processos de mapeamentos entre entidades de domínio, DTOs e ViewModels. Mas fica a dica para você procurar na internet qual o funcionamento de um AutoMapper, por exemplo.

Testes

Expanda a pasta de solução Tests e dentro da pasta Domain adicione um projeto do tipo Unit Test Project chamado CodeCoverage.Domain.Tests.

Neste projeto, inclua uma pasta chamada Entities, e dentro dela vamos incluir duas classes de testes, mas antes é preciso instalar o pacote NUnit, para isso abra o Package Manager Console selecione o projeto de testes do domínio e digite:

Adicione uma referência para o projeto de domínio, para que os testes possam acessar as entidades. Então adicione as classes de testes na pasta Entities.

Testes da classe de estado

Testes da classe de pessoa

Adicione um outro projeto do tipo Unit Test Project chamado CodeCoverage.Prompt.Tests e adicione uma referência do projeto CodeCoverage.Prompt e instale o pacote do NUnit também.

Crie uma pasta chamada Dto, e dentro dela inclua uma classe de testes chamada PersonDtoTests para pessoas.

Usando o Cake

Abra o Powershell, e se posicione na pasta da solução, e logo após digite o comando para instalar o pacote que compila e executa o script do Cake:

Ainda na pasta raiz da solução, crie um novo arquivo chamado build.cake e crie também a pasta docs/testsResults/Reports, que será onde ficará os resultados dos testes.

Dica: você pode adicionar o arquivo build.cake à solução, para que ele faça parte do projeto, mas é muito mais produtivo usar o Visual Studio Code e a extensão do Cake, conforme expliquei neste artigo.

Volte ao Powershell e digite o comando .\build.ps1 para executar o script do Cake.

Após a execução do script, o Report Generator irá compilar os arquivos xml do OpenCover e gerar uma visualização mais amigável e detalhada e ainda abrir um sumário no seu navegador padrão, incluind um histório de cobertura.

.gitignore

Se você está usando o arquivo .gitignore padrão do Visual Studio – aquele que é fornecido, por exemplo, pelo GitHub ou Visual Studio Online – será preciso alterar para que ele ignore os arquivos compilados do Cake e não suba para o repositório do GitHub. Para isso encontre o trecho a seguir:

E descomente as duas últimas linhas.

Pronto, agora podemos acompanhar a evolução dos testes de nosso aplicativo de forma elegante e segura.

Até a próxima e se quiser, acesse o projeto completo em meu GitHub:

https://github.com/tiagopariz/CodeCoverage

Cake: automatizando tarefas

O Cake é um automatizador de tarefas construído sobre o compilador do C# e de fácil configuração.

Instalando o Cake

Para usar o Cake, precisamos baixar os scripts de automação que vem todos em um arquivo chamado build.ps1 que roda no Powershell. Para isso, abra o Powershell, crie uma pasta chamada CakeAutomation.

Com a pasta criado, execute o comando para baixar o pacote com as configurações.

Pronto, o ambiente está configurado, agora precisamos de um projeto para automatizar.

Crie uma aplicação de exemplo

Eu tenho um post que ensina como criar uma aplicação console com o Visual Studio Code, vamos usar este exemplo para automatizar uma build:

Visual Studio Code: como criar uma aplicação console em C#

Crie o script de build da aplicação com o Cake

Na raiz do projeto, inclua uma arquivo chamado build.cake, que será onde residirá todo o código de automação. Edite o arquivo conforme segue:

Agora o script está pronto para ser rodado, para isso, é preciso que você esteja na raiz do projeto, via powershell digite o comando a seguir:

Site oficial

https://cakebuild.net/

Extensão para VS Code:

https://marketplace.visualstudio.com/items?itemName=cake-build.cake-vscode

Repositório no GitHub:

https://github.com/tiagopariz/CakeAutomation

Visual Studio: alterar o framework padrão para novos projetos

Introdução

Muitas vezes é preciso que todos os novos projetos já estejam em uma versão do .Net Framework específica, ou simplesmente, que já seja criado com o target na última versão disponível no Visual Studio.

Alterando a versão padrão

Abra o Visual Studio, clique em File, em seguida em New e por último em Project…

Anote a versão do .Net Framework que será a padrão para os novos projetos, como por exemplo “4.6.1”.

Pressione as teclas Win + R, em Abrir digite o comando regedit e clique em Ok.

A janela do Editor do Registro será exibida.

Localize a chave HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\14.0\NewProjectDialog, e edite a chave fxVersion para a versão do .Net Framework desejada.

Observação: onde está escrito 14.0, que equivale a versão do Visual Studio 2015, pode ser alterada para a versão do seu Visual Studio, como por exemplo, 13.0 para o 2013.

O Visual Studio 2017 não precisa desta configuração, pois ele lembra a última versão usada ao criar um projeto.

Pronto, agora todas os novos projetos serão automaticamente definido com a versão configurada por padrão.

NuGet: atualizar um pacote instalado no projeto

Introdução

Para atualizar um pacote NuGet que já está instalado em uma solução, é muito simples, porém, é preciso muita cautela e talvez alguma revisão de código. A seguir eu mostro uma atualização do pacote FluentValidator da versão 2.0.0 para a última versão.

Instale um pacote NuGet antigo

Primeiro, vamos instalar uma versão antiga do pacote FluentValidator, em uma nova solução com um projeto console.

Crie a solução com um projeto do tipo Console Application chamada NugetUpdatePackage.

Clique no menu Tools, em seguida em NuGet Package Manager e finalmente em Package Manager Console.

Em Package Manager Console, em Default project, selecione o projeto que será instalado o pacote.

Digite o comando a seguir, que irá instalar a versão 2.0.0 do FluentValidator, que não é a última:

Edite a classe Program.cs, conforme segue:

Execute o programa, e verifique o funcionamento.

Atualizando o pacote para a ultima versão

Abra a janela Package Manager Console, em Default project, selecione o projeto que será atualizado o pacote, e digite o comando a seguir, que irá atualizar para a ultima versão do FluentValidator:

Agora o nosso projeto está com a última versão, todavia, será preciso revisar o código, pois, há algumas alterações na forma de usar o pacote.

O método IsValid parece não estar funcionando, e para entender o problema, precisamos ler a documentação, ou procurar pelo recurso de Intellisense da própria IDE. E neste caso conseguimos deduzir pelo por ele mesmo.

Pronto, nosso código voltou a compilar.

 

C# with Patterns: Adapters

Na série C# with Patterns, que mostra como usar padrões de arquitetura em programação com C#, vamos conhecer o padrão de adaptadores, ou Adapters Pattern.

Continuar lendo C# with Patterns: Adapters