Skip to content

Commit b499781

Browse files
committed
wip
1 parent 2683ab6 commit b499781

File tree

3 files changed

+101
-22
lines changed

3 files changed

+101
-22
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ analyzer-d4-passivessl fetch a redis feed of certificate and TLS sessions and ma
44
```bash
55
go get github.com/gomodule/redigo/redis
66
go get github.com/lib/pq
7+
sudo apt install postgresal-plpython3-10
78
```

main.go

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,21 @@ func main() {
100100
s := sessionRecord{}
101101
_ = json.Unmarshal([]byte(dat), &s)
102102

103-
if len(s.Certificates) > 0 {
103+
if isValid(&s){
104+
// Create ja3* records
105+
err = insertJA3(&s)
106+
if err != nil {
107+
log.Fatal(fmt.Sprintf("Could not insert JA3 into DB: %q", err))
108+
}
104109
// Insert Session
105110
ids, err := insertSession(&s)
106111
if err != nil {
107112
log.Fatal(fmt.Sprintf("Insert Sessions into DB failed: %q", err))
108113
}
114+
err = insertFuzzyHash(&s, ids)
115+
if err != nil {
116+
log.Fatal(fmt.Sprintf("Insert Fuzzy Hash into DB failed: %q", err))
117+
}
109118
// Attempt to roughly build a chain of trust
110119
session := buildChain(&s)
111120

@@ -119,17 +128,23 @@ func main() {
119128
if err != nil {
120129
log.Fatal(fmt.Sprintf("Could not link Certs and Session into DB: %q", err))
121130
}
122-
123-
// Create ja3* records
124-
err = insertJA3(session)
125-
if err != nil {
126-
log.Fatal(fmt.Sprintf("Could not insert JA3 into DB: %q", err))
127-
}
128131
}
129132
}
130133
}
131134
}
132135

