Analizar vulnerabilidades en tu código con CodeQL en local

En un artículo anterior compartí contigo lo importante que es traer la seguridad al día a día de los desarrolladores. Si bien en Azure DevOps podemos hacer uso de herramientas de terceros para cumplir nuestro cometido, GitHub nos provee de diferentes herramientas que nos permiten también ejecutar este tipo de tareas. Hoy quiero hablarte de una de ellas llamada CodeQL, que nos ayuda a analizar el código en busca de vulnerabilidades. Para este artículo quiero mostrarte cómo usarla desde tu máquina local.

¿Qué es CodeQL?

Antes de jugar con ella, contarte que CodeQL pertenece al grupo de herramientas denominadas SAST (Static Application Security Testing) y GitHub la ofrece de forma gratuita para todos los repositorios públicos de GitHub.com y a través de la licencia GitHub Advanced Security. Esta genera una base de datos con tu código sobre la que se podrán realizar consultas para los diferentes lenguajes soportados a día de hoy. Existen muchas ya generadas por parte del equipo de CodeQL listas para usar, aunque puedes crear también las tuyas propias. Esta herramienta puede utilizarse de diferentes maneras: usando GitHub Actions, la linea de comandos o integrándola con herramientas de CI de terceros. En este artículo te quiero mostrar cómo usarla a través de la línea de comandos.

Importante: esta herramienta requiere de licencia GitHub Advanced Security en aquellos supuestos que no sean académicos u open source.

Instalación y configuración de CodeQL en local

En este ejemplo voy a utilizar los binarios para MacOs, pero que sepas que también están disponibles para Windows y Linux. Lo primero que debo hacer es descargarme la última versión para mi sistema operativo, creo una carpeta llamada codeql-home donde almacenaré el directorio resultante y descomprimo los binarios allí:

# Download CodeQL for mac with cURL
curl -L https://github.com/github/codeql-cli-binaries/releases/download/v2.8.2/codeql-osx64.zip -o codeql-osx64.zip
# Create a folder for CodeQL
mkdir $HOME/codeql-home
# Unzip the file in $HOME/codeql-home folder
unzip codeql-osx64.zip -d $HOME/codeql-home && rm codeql-osx64.zip

Lo siguiente que vas a necesitar son las consultas ya construidas por el equipo de CodeQL que te facilitarán el análisis del código. Para ello, en la misma carpeta codeql-home clona el repositorio donde se alojan, pero renombra el mismo para que no coincida en nombre con el directorio de los binarios:

# Download queries and add them to the CodeQL home folder
cd $HOME/codeql-home
git clone --recursive https://github.com/github/codeql.git codeql-repo

Dentro de la carpeta codeql-home deberias de tener ahora dos directorios: codeql y codeql-repo al mismo nivel:

Contenido del directorio codeql-home

Para comprobar que todo funciona correctamente, exporta a la variable de entorno PATH la ruta del directorio codeql-home/codeql:

# Add the CodeQL home folder to the PATH
export PATH=$PATH:$HOME/codeql-home/codeql

Y lanza estos dos comandos:

# Check the configuration
codeql resolve languages
codeql resolve qlpacks

El primero de ellos te devolverá un listado con los lenguajes soportados:

codeql resolve languages

El segundo los packs de consultas detectados en el directorio codeql-repo:

codeql resolve qlpacks

Ahora ya estás list@ para buscar vulnerabilidades tu código 😃

Crear una base de datos de tu código con CodeQL

Ahora que ya tienes la herramienta descargada y configurada, lo siguiente es crear la base de datos que CodeQL necesita para consultar las potenciales vulnerabilidades que pueda tener tu código. Para ello posicionate en el repositorio que quieres analizar y ejecuta el siguiente comando:

# Create a database of my code
codeql database create codeqldb --language=csharp

