Segurança com Go Parte II: Eficiência e confiabilidade na era digital

Segurança com Go Parte II: Eficiência e confiabilidade na era digital

Na primeira parte do nosso tópico, fizemos uma breve introdução ao Go e como ele é utilizado na segurança cibernética, além de realizar alguns exercícios básicos. Nesta segunda parte tentarei ir um pouco mais longe através de exercícios práticos, que têm caráter meramente educativo.

Esclareço que, para isso, utilizo o sistema operacional Kali Linux, que é recomendado por possuir algumas ferramentas pré-instaladas e dependências para o desenvolvimento de nossas ferramentas em Go.

1. Scanner de porta TCP

Um dos detalhes mais comuns na realização de auditorias ou outros tipos de atividade dentro da segurança informática é a verificação do nosso alvo ou máquina.

Devido ao meu trabalho, tenho realizado algumas auditorias a alguns clientes e infra-estruturas, o que me permite dizer-lhe que se está apenas a começar na segurança informática, deve sempre efectuar um scan à máquina ou alvo, de forma a encontrar portas abertas, que posteriormente podem ser testadas e verificar se apresentam alguma vulnerabilidade. Dito isto, prosseguimos com as instruções para criar nosso scanner de porta TCP.

Abrimos nosso editor de código (neste caso usarei o Vim através do terminal Kali Linux) e criamos nosso arquivo com o seguinte comando:

Figura 1. Criar um arquivo Go. Fonte: Bladimir Peláez.

Figura 2. Livrarias básicas. Fonte: Bladimir Peláez.


Como você pode ver na figura, precisamos importar algumas bibliotecas para que nosso scanner funcione. Caso contrário, ocorreremos alguns erros ao executar nosso programa em Go. Antes de continuar, deixe-me explicar um pouco sobre essas livrarias.

  • fmt: fornece funções para formatar texto de saída e entrada. É amplamente utilizado para imprimir mensagens no console e formatar strings de texto.
  • net: é essencial para programação de rede em Go. Fornece funções e tipos de dados para trabalhar com conexões de rede, como conexões TCP/IP e UDP.
  • strconv: é usado para converter cadeias de caracteres e tipos de dados numéricos, como números inteiros e flutuantes.
  • time: O próprio nome já diz sua função, pois basicamente oferece funcionalidades para trabalhar com horas e gerenciar datas e horários em Go.

Agora podemos continuar adicionando a função principal ao nosso programa.

Figura 3. Função principal. Fonte: Bladimir Peláez.


Como você pode ver, defini a função principal do nosso programa. Esta função fará o processo de digitalização com base no site ou URL fornecido. Enfatizo que utilizo apenas um site de teste. Agora deixe-me dar uma breve explicação do que acontece nesta função.

  • func main: é dizer ao Go que é uma função.
  • target := "testhtml5.vulnweb.com": define a variável target que armazena o nome do nosso alvo no qual a varredura será realizada.
  • for port := 1; port <= 1024; port++: começa um loop for que passa pelas portas 1 a 1024, do tipo TCP e bem conhecidas.
  • address := target + ":" + strconv.Itoa(port): Basicamente, cria uma string que combina o nome do servidor com o número da porta atual.
  • conn, err := net.DialTimeout("tcp", address, time.Second): tenta estabelecer uma conexão TCP com o servidor e usa um tempo limite de um segundo.
  • if err != nil { continue }: verifica se ocorreu um erro ao tentar conectar. Se ocorrer um erro (indicando que a porta está fechada ou não respondendo), o loop continua para a próxima porta sem exibir mensagem.
  • defer conn.Close(): Se a conexão for estabelecida com sucesso, a conexão será agendada para fechar no final da função.
  • fmt.Printf("Puerto %d abierto\n", port): Se a conexão for estabelecida com êxito, será exibida uma mensagem indicando que a porta está aberta no número da porta atual.
Figura 4. Scanner TCP completo com Go. Fuente: Bladimir Peláez.


Depois de explicado o acima exposto e como podemos ver na imagem, temos o nosso programa Go totalmente pronto. Agora executamos no terminal para ver o resultado.

Figura 5. Executando a varredura. Fonte: Bladimir Peláez.