136+
func isValid(s * sessionRecord) bool {
137+
// Relationships
138+
if len(s.Certificates) < 1 || s.JA3Digest == "" || s.JA3 == "" {
139+
return false
140+
}
141+
// Basic informations
142+
if s.ClientPort == "" || s.ServerPort == "" || s.ServerIP == "" || s.ClientIP == "" {
143+
return false
144+
}
145+
return true
146+
}
147+
133148
func insertJA3(s *sessionRecord) error {
134149
q := `INSERT INTO "ja3" (hash, raw, type) VALUES ($1, $2, $3) ON CONFLICT DO NOTHING`
135150
_, err := db.Exec(q, s.JA3Digest, s.JA3, "ja3")
@@ -144,6 +159,15 @@ func insertJA3(s *sessionRecord) error {
144159
return nil
145160
}
146161

162+
func insertFuzzyHash(s *sessionRecord, ids int64) error {
163+
q := `INSERT INTO "fuzzy_hash" (type, value, "id_sessionRecord") VALUES ($1, $2, $3) ON CONFLICT DO NOTHING`
164+
_, err := db.Exec(q, "TLSH", s.TLSH, ids)
165+
if err != nil {
166+
return err
167+
}
168+
return nil
169+
}
170+
147171
// insertPublicKeys insert each public key of each certificate of a session
148172
func insertPublicKey(c x509.Certificate) (string, error) {
149173
pub, err := x509.ParsePKIXPublicKey(c.RawSubjectPublicKeyInfo)
@@ -321,9 +345,9 @@ func insertCertificates(s *sessionRecord) ([]string, error) {
321345
}
322346

323347
func insertSession(s *sessionRecord) (int64, error) {
324-
q := `INSERT INTO "sessionRecord" (dst_ip, src_ip, dst_port, src_port, timestamp) VALUES ($1, $2, $3, $4, $5) RETURNING id`
348+
q := `INSERT INTO "sessionRecord" (dst_ip, src_ip, dst_port, src_port, timestamp, hash_ja3) VALUES ($1, $2, $3, $4, $5, $6) RETURNING id`
325349
var id int64
326-
err := db.QueryRow(q, s.ServerIP, s.ClientIP, s.ServerPort, s.ClientPort, s.Timestamp).Scan(&id)
350+
err := db.QueryRow(q, s.ServerIP, s.ClientIP, s.ServerPort, s.ClientPort, s.Timestamp, s.JA3Digest).Scan(&id)
327351
if err != nil {
328352
return 0, err
329353
}
@@ -339,7 +363,7 @@ func initRedis() {
339363
}
340364

341365
func initDB() {
342-
connStr := "user=postgres password=postgres dbname=new_database"
366+
connStr := "user=postgres password=postgres dbname=passive_ssl"
343367
err := errors.New("")
344368
db, err = sql.Open("postgres", connStr)
345369
if err != nil {

passivessl.sql

Lines changed: 66 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@
44
-- Project Site: pgmodeler.com.br
55
-- Model Author: ---
66

7+
SET check_function_bodies = false;
8+
-- ddl-end --
9+
710

811
-- Database creation must be done outside an multicommand file.
912
-- These commands were put in this file only for convenience.
10-
-- -- object: new_database | type: DATABASE --
11-
-- -- DROP DATABASE IF EXISTS new_database;
12-
-- CREATE DATABASE new_database
13+
-- -- object: passive_ssl | type: DATABASE --
14+
-- -- DROP DATABASE IF EXISTS passive_ssl;
15+
-- CREATE DATABASE passive_ssl
1316
-- ;
1417
-- -- ddl-end --
1518
--
@@ -64,7 +67,7 @@ CREATE TABLE public.certificate(
6467
is_valid_chain bool NOT NULL DEFAULT false,
6568
"notBefore" time,
6669
"notAfter" time,
67-
"isSS" bool NOT NULL DEFAULT false,
70+
"is_SS" bool NOT NULL DEFAULT false,
6871
CONSTRAINT certificate_pk PRIMARY KEY (hash)
6972

7073
);
@@ -104,7 +107,7 @@ CREATE TABLE public."sessionRecord"(
104107
src_ip inet NOT NULL,
105108
dst_port int4 NOT NULL,
106109
src_port int4 NOT NULL,
107-
hash_ja3 bytea,
110+
hash_ja3 bytea NOT NULL,
108111
"timestamp" time(0) with time zone,
109112
CONSTRAINT "sessionRecord_pk" PRIMARY KEY (id)
110113

@@ -130,7 +133,7 @@ ALTER TABLE public.ja3 OWNER TO postgres;
130133
-- ALTER TABLE public."sessionRecord" DROP CONSTRAINT IF EXISTS ja3_fk CASCADE;
131134
ALTER TABLE public."sessionRecord" ADD CONSTRAINT ja3_fk FOREIGN KEY (hash_ja3)
132135
REFERENCES public.ja3 (hash) MATCH FULL
133-
ON DELETE SET NULL ON UPDATE CASCADE;
136+
ON DELETE RESTRICT ON UPDATE CASCADE;
134137
-- ddl-end --
135138

136139
-- object: public."many_sessionRecord_has_many_certificate" | type: TABLE --
@@ -162,8 +165,8 @@ ON DELETE RESTRICT ON UPDATE CASCADE;
162165
CREATE TABLE public.fuzzy_hash(
163166
id bigserial NOT NULL,
164167
type text NOT NULL,
165-
value public.hstore NOT NULL,
166-
hash_ja3 bytea,
168+
value text NOT NULL,
169+
"id_sessionRecord" bigint,
167170
CONSTRAINT fuzzy_hash_pk PRIMARY KEY (id)
168171

169172
);
@@ -258,11 +261,62 @@ CREATE INDEX path_index ON public.certificate
258261
WITH (BUFFERING = ON);
259262
-- ddl-end --
260263

261-
-- object: ja3_fk | type: CONSTRAINT --
262-
-- ALTER TABLE public.fuzzy_hash DROP CONSTRAINT IF EXISTS ja3_fk CASCADE;
263-
ALTER TABLE public.fuzzy_hash ADD CONSTRAINT ja3_fk FOREIGN KEY (hash_ja3)
264-
REFERENCES public.ja3 (hash) MATCH FULL
264+
-- object: "sessionRecord_fk" | type: CONSTRAINT --
265+
-- ALTER TABLE public.fuzzy_hash DROP CONSTRAINT IF EXISTS "sessionRecord_fk" CASCADE;
266+
ALTER TABLE public.fuzzy_hash ADD CONSTRAINT "sessionRecord_fk" FOREIGN KEY ("id_sessionRecord")
267+
REFERENCES public."sessionRecord" (id) MATCH FULL
265268
ON DELETE SET NULL ON UPDATE CASCADE;
266269
-- ddl-end --
267270

271+
-- object: plpython3u | type: LANGUAGE --
272+
-- DROP LANGUAGE IF EXISTS plpython3u CASCADE;
273+
CREATE LANGUAGE plpython3u;
274+
-- ddl-end --
275+
ALTER LANGUAGE plpython3u OWNER TO postgres;
276+
-- ddl-end --
277+
278+
-- object: public.tlshc | type: FUNCTION --
279+
-- DROP FUNCTION IF EXISTS public.tlshc(text,text) CASCADE;
280+
CREATE FUNCTION public.tlshc ( a text, b text)
281+
RETURNS int4
282+
LANGUAGE plpython3u
283+
VOLATILE
284+
CALLED ON NULL INPUT
285+
SECURITY INVOKER
286+
COST 1
287+
AS $$
288+
import tlsh
289+
return tlsh.diff(a, b)
290+
$$;
291+
-- ddl-end --
292+
ALTER FUNCTION public.tlshc(text,text) OWNER TO postgres;
293+
-- ddl-end --
294+
295+
-- object: public.tlsht | type: FUNCTION --
296+
-- DROP FUNCTION IF EXISTS public.tlsht(IN text,IN text,IN int4,int4) CASCADE;
297+
CREATE FUNCTION public.tlsht (IN filter text, IN hash text, IN threshold int4, maxrows int4)
298+
RETURNS SETOF public.fuzzy_hash
299+
LANGUAGE plpython3u
300+
IMMUTABLE LEAKPROOF
301+
RETURNS NULL ON NULL INPUT
302+
SECURITY INVOKER
303+
COST 1
304+
ROWS 1000
305+
AS $$
306+
import tlsh
307+
param = ["TLSH"]
308+
#param[0] = filter
309+
#plan = plpy.prepare("SELECT * FROM fuzzy_hash WHERE type <> $1", ["text"])
310+
#rv = plan.execute(param, maxrows)
311+
rv = plpy.execute("SELECT * FROM fuzzy_hash", 1000)
312+
r = []
313+
for x in rv:
314+
if tlsh.diff(x["value"], hash) < threshold:
315+
r.append(x)
316+
return r
317+
$$;
318+
-- ddl-end --
319+
ALTER FUNCTION public.tlsht(IN text,IN text,IN int4,int4) OWNER TO postgres;
320+
-- ddl-end --
321+
268322

0 commit comments

Comments
 (0)