Há um tempo atrás eu tive a necessidade de verificar uma série de Buckets S3 na AWS, o objetivo era ver a possibilidade de de algum Bucket com permissão de escrita, de modo que fosse possível inserir algum arquivo dentro dele.
Depois de considerar várias possibilidades, imaginei que o método mais acertivo seria validar se com uma outra chave de acesso (Token) da AWS seria possível inserir um arquivo dentro de um outro Bucket, essa Prova de Conceito já seria suficiente para demonstrar que aquele Bucket estaria passível de ser comprometido.

Inicialmente pensei em criar um servidor para essa atividade, mas depois imaginei que como seria uma atividade que iria rodar apenas alguns dias por semana, não valeria muito a pena manter um EC2 apenas para isso.

Pesquisei outros meios e achei que o BitBucket seria a melhor opção para essa tarefa. Fiz a configuração pelo Pipeline baixando uma imagem Docker de um CentOS.

Eu queria fazer tudo dinamicamente, ou seja, era precisar tirar uma listagem de todos os Buckets existentes nas contas da AWS e depois verificar um por um para saber se algum deles teria permissão de escrita.

Então no pipeline do BitBucket eu inici com o download a imagem Docker do CentOS, depois iniciou algumas instalações que vou precisar, como do python e python-pip para baixar o “slackcliente” pois eu também queria que um aviso fosse enviado para um canal específico do Slack.

Também foi preciso instalar o AWSCLI, a interface de linha de comando da AWS. A instalação do AWSCLI se faz necessária por dois motivos:

  • Foi preciso configurar o perfil correto no AWSCLI para conseguir listar todos os buckets S3.
  • Depois era preciso configurar um outro perfil, o falso para fazer a tentativa de inserir arquivos dentro do Bucket.
pipelines:
    default:
        - step:
            name: HMG - Checking S3 Buckets
            image:
              name: fastexpress/machine:latest
              username: $DOCKER_USER
              password: $DOCKER_PWD
            script:
                - yum install epel-release -y
                - yum install python-pip -y
                - pip install --upgrade pip
                - yum install python3 -y
                - yum install python3-pip -y
                - pip3 install slackclient
                - pip install awscli
                - export SLACK_API_TOKEN=$SLACK_API_TOKEN
                - mkdir -p /root/.aws
                - aws --profile homologation configure set aws_access_key_id ${HMG_AWS_ACCESS_KEY_ID}
                - aws --profile homologation configure set aws_secret_access_key ${HMG_AWS_SECRET_ACCESS_KEY}
                - aws --profile homologation configure set region "us-east-1"
                - aws --profile fake configure set aws_access_key_id ${FAKE_AWS_ACCESS_KEY_ID}
                - aws --profile fake configure set aws_secret_access_key ${FAKE_AWS_SECRET_ACCESS_KEY}
                - aws --profile fake configure set region "us-east-1"
                - cp s3-sec-alerts.py /tmp/s3-sec-alerts.py && chmod +x /tmp/s3-sec-alerts.py
                - cp checkAllBucket.sh /tmp/checkAllBucket.sh && chmod +x /tmp/checkAllBucket.sh
                - cd /tmp
                - ./checkAllBucket.sh homologation fake
                - ls -lsh
                - cat /tmp/output.txt
                - python3 s3-sec-alerts.py

        - step:
            name: PRD - Checking S3 Buckets
            image:
              name: fastexpress/machine:latest
              username: $DOCKER_USER
              password: $DOCKER_PWD
            script:
                - yum install epel-release -y
                - yum install python-pip -y
                - pip install --upgrade pip
                - yum install python3 -y
                - yum install python3-pip -y
                - pip3 install slackclient
                - pip install awscli
                - export SLACK_API_TOKEN=$SLACK_API_TOKEN
                - mkdir -p /root/.aws
                - aws --profile production configure set aws_access_key_id ${PRD_AWS_ACCESS_KEY_ID}
                - aws --profile production configure set aws_secret_access_key ${PRD_AWS_SECRET_ACCESS_KEY}
                - aws --profile production configure set region "us-east-1"
                - aws --profile fake configure set aws_access_key_id ${FAKE_AWS_ACCESS_KEY_ID}
                - aws --profile fake configure set aws_secret_access_key ${FAKE_AWS_SECRET_ACCESS_KEY}
                - aws --profile fake configure set region "us-east-1"
                - cp s3-sec-alerts.py /tmp/s3-sec-alerts.py && chmod +x /tmp/s3-sec-alerts.py
                - cp checkAllBucket.sh /tmp/checkAllBucket.sh && chmod +x /tmp/checkAllBucket.sh
                - cd /tmp
                - ./checkAllBucket.sh production fake
                - python3 s3-sec-alerts.py

Algumas variáveis deixei apenas como de ambiente, porque o processo só iria ser executado uma vez pelo Pipeline na Infraestrutura do BitBucket.

export SLACK_API_TOKEN=$SLACK_API_TOKEN
aws –profile fake configure set aws_access_key_id ${FAKE_AWS_ACCESS_KEY_ID}

Algumas dessas variáveis configurei no Settings do projeto.

Depois disso, apenas faço chamados em outros scripts, um Shell Script que é quem vai gerar a lista de Buckets e pelo AWCLI vai tentar mover arquivos para dentro do Bucket e o outros script em Pythonfeito simplesmente para ler o arquivo de saída do script anterior e enviar para um Canal no Slack.

#!/bin/bash

s3_output_list="/tmp/bucket_list.lst"
poc_file="/tmp/poc.txt"
result="/tmp/stdout.txt"
output="/tmp/output.txt"
now=$(date)
COUNT=0

aws --profile $1 s3 ls | cut -d " " -f3 > $s3_output_list

while IFS= read -r line
  do
    echo "Prova de Conceito - Acesso nao autorizado [bucket = $line] - Squad XYZ [$now]"  > $poc_file
    echo "Testando o Bucket S3 - [$line] da conta AWS [$1]"
    aws s3 --profile $2 cp $poc_file s3://$line/poc.txt 1>> $result
    COUNT=$((COUNT + 1))
    echo "-----------------------------------------------------------------------------------------"
  done < "$s3_output_list"

cat $result | cut -d " " -f13 > $output

if grep -q "s3://" $output
then
        sed -i "1i Os Buckets abaixo estao com Public Access e permissao de Write Objects:" $output
        sed -i "1i Foram verificados $COUNT Buckets S3 na conta de [$1] - [$now]" $output
        sed -i "1i PoC - Processo para verificar se e possivel injetar arquivos dentro de um Bucket S3" $output
else
       echo "PoC - Processo para verificar se e possivel injetar arquivos dentro de um Bucket S3" >> $output
       echo "Foram verificados $COUNT Buckets S3 na conta de [$1] - [$now]" >> $output
       echo "Nenhum Bucket S3 publico foi localizado com permissao de Write Objects" >> $output

fi
#!/usr/bin/env python

import os
import slack

# --------------------------------------------------------------------- #
# GitHub Project: https://github.com/slackapi/python-slackclient
# Env var with Key: "SLACK_API_TOKEN"
# --------------------------------------------------------------------- #

client = slack.WebClient(token=os.environ['SLACK_API_TOKEN'])

output_file = "/tmp/output.txt"
channel ='#security-alerts'

file = open(output_file,"r+")
result = file.read()
message  = str(result)
response = client.chat_postMessage(
        channel=channel, text=message )

Depois de pronto, pelo BitBucket configurei apenas o agendamento para que o pipeline rodasse e após a finalização a mensagem fosse enviada para o Slack pelo script em Python.