Algunos scripts para Dionaea

Tanto si somos una empresa o un centro dedicado a la seguridad informática, o si simplemente queremos investigar malware, sabemos de la importancia de las HoneyNets como fuente para la detección y obtención de nuevas muestras de malware. También, si queremos descubrir hacia dónde se están dirigiendo los ataques y anticiparse a cuando ocurra en nuestra red en producción, nos puede venir bien montar una honey.

En varios artículos se ha hablado de Dionaea y en esta ocasión voy a mostrar algunos scripts para mostrar los últimos binarios que no eran detectados por la mayoría de antivirus.

Para considerar que se trate de una muestra nueva, tomamos como referencia VirusTotal porque ofrece un servicio con múltiples motores de antivirus guardándonos el resultado en el momento de enviar nuestra muestra. Si la muestra no la detectan más de tres motores, diremos que es un especimen nuevo o una mutación desconocida y no detectada.

Teniendo en cuenta lo anterior, he preparado una consulta SQL que ejecutaremos en la base de datos sqlite3 que muestra aquellos binarios que fueron detectados como malware por menos de cuatro motores de antivirus:

select 
    count(distinct(virustotal))
from (
SELECT
    vt.virustotal_timestamp as timestamp,vs.virustotal,count(vs.virustotal) as 
undetected,virustotal_md5_hash,virustotal_permalink
FROM
    virustotalscans vs
inner join
    virustotals vt
on
    vs.virustotal = vt.virustotal and virustotalscan_result is null
group by
    vs.virustotal)
where
    undetected >38 and strftime('%m-%Y', datetime(timestamp, 'unixepoch', 
'localtime')) == strftime('%m-%Y','now', '-1 month') 
;

Una manera de saber si está aumentando la actividad es contar los ataques recibidos y ver cuántos contenían esas muestras que suponemos nuevas. Adjunto la consulta para realizar esto:

select 
    count(distinct(virustotal))
from (
SELECT
    vt.virustotal_timestamp as timestamp,vs.virustotal,count(vs.virustotal) as 
undetected,virustotal_md5_hash,virustotal_permalink
FROM
    virustotalscans vs
inner join
    virustotals vt
on
    vs.virustotal = vt.virustotal and virustotalscan_result is null
group by
    vs.virustotal)
where
    undetected >38 and strftime('%m-%Y', datetime(timestamp, 'unixepoch', 
'localtime')) == strftime('%m-%Y','now', '-1 month') 
;

Se han detectado XXXX muestras de las cuales XX son únicas.

Otra información que se puede extraer de Dionaea es el origen de los ataques para identificar aquellos países “calientes”: aquellos que más nos visitan. De esta forma podemos ser conscientes de quién está llamando a nuestra puerta. Con el siguiente script se calcula el número de atacantes que han «visitado» nuestro honeypot y el de países de origen. También adjunto el código para crear un mapa con los países que más atacan.

#!/usr/bin/python2.6

import sqlite3
import GeoIP
import getopt
import sys

gi = GeoIP.new(GeoIP.GEOIP_MEMORY_CACHE)
countries = ''
attackers = '0'

def executeQueryTemp(sql):
    conn_tmp = sqlite3.connect('/opt/dionaea/var/dionaea/logsql.sqlite')
    ct = conn_tmp.cursor()
    ct.execute(sql)
    row_tmp = ct.fetchone()
    attackers = str(row_tmp[0])
    ct.close()
    return attackers

def executeQuery(sql):
    conn = sqlite3.connect('/opt/dionaea/var/dionaea/logsql.sqlite')
    c = conn.cursor()
    c.execute(sql)
    f_html = open('geomap.html', 'w')

    f_html.write('<div><script src="http://www.google.com/jsapi" 
type="text/javascript"></script>')
    f_html.write("""<script type="text/javascript">google.load('visualization', 
'1', {packages: [\'geomap\']});</script>""")
    f_html.write("""<script type="text/javascript">
    function drawVisualization() {
    // Create and populate the data table.
    var data = new google.visualization.DataTable();
    data.addColumn('string', '', 'Country');
    data.addColumn('number', 'Hosts');
""")

    country_list = {}
    for row in c:
        count = row[0]
        ip_addr = row[1]
        country = gi.country_code_by_addr(str(ip_addr))
        if country in country_list:
            country_list[str(country)] = country_list[str(country)] + count
        else:
            country_list[str(country)] = count
    # print str(country_list)
    countries = str(len(country_list))

    f_html.write('data.addRows(' + str(countries) + ');')
    num_item = 0
    for cc, cc_count in country_list.iteritems():
        f_html.write('data.setValue(' + str(num_item) + ', 0, \'' + str(cc) + '\');')
        f_html.write('data.setValue(' + str(num_item) + ', 1, ' + str(cc_count) + ');')
        num_item = num_item + 1
    

    f_html.write("""
    var geomap = new google.visualization.GeoMap(document.getElementById('geomap'));
    geomap.draw(data, null);
    }
    google.setOnLoadCallback(drawVisualization);
    </script>
    </div>
    <div id="geomap" style="height: 350px; width: 600px;">
    </div>
""")
    f_html.close()
    return countries

def createSQL():
    queryDesc = "List of attackers by country"
    querySQL = """
SELECT 
    count(remote_host) as count, remote_host 
FROM 
    connections 
WHERE 
    strftime('%m-%Y', datetime(connection_timestamp, 'unixepoch', 'localtime')) == 
strftime('%m-%Y','now','-1 month') 
GROUP BY
    remote_host 
ORDER BY 
    count DESC
; """
    return querySQL

def createSQLTMP():
    queryTMP = """
SELECT 
    count(remote_host)
FROM 
    connections 
WHERE 
    strftime('%m-%Y', datetime(connection_timestamp, 'unixepoch', 'localtime')) == 
strftime('%m-%Y','now','-1 month') 
; """
    return queryTMP


def main():
    countries = ''
    attackers = '0'
    query_attack = createSQLTMP()
    attackers = str(executeQueryTemp(query_attack))
    query_country = createSQL()
    countries = str(executeQuery(query_country))

    print str(attackers)
    print str(countries)
    f_text = open('geomap.txt', 'w')
    texto = 'Se han detectado ' + str(attackers) + ' atacantes desde ' + 
str(countries) + ' paises\n'
    f_text.write(texto)
    f_text.close
    sys.exit()

if __name__ == "__main__":
    main()

Y aquí una imagen de muestra del mapa que genera:

mapa

Por último, algunas URLs capturadas durante el pasado mes que nos pueden venir bien para añadir en listas negras del firewall o proxy, podría extraerse con la siguiente consulta:

SELECT
    count(*), download_url
FROM
    downloads d
INNER JOIN
    connections c
ON 
    d.connection == c.connection and strftime('%m-%Y', datetime(connection_timestamp, 
'unixepoch', 'localtime')) == strftime('%m-%Y', 'now', '-1 month')
GROUP BY
    download_url
ORDER BY
    count(*) DESC
LIMIT 10
;

NOTA: Los scripts son un refrito de varias fuentes que han sido modificados o me he basado en ellos para modificarlos. Disculpad si no son muy limpios.

Espero que os sean de utilidad y podáis corregir o ampliar la información que se puede extraer de Dionaea y las comentéis para compartirlas entre todos.