En este caso estoy utilizando un código desarrollado con ASP.NET Core MVC, por lo que el lenguaje será csharp. Una vez que finalice el proceso se habrá creado un directorio llamado codeqldb con la base de datos.

Consultar la base de datos

El siguiente paso es realizar consultas sobre la base de datos generada. Pero ¿qué consultas hago y cómo? Gracias al repositorio que has clonado, podemos utilizar diferentes conjuntos de consultas construidas por el equipo de CodeQL, en lenguaje QL, que nos harán la vida más fácil. Además las han agrupado en tres categorías:

  • Code Scanning: son las consultas que se lanzan por defecto cuando ejecutas la herramienta desde GitHub.
  • Security Extended: consultas de menor severidad y precisión que las anteriores.
  • Security and quality: además de las consultas de seguridad también lanza consultas de calidad del código.

Puedes ejecutar cada una de ellas a través de los siguientes comandos:

CODEQL_SUITES_PATH=$HOME/codeql-home/codeql-repo/csharp/ql/src/codeql-suites
RESULTS_FOLDER=codeql-results
mkdir -p $RESULTS_FOLDER
# Code Scanning suite: Queries run by default in CodeQL code scanning on GitHub.
codeql database analyze codeqldb $CODEQL_SUITES_PATH/csharp-code-scanning.qls \
--format=sarifv2.1.0 \
--output=$RESULTS_FOLDER/csharp-code-scanning.sarif

# Security extended suite: Queries of lower severity and precision than the default queries
codeql database analyze codeqldb $CODEQL_SUITES_PATH/csharp-security-extended.qls \
--format=sarif-latest \
--output=$RESULTS_FOLDER/csharp-security-extended.sarif

# Security and quality suite: Queries of lower severity and precision than the default queries
codeql database analyze codeqldb $CODEQL_SUITES_PATH/csharp-security-and-quality.qls \
--format=sarif-latest \
--output=$RESULTS_FOLDER/csharp-security-and-quality.sarif 

Cada uno de estos comandos generará un archivo en formato SARIF con los resultados de las consultas. El proceso puede tardar un tiempo, dependiendo de la potencia de tu equipo.

Visualizar el resultado de las consultas

Para poder visualizar de una forma sencilla el resultado de cada uno de los archivos he utilizado la extensión Sarif Viewer. Sin embargo, para que esta sepa interpretar correctamente los archivos hay que modificar el valor de la propiedad $schema de https://json.schemastore.org/sarif-2.1.0.json a http://json.schemastore.org/sarif-2.1.0-rtm.1 a día de hoy. Para ello he utilizado jq para reemplazar el valor de manera sencilla:

# If you want to see the result with Sarif Viewer you have to change the schema to http://json.schemastore.org/sarif-2.1.0-rtm.1
cat $RESULTS_FOLDER/csharp-code-scanning.sarif | jq '.["$schema"] = "http://json.schemastore.org/sarif-2.1.0-rtm.1"' > $RESULTS_FOLDER/csharp-code-scanning-fixed-schema.sarif
cat $RESULTS_FOLDER/csharp-security-extended.sarif | jq '.["$schema"] = "http://json.schemastore.org/sarif-2.1.0-rtm.1"' > $RESULTS_FOLDER/csharp-security-extended-fixed-schema.sarif
cat $RESULTS_FOLDER/csharp-security-and-quality.sarif | jq '.["$schema"] = "http://json.schemastore.org/sarif-2.1.0-rtm.1"' > $RESULTS_FOLDER/csharp-security-and-quality-fixed-schema.sarif

Una vez hecho este cambio, e instalada la extensión en tu Visual Studio Code, si abres por ejemplo el último de los archivos, csharp-security-and-quality-fixed-schema.sarif, que será el que posiblemente más información tenga, verás un resultado parecido a este:

Resultados de CodeQL con Sarif Viewer

y si haces clic en cualquiera de las lineas te llevará al código y te mostrará los puntos conflictivos.

¡Saludos!