
Codificatore/decodificatore Thrift di facile lettura.
Readable Thrift rende semplici da gestire i messaggi binari del protocollo Thrift convertendoli da e verso un formato leggibile. Questo rende l'analisi manuale e la manomissione dei messaggi Thrift in formato binario semplici quanto lavorare con protocolli in chiaro come HTTP.
La libreria è implementata in Java, consentendo l'integrazione con estensioni per i più comuni strumenti di test di applicazioni web che girano sulla JVM, come Burp e ZAP. Tutto ciò che serve per mettere in funzione uno strumento di analisi o manomissione è estrarre i byte appropriati e passarli al codec.
La libreria readablethrift è un pacchetto Maven basato su Gradle che può essere
installato e incluso come dipendenza in altri progetti. Espone quattro semplici
metodi per codificare e decodificare, in forma binaria grezza o codificata in Base64.
Nota: Attualmente è supportato solo il formato binario standard del protocollo. Il compact binary e il JSON (diverso dal JSON leggibile prodotto dal codec) non sono ancora supportati.
ThriftCodec::decode crea un'istanza descrittiva di org.json.JSONObject
direttamente da un buffer di byte grezzi che contiene un messaggio Thrift binario.ThriftCodec::decodeB64String decodifica una stringa Base64
e poi chiama decode su di essa.ThriftCodec::encode converte un'istanza descrittiva di org.json.JSONObject in un
buffer di byte grezzi contenente il messaggio Thrift binario equivalente.ThriftCodec::b64encodeJson converte un oggetto JSON
in formato Thrift binario e codifica il risultato in Base64.La classe ThriftCodec è progettata per essere estensibile, in modo da poter gestire
modifiche o estensioni al formato binario del protocollo Thrift, come ad esempio
intestazioni binarie aggiuntive o incapsulamenti.
Per usare l'interfaccia a riga di comando interattiva inclusa nella libreria,
usa il task Gradle predefinito per creare un JAR e poi eseguilo con
java -jar:
$ ./gradlew
BUILD SUCCESSFUL in 1s
2 actionable tasks: 2 executed
$ java -jar build/libs/readablethrift-1.0.0-all.jar
Enter Base64 encoded message or JSON object (or q to quit):
Per mostrare come apparirà il JSON leggibile, prendiamo un esempio di blob binario codificato in Base64 estratto da un po' di traffico applicativo:
$ base64 -D | hexdump
gAEAAQAAAAVsb2dpbgAAAAAMAAALAAAAAAAIY29vbHVzZXILAAEAAAALcGFzc3dvcmQxMjMAAA==
00000000: 8001 0001 0000 0005 6c6f 6769 6e00 0000 ........login...
00000010: 000c 0000 0b00 0000 0000 0863 6f6f 6c75 ...........coolu
00000020: 7365 720b 0001 0000 000b 7061 7373 776f ser.......passwo
00000030: 7264 3132 3300 00 rd123..
Le stringhe "login", nome utente e password suggeriscono che si tratta di una richiesta di autenticazione. Se si volesse manomettere questo messaggio al volo, bisognerebbe consultare i dettagli interni del parser del formato binario del protocollo Thrift, capire la struttura del messaggio con un editor esadecimale e poi aggiornare manualmente ogni campo. Nel caso delle stringhe nome utente e password, sarebbe necessario aggiornare anche i valori di lunghezza con prefisso insieme alle stringhe stesse. Questo sarebbe un processo noioso, soggetto a errori e dispendioso in termini di tempo. Readable Thrift rende questo processo più semplice; ecco lo stesso messaggio quando gli viene passato:
Enter Base64 encoded message or JSON object (or q to quit): gAEAAQAAAAVsb2dpbgAAAAAMAAALAAAAAAAIY29vbHVzZXILAAEAAAALcGFzc3dvcmQxMjMAAA==
{"message": {
"name": "login",
"type": "call",
"fields": [{
"id": 0,
"type": "struct",
"value": [
{
"id": 0,
"type": "string",
"value": "cooluser"
},
{
"id": 1,
"type": "string",
"value": "password123"
}
]
}],
"seqid": 0
}}
Ora possiamo facilmente verificare che il messaggio descrive una chiamata al metodo "login", con una struct
contenente due valori stringa come argomento. Aggiornare i valori delle stringhe è semplice come
modificare i campi JSON value e ripassare il nuovo testo JSON al codec.
Tutti i prefissi di lunghezza e gli altri dettagli del formato binario verranno gestiti automaticamente.
È anche possibile aggiungere nuovi campi per testare possibili parametri opzionali.
Magari c'è un flag booleano admin o debug? O una lista di ID di permessi?
Descrivi un nuovo campo con un id, un type e un value, e poi aggiungilo
all'array fields:
Enter Base64 encoded message or JSON object (or q to quit): {"message": {
"name": "login",
"type": "call",
"fields": [{
"id": 0,
"type": "struct",
"value": [
{
"id": 0,
"type": "string",
"value": "differentuser"
},
{
"id": 1,
"type": "string",
"value": "differentpassword!"
}
]
},
{"id": 1, "type": "bool", "value": true},
{"id": 2, "type": "list", "value":
{
"elemType": "i32",
"list": [1, 2, 3]
}
},
{"id": 3, "type": "map", "value":
{
"keyType": "string",
"valueType": "string",
"map": {
"dog": "bark",
"cat": "meow"
}
}
}],
"seqid": 0
}}
gAEAAQAAAAVsb2dpbgAAAAAMAAALAAAAAAANZGlmZmVyZW50dXNlcgsAAQAAABJkaWZmZXJlbnRwYXNzd29yZCEAAgABAQ8AAggAAAADAAAAAQAAAAIAAAADDQADCwsAAAACAAAAA2NhdAAAAARtZW93AAAAA2RvZwAAAARiYXJrAA==
Di seguito è riportato il messaggio aggiornato riconvertito nel protocollo binario Thrift:
$ base64 -D | hexdump
gAEAAQAAAAVsb2dpbgAAAAAMAAALAAAAAAANZGlmZmVyZW50dXNlcgsAAQAAABJkaWZmZXJlbnRwYXNzd29yZCEAAgABAQ8AAggAAAADAAAAAQAAAAIAAAADDQADCwsAAAACAAAAA2NhdAAAAARtZW93AAAAA2RvZwAAAARiYXJrAA==
00000000: 8001 0001 0000 0005 6c6f 6769 6e00 0000 ........login...
00000010: 000c 0000 0b00 0000 0000 0d64 6966 6665 ...........diffe
00000020: 7265 6e74 7573 6572 0b00 0100 0000 1264 rentuser.......d
00000030: 6966 6665 7265 6e74 7061 7373 776f 7264 ifferentpassword
00000040: 2100 0200 0101 0f00 0208 0000 0003 0000 !...............
00000050: 0001 0000 0002 0000 0003 0d00 030b 0b00 ................
00000060: 0000 0200 0000 0363 6174 0000 0004 6d65 .......cat....me
00000070: 6f77 0000 0003 646f 6700 0000 0462 6172 ow....dog....bar
00000080: 6b00