Iniciamos nosso programa com o comando go run escaner.go. Feito isso, esperamos até que nosso programa termine e retorne os resultados. No meu caso usei um site de teste e como vocês podem ver indicou que a porta 80 está aberta no site.

Às vezes demora um pouco, tudo depende da sua rede e do site que você deseja digitalizar. Recomendo que, se quiser praticar, faça-o de forma controlada, seja em ambientes virtuais ou em redes locais de sua propriedade.

2. Verificação básica de senha

Você já se perguntou o quão seguras são as senhas que você cria? Você certamente sabe que é de extrema importância proteger nossos dados e informações, certo? Nesta parte, mostrarei como usar Go para verificar a segurança das senhas e se elas atendem aos padrões básicos recomendados.

Inicialmente vou criar meu arquivo chamado password.go. Lembre-se que eu uso o Vim através do terminal, mas você pode usar qualquer editor que desejar.

Figura 6. Arquivo password.go. Fonte: Bladimir Peláez.


Criamos nosso arquivo e importamos as bibliotecas necessárias. Anteriormente, expliquei a função da biblioteca fmt e, no caso do regexp, é usado para trabalhar com expressões regulares.

Figura 7. Função de entrada. Fonte: Bladimir Peláez.


Temos nossa função principal definida, na qual será executada a maior parte da lógica do programa. Mas primeiro deixe-me explicar um pouco sobre o que esta função contém.

  • password := "P@ssw0rd": Os personagens que queremos testar são armazenados aqui. No meu caso, adicionei um exemplo de senha básica.
  • isStrong := isStrongPassword(password): Nesta linha chamamos uma função que definiremos posteriormente e passaremos nossa variável como parâmetro password.
  • if isStrong { ... } else { ... }: aqui fazemos a verificação isStrong para determinar se a senha é forte ou não.
Figura 8. Função isStrongPassword. Fonte: Bladimir Peláez.

Esta função basicamente aceita um valor como argumento. Aqui você recebe o valor password da função main definido anteriormente e retorna um valor booleano true ou false que indica se a senha atende ou não a determinados critérios de segurança. Para entender um pouco mais sobre isso, e como já fiz antes, vou explicar um pouco sobre o que acontece em cada linha deste código.

  • if len(password) < 8 { return false }: aqui você precisa verificar se a senha possui pelo menos 8 caracteres. Caso contrário, ele nos retornará false.
  • if matched, _ := regexp.MatchString([A-Z], password); !matched { return false }: Uma expressão regular é usada para verificar se a senha contém pelo menos uma letra maiúscula. Se não contiver, será retornado false.
  • if matched, _ := regexp.MatchString([0-9], password); !matched { return false }: Assim como na verificação anterior, é utilizada uma expressão regular, mas neste caso para verificar se a senha contém pelo menos um número.

Finalmente, se a senha passar em todas essas verificações, ela será retornada true, indicando que atende aos critérios de segurança.

Agora executamos nosso programa com o comando go run password.go:

Figura 9. Execução do password.go. Fonte: Bladimir Peláez.

Quando executamos nosso programa, ele nos informa que nossa senha é forte e segura. Convido você a experimentar você mesmo se tiver curiosidade, pois é importante verificar as senhas que você cria e evitar que pessoas mal-intencionadas as quebrem se forem muito fracas.

Na minha experiência com algumas ferramentas de quebra de senhas, percebi que há muitas pessoas que usam senhas com comprimento um pouco maior que o normal e aparentemente acreditam que a prática é segura. Se você realmente deseja ter uma senha confiável e segura, utilize combinações de letras, números, letras maiúsculas e, principalmente, alguns caracteres especiais, pois isso ajuda a dificultar bastante a decifração e você consegue proteger melhor seus dados e informações.

3. Gerador de senha com Go

Nesta última parte mostrarei como usar o Go para criar um gerador de senhas fortes, algo muito útil na hora de definir uma nova senha. Suponha que você se inscreva em um novo site onde, obviamente, eles pedem uma senha. A maioria das pessoas usa as mesmas senhas para todos os sites que acessam e, em alguns casos, geralmente alteram apenas um caractere.

