Skip to content

Commit 957d3a5

Browse files
committed
network2john.lua: Portability fix and Radius improvements
Add a try/catch for DHCPv4 parsing. We were apparently using option field names that were added to Wireshark/tshark experimentally, and later renamed. Ubuntu 24.04 (Wireshark v4.2) had the old names, Ubuntu 25.04 (Wireshark v4.4) has the new names. We now try the newer version's field names first, then fallback to the older version's. For Radius and CHAP, adds source and destination ip addresses in uid and gid fields respectively, and hostname to GECOS if found.
1 parent beb2b6a commit 957d3a5

File tree

1 file changed

+122
-10
lines changed

1 file changed

+122
-10
lines changed

run/network2john.lua

Lines changed: 122 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
-- #!/usr/bin/env lua -> shebang line seems to be breaking tshark :-(
22

3-
-- Usage: tshark -q -Xlua_script:network2john.lua -r selected.pcap
3+
-- Usage: tshark -q -X lua_script:network2john.lua -r selected.pcap
44
--
55
-- Wireshark in Fedora 25 doesn't have Lua enabled. Use Fedora 27 / Ubuntu or
66
-- something else which has Wireshark with Lua support or compile Wireshark
@@ -9,13 +9,46 @@
99
-- tshark -r selected.pcap -T pdml > data.pdml # use this for development!
1010

1111

12+
-- Helper function
13+
local function get_hostname()
14+
local v
15+
16+
-- RADIUS / EAP sources
17+
v = f_nas_id and f_nas_id()
18+
if v then return tostring(v.value or v) end
19+
20+
v = f_calling and f_calling()
21+
if v then return tostring(v.value or v) end
22+
23+
v = f_eap_id and f_eap_id()
24+
if v then return tostring(v.value or v) end
25+
26+
v = f_vsa and f_vsa()
27+
if v then return tostring(v.value or v) end
28+
29+
-- Resolved IP hostnames (requires tshark -N dNns)
30+
v = f_src_host4 and f_src_host4()
31+
if v then return tostring(v.value or v) end
32+
33+
v = f_dst_host4 and f_dst_host4()
34+
if v then return tostring(v.value or v) end
35+
36+
v = f_src_host6 and f_src_host6()
37+
if v then return tostring(v.value or v) end
38+
39+
v = f_dst_host6 and f_dst_host6()
40+
if v then return tostring(v.value or v) end
41+
42+
return ""
43+
end
44+
1245
-- Extract RADIUS CHAP hashes from .pcap files.
1346
-- https://tools.ietf.org/html/rfc2865 -> The CHAP challenge value is found in
1447
-- the CHAP-Challenge Attribute (60) if present in the packet, otherwise in the
1548
-- Request Authenticator field. NOTE: We don't handle the former case yet.
1649

1750
if not Listener then
18-
print("Usage: tshark -q -Xlua_script:network2john.lua -r target.pcap")
51+
print("Usage: tshark -q -X lua_script:network2john.lua -r target.pcap")
1952
os.exit(0)
2053
end
2154
tap_radius = Listener.new(nil, "radius")
@@ -27,9 +60,27 @@ local f_authenticator = Field.new("radius.authenticator")
2760
local f_username = Field.new("radius.User_Name")
2861
local f_ident = Field.new("radius.CHAP_Ident")
2962
local f_hash = Field.new("radius.CHAP_String")
63+
local f_src4 = Field.new("ip.src")
64+
local f_dst4 = Field.new("ip.dst")
65+
local f_src6 = Field.new("ipv6.src")
66+
local f_dst6 = Field.new("ipv6.dst")
67+
local f_nas_id = Field.new("radius.NAS_Identifier")
68+
local f_calling = Field.new("radius.Calling_Station_Id")
69+
local f_eap_id = Field.new("eap.identity")
70+
local f_vsa = Field.new("radius.Vendor_Specific")
71+
local f_src_host4 = Field.new("ip.src_host")
72+
local f_dst_host4 = Field.new("ip.dst_host")
73+
local f_src_host6 = Field.new("ipv6.src_host")
74+
local f_dst_host6 = Field.new("ipv6.dst_host")
3075

