
Analizador de bytecode de Java personalizable mediante reglas JSON.
Analizador de bytecode de Java personalizable mediante reglas JSON. Es una herramienta de línea de comandos que recibe una ruta que contiene uno o más archivos Jar o War, los analiza utilizando las reglas proporcionadas y genera informes HTML con los resultados.
usage: java -jar cba-cli.jar [OPTIONS] -a DIRECTORY_TO_ANALYZE
-a,--analyze <pathToAnalyze> Ruta del directorio para ejecutar el
análisis.
-c,--checks <checks...> Lista separada por espacios de comprobaciones personalizadas
que se ejecutarán en el análisis.
-f,--custom-file <customFile> Especifica un archivo en formato JSON para ejecutar
reglas personalizadas. Lea más en
https://github.com/fergarrui/custom-bytecode-analyzer.
-h,--help Imprime este mensaje.
-i,--items-report <maxItems> Número máximo de elementos por informe. Si el
número de problemas encontrados supera este
valor, el informe se dividirá en diferentes
archivos. Útil si se esperan demasiados
problemas en el informe. Valor por defecto: 50.
-o,--output <outputDir> Directorio para guardar el informe. Advertencia:
si ya hay informes guardados en este directorio, serán sobrescritos.
El valor por defecto es "report".
-v,--verbose-debug Aumenta la verbosidad al modo depuración.
-vv,--verbose-trace Aumenta la verbosidad al modo traza - lo hace más lento, úselo solo cuando sea necesario.
El archivo de reglas se puede especificar usando el argumento -f,--custom-file. El archivo está en formato JSON y tiene la siguiente estructura:
finalTambién puedes consultar net.nandgr.cba.custom.model.Rules.java para ver la estructura en código Java.
Ya existen varias reglas en el directorio examples. De todas formas, a continuación se enumeran ejemplos para cada regla.
Si necesitamos encontrar clases con deserialización personalizada, podemos hacerlo con bastante facilidad. Una clase define deserialización personalizada implementando private void readObject(ObjectInputStream in). Por lo tanto, solo necesitamos encontrar todas las clases donde esté definido ese método. Bastaría con definir una regla como:
{
"rules": [{
"name": "Custom deserialization",
"methods": [{
"name": "readObject",
"visibility": "private",
"parameters" : [{
"type" : "java.io.ObjectInputStream"
}]
}]
}]
}
Reportará métodos con visibilidad private, nombre readObject y un parámetro de tipo java.io.ObjectOutputStream. Los parámetros son un array; si se especifica más de uno, todos deben coincidir para ser reportados. Como solo tenemos una regla, se creará un informe llamado: custom-deserialization-0.html.
En este caso, se debe definir una regla con dos métodos. El mismo que en el ejemplo anterior para deserialización, y uno nuevo para coincidir con private void writeObject(ObjectOutputStream out). Como se muestra en la estructura JSON anterior, la propiedad rules.rule.methods es un array de métodos, por lo que se puede escribir una regla como esta:
{
"rules": [{
"name": "Custom serialization and deserialization",
"methods": [{
"name": "readObject",
"visibility": "private",
"parameters" : [{
"type" : "java.io.ObjectInputStream"
}]
},{
"name": "writeObject",
"report": "false",
"visibility": "private",
"parameters" : [{
"type" : "java.io.ObjectOutputStream"
}]
}]
}]
}
La propiedad report se estableció en false para evitar reportar dos veces la misma regla. Estamos usando el segundo método solo como condición, pero reportar solo los métodos readObject debería ser suficiente para el propósito de esta regla.
Si una propiedad no está definida, siempre coincidirá como verdadero. Por ejemplo, esta regla devolvería todas las definiciones de métodos:
{
"rules": [{
"name": "Method definitions",
"methods": [{
}]
}]
}
También se pueden encontrar invocaciones de métodos. El JSON en este caso sería:
{
"rules": [{
"name": "String equals",
"invocations": [{
"owner": "java.lang.String",
"method": {
"name": "equals"
}
}]
}]
}
La propiedad owner especifica la clase que contiene el método.
Otro ejemplo de invocación de método un poco más útil que el anterior:
{
"rules": [{
"name": "Method invocation by reflection",
"invocations": [{
"owner": "java.lang.reflect.Method",
"method": {
"name": "invoke"
}
}]
}]
}
Es lo mismo que cualquier invocación de método, pero el nombre del método en este caso debe ser <init>.
{
"rules": [{
"name" : "String instantiation",
"invocations" : [{
"owner" : "java.lang.String",
"method" : {
"name" : "<init>"
}
}]
}]
}
Esta regla encontrará ocurrencias de:
[...]
String s = new String("foo");
[...]