Eu fui um desses e deixe-me dizer que fiz isso para não ter que escrevê-los ou salvá-los para cada site, mas percebi o grande risco que isso representa, pois basta que alguém tenha sua senha e tente acessar alguns sites usando sua mesma senha. A seguir, mostrarei como criei um gerador de senhas fortes com Go.

Figura 10. Criação do genpassword.go. Fonte: Bladimir Peláez.

Figura 11. Importando livrarias. Fonte: Bladimir Peláez.

Acima podemos ver a criação do nosso arquivo e, posteriormente, a importação das bibliotecas necessárias ao nosso programa. Você pode notar que chamei a biblioteca de fmt, algo necessário em quase todos os programas criados com Go. A biblioteca math/rand é usada para gerar números aleatórios e o pacote time ajuda no gerenciamento do tempo (como já indiquei).

Figura 12. Funções do nosso programa. Fonte: Bladimir Peláez.

Defini duas funções: a primeira é gerar a senha e a segunda é a nossa função principal ou de entrada onde é produzida a lógica do nosso programa. Agora vou explicar o que você vê aqui.

  • func generateRandomPassword(length int) string: define a função que toma como argumento um número inteiro indicando o comprimento da senha a ser gerada.
  • const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789": variável que contém todos os caracteres com os quais serão feitas todas as combinações para nossa senha.
  • seed := rand.NewSource(time.Now().UnixNano()): crie uma fonte de números aleatórios rand.Source usando carimbo de data/hora atual em nanossegundos time.Now().UnixNano() como semente seed. Isso garante que toda vez que você executar o programa, uma senha diferente apareça.
  • random := rand.New(seed): cria um gerador de números aleatórios usando a semente definida acima.
  • password := make([]byte, length): cria um slice de bytes chamado password com o comprimento especificado pelo argumento length. Este slice será usado para armazenar a senha gerada.
  • for i := range password { ... }: inicia um loop for que percorre cada índice do slice password.
  • password[i] = charset[random.Intn(len(charset))]: Em cada iteração do loop, um caractere é selecionado aleatoriamente do conjunto charset usando gerador de números aleatórios randome é armazenado na posição correspondente do slice password.
  • return string(password): retorna a senha gerada como uma sequência de caracteres.

Agora vamos ao recurso main:

  • password := generateRandomPassword(12): chamamos a função generateRandomPassword com um argumento de comprimento 12 caracteres e armazenamos a senha gerada na variável password.
  • fmt.Printf("Contraseña generada: %s\n", password): imprimimos a senha gerada no console usando fmt.Printf. A senha será exibida no console como resultado da execução do programa.

Executamos nosso programa e podemos ver o seguinte:

Figura 13. Execução de genpassword.go. Fonte: Bladimir Peláez.

Na figura notamos como quando executamos nosso programa várias vezes, ele retorna uma sequência de caracteres completamente diferente. Podemos utilizar essas sequências de caracteres como senhas para alguns sites e você pode se sentir confiante ao utilizá-las, já que meu foco foi criar um programa que preserve boas práticas quanto aos critérios e proteção das senhas que são geradas.

Conclusão

Depois de explorar mais a fundo o papel do Go na segurança cibernética, estou ainda mais impressionado com sua eficiência e confiabilidade neste campo crítico. A capacidade do Go de criar binários altamente eficientes e otimizados é essencial na criação de aplicações de segurança que exigem respostas rápidas e gerenciamento eficiente de recursos.

Além disso, seu foco na simultaneidade permite o desenvolvimento de sistemas de detecção e resposta em tempo real, uma necessidade na segurança cibernética moderna. A minha confiança no Go como uma ferramenta essencial para melhorar a segurança dos sistemas digitais só tem crescido à medida que me aprofundo nas suas capacidades e vantagens nesta área.

Com Go, estou preparado para enfrentar desafios constantes e contribuir para um ambiente digital mais seguro e confiável.

Espero que este guia tenha sido útil para você. Saudações!

💡
As opiniões e comentários expressos neste artigo são de propriedade exclusiva de seu autor e não representam necessariamente o ponto de vista da Revelo.

A Revelo Content Network acolhe todas as raças, etnias, nacionalidades, credos, gêneros, orientações, pontos de vista e ideologias, desde que promovam diversidade, equidade, inclusão e crescimento na carreira dos profissionais de tecnologia.