3176
function tap_radius.packet(pinfo,tvb,tapdata)
3277
local code = f_code()
78+
local src = (f_src4 and f_src4()) or (f_src6 and f_src6())
79+
local dst = (f_dst4 and f_dst4()) or (f_dst6 and f_dst6())
80+
81+
if not src or not dst then
82+
return
83+
end
3384

3485
if code.value == 1 then -- Access-Request
3586
local canary = f_ident()
@@ -38,7 +89,10 @@ function tap_radius.packet(pinfo,tvb,tapdata)
3889
local id = tostring(f_ident().value):lower()
3990
local response = tostring(f_hash().value):lower()
4091
local username = tostring(f_username().value)
41-
local hash = string.format("%s:$chap$%s*%s*%s", username, id, challenge, response)
92+
local ips = tostring(src.value)
93+
local ipd = tostring(dst.value)
94+
local hostname = get_hostname()
95+
local hash = string.format("%s:$chap$%s*%s*%s:%s:%s:%s", username, id, challenge, response, ips, ipd)
4296
print(hash)
4397
canary = nil
4498
end
@@ -55,6 +109,18 @@ local f_code = Field.new("radius.code")
55109
local f_authenticator = Field.new("radius.authenticator")
56110
local f_username = Field.new("radius.User_Name")
57111
local f_upe = Field.new("radius.User_Password_encrypted")
112+
local f_src4 = Field.new("ip.src")
113+
local f_dst4 = Field.new("ip.dst")
114+
local f_src6 = Field.new("ipv6.src")
115+
local f_dst6 = Field.new("ipv6.dst")
116+
local f_nas_id = Field.new("radius.NAS_Identifier")
117+
local f_calling = Field.new("radius.Calling_Station_Id")
118+
local f_eap_id = Field.new("eap.identity")
119+
local f_vsa = Field.new("radius.Vendor_Specific")
120+
local f_src_host4 = Field.new("ip.src_host")
121+
local f_dst_host4 = Field.new("ip.dst_host")
122+
local f_src_host6 = Field.new("ipv6.src_host")
123+
local f_dst_host6 = Field.new("ipv6.dst_host")
58124

59125
-- put the passed-in args into a table
60126
local args = {...}
@@ -65,9 +131,15 @@ end
65131

66132
function tap_radius.packet(pinfo,tvb,tapdata)
67133
local code = f_code()
134+
local src = (f_src4 and f_src4()) or (f_src6 and f_src6())
135+
local dst = (f_dst4 and f_dst4()) or (f_dst6 and f_dst6())
136+
137+
if not src or not dst then
138+
return
139+
end
68140

69141
if count < 2 then
70-
print("Usage: tshark -q -Xlua_script:network2john.lua -X lua_script1:<secret-or-password-value-here> -X lua_script1:0 -r target.pcap\n")
142+
print("Usage: tshark -q -X lua_script:network2john.lua -X lua_script1:<secret-or-password-value-here> -X lua_script1:0 -r target.pcap\n")
71143
print("Note: -X lua_script1:<secret-or-password-value-here> -> this is used as either the user password or the shared secrert\n")
72144
print("Note: Use -X lua_script1:0 to attack RADIUS shared secret\n")
73145
print("Note: Use -X lua_script1:1 to attack user password")
@@ -83,7 +155,10 @@ function tap_radius.packet(pinfo,tvb,tapdata)
83155
local username = tostring(f_username().value)
84156
local secret = args[1]
85157
local mode = args[2]
86-
local hash = string.format("%s:$radius$1*%s*%s*%s*%s", username, mode, secret, challenge, upe)
158+
local ips = tostring(src.value):gsub(":", ".")
159+
local ipd = tostring(dst.value):gsub(":", ".")
160+
local hostname = get_hostname()
161+
local hash = string.format("%s:$radius$1*%s*%s*%s*%s:%s:%s:%s", username, mode, secret, challenge, upe, ips, ipd, hostname)
87162
print(hash)
88163
canary = nil
89164
end
@@ -103,6 +178,11 @@ local f_etype = Field.new("eap.type")
103178
local f_identity = Field.new("eap.identity")
104179
local f_challenge = Field.new("eap.md5.value")
105180
local f_response = Field.new("eap.md5.value")
181+
local f_src4 = Field.new("ip.src")
182+
local f_dst4 = Field.new("ip.dst")
183+
local f_src6 = Field.new("ipv6.src")
184+
local f_dst6 = Field.new("ipv6.dst")
185+
local f_eap_id = Field.new("eap.identity")
106186

107187
local username = nil
108188
local challenge = nil
@@ -112,6 +192,14 @@ local id = nil
112192
function tap_eap.packet(pinfo,tvb,tapdata)
113193
local code = f_code()
114194
local etype = f_etype()
195+
local src = (f_src4 and f_src4()) or (f_src6 and f_src6())
196+
local dst = (f_dst4 and f_dst4()) or (f_dst6 and f_dst6())
197+
local hostname = get_hostname()
198+
199+
if not src or not dst then
200+
return
201+
end
202+
115203

116204
if code.value == 2 and etype.value == 1 then -- Response, Identity (extract username)
117205
username = tostring(f_identity())
@@ -127,7 +215,10 @@ function tap_eap.packet(pinfo,tvb,tapdata)
127215
end
128216

129217
if username and challenge and response then
130-
local hash = string.format("%s:$chap$%s*%s*%s", username, id, challenge, response)
218+
local ips = tostring(src.value)
219+
local ipd = tostring(dst.value)
220+
local hostname = get_hostname()
221+
local hash = string.format("%s:$chap$%s*%s*%s:%s:%s:%s", username, id, challenge, response, ips, ipd, hostname)
131222
print(hash)
132223
username = nil
133224
challenge = nil
@@ -258,9 +349,15 @@ end
258349

259350
tap_dhcpv4 = Listener.new(nil, "bootp")
260351

261-
local f_algorithm = Field.new("bootp.option.dhcp_authentication.alg_delay")
262-
local f_hash= Field.new("bootp.option.dhcp_authentication.hmac_md5_hash")
263-
local f_dhcpv4 = Field.new("bootp")
352+
local f_algorithm = Field.new("dhcp.option.dhcp_authentication.alg_delay", true)
353+
if f_algorithm then
354+
local f_hash= Field.new("dhcp.option.dhcp_authentication.hmac_md5_hash")
355+
local f_dhcpv4 = Field.new("dhcp")
356+
else
357+
local f_algorithm = Field.new("bootp.option.dhcp_authentication.alg_delay")
358+
local f_hash= Field.new("bootp.option.dhcp_authentication.hmac_md5_hash")
359+
local f_dhcpv4 = Field.new("bootp")
360+
end
264361

265362
function tap_dhcpv4.packet(pinfo,tvb,tapdata)
266363
local canary = f_hash()
@@ -296,6 +393,10 @@ tap_iscsi = Listener.new(nil, "iscsi")
296393

297394
local f_opcode = Field.new("iscsi.opcode")
298395
local f_kv = Field.new("iscsi.keyvalue")
396+
local f_src4 = Field.new("ip.src")
397+
local f_dst4 = Field.new("ip.dst")
398+
local f_src6 = Field.new("ipv6.src")
399+
local f_dst6 = Field.new("ipv6.dst")
299400

300401
local username = nil
301402
local challenge = nil
@@ -304,6 +405,15 @@ local id = nil
304405

305406
function tap_iscsi.packet(pinfo,tvb,tapdata)
306407
local opcode = f_opcode()
408+
local ips = tostring(src.value):gsub(":", ".")
409+
local ipd = tostring(dst.value):gsub(":", ".")
410+
local src = (f_src4 and f_src4()) or (f_src6 and f_src6())
411+
local dst = (f_dst4 and f_dst4()) or (f_dst6 and f_dst6())
412+
413+
if not src or not dst then
414+
return
415+
end
416+
307417

308418
if opcode.value == 0x23 then -- extract CHAP_C, and CHAP_I
309419
items = {f_kv()}
@@ -332,7 +442,9 @@ function tap_iscsi.packet(pinfo,tvb,tapdata)
332442
end
333443

334444
if username and challenge and response then
335-
local hash = string.format("%s:$chap$%s*%s*%s", username, id, challenge, response)
445+
local ips = tostring(src.value)
446+
local ipd = tostring(dst.value)
447+
local hash = string.format("%s:$chap$%s*%s*%s:%s:%s", username, id, challenge, response, ips, ipd)
336448
print(hash)
337449
username = nil
338450
challenge = nil

0 commit comments

Comments
 (0)