Xây dựng không gian mật khẩu

Một phần của tài liệu Thám mã trên các hệ thống email (Trang 29)

2.2.1 Khái niệm không gian mật khẩu

Không gian mật khẩu được hiểu là một danh sách mật khẩu có thứ tự phù hợp với thói quen đặt mật khẩu của đối tượng quan tâm. Một cách thức đơn giản để xây dựng không gian mật khẩu là liệt kê các mật khẩu thường sử dụng. Tuy nhiên cách này bị hạn chế ở một số điểm: (1) số lượng mật khẩu hạn chế trong tập các mật khẩu thu thập được; (2) mật khẩu trong không gian thiếu đi sự cá nhân hóa cho các

28

đối tượng cụ thể; (3) thứ tự các mật khẩu trong không gian đôi khi không phản ánh chính xác các thói quen của đối tượng.

Cách tiếp cận phù hợp hơn trong việc xây dựng không gian mật khẩu là đặt ra một cấu trúc tổng quát cho các mật khẩu nằm trong không giam mật khẩu, sau đó việc sinh mật khẩu sẽ là việc kết hợp giữa cấu trúc này với các thông tin cá nhân của đối tượng.

Các nội dung tiếp theo sẽ trình bày một phương pháp đề xuất để biểu diễn thông tin cá nhân của đối tượng, cấu trúc mật khẩu và giải thuật để sinh mật khẩu trong không gian.

2.2.2 Từ điển

Đa số mật khẩu có cấu trúc thường chứa trong đó những xâu ký tự đại diện cho những thông tin cá nhân đặc trưng cho đối tượng quan tâm như: tên, ngày sinh, nơi sinh sống,… Các thông tin này có thể được thu thập qua những kênh thông tin đặc thù. Trong trường hợp không thể thu thập được chính xác các thông tin này, có thể giả định chúng nằm trong một tập hợp các xâu ký tự được xác định trước, được gọi là từ điển.

Danh sách mật khẩu có thể được sinh từ một cấu trúc mật khẩu có chứa thông tin quan tâm, kèm theo từ điển về thông tin đó.

Ví dụ: cho một từ điển về tên đối tượng NAME = {tung, minh, trung},

Các mật khẩu có chứa tên dưới dạng “u$NAMEv” sẽ bao gồm {utungv, uminhv, utrungv}.

Thứ tự các xâu ký tự trong từ điển có thể đại diện cho thứ tự ưu tiên của các mật khẩu được sinh ra tương ứng.

Khi xây dựng một công cụ sinh mật khẩu, chúng ta có thể định nghĩa trước một số từ điển có sẵn, áp dụng cho mọi đối tượng như:

1. Các mật khẩu thường gặp

2. Các tên riêng

3. Các vị trí địa lý

4. Ngày tháng năm sinh

29

Các từ điển này có thể được rút gọn bằng cách định nghĩa đè lên bằng một từ điển khác nhỏ hơn, đại diên cho các thông tin gắn liền với đối tượng đang xem xét. Ví dụ: từ điển tên riêng cho một đối tượng có thể là danh sách tên của những người liên quan tới đối tượng (vợ, chồng, bố, mẹ, con cái), thay vì một danh sách tất cả các tên riêng .

2.2.3 Cấu trúc mật khẩu

Cấu trúc mật khẩu được định nghĩa bằng một danh sách có thứ tự các mẫu mật khẩu; {P1, P2,… ,Pn} trong đó mỗi mẫu Pi là một xâu ký tự, trong đó mỗi ký tự có thể thuộc các nhóm sau:

1. Ký tự cuối: là ký tự thuộc bảng ký tự của mật khẩu (ví dụ ký tự ASCII)

2. Từ điển: siêu ký tự đại diện cho một từ điển sẵn có

3. Mẫu mật khẩu: siêu ký tự đại diện cho một mẫu mật khẩu khác được định nghĩa trước

Ví dụ với một mẫu: P = “abc$NAME%DATE” trong đó

1. “abc” là chuỗi ký tự cuối

2. $NAME: đại diện cho một từ điển tên, ví dụ NAME = {tung, minh, trung}

3. %DATE: đại diện cho một mẫu ngày tháng năm được định nghĩa trước có dạng DATE = “$DAY$MONTH$YEAR” trong đó

$DAY: đại diện cho một từ điển ngày DAY = {21,25}

$MONTH: đại diện cho một từ điển tháng MONTH = {03,08}2>> $YEAR: đại diện cho một từ điển năm YEAR = {13,14}

Với những thông tin như vậy, ta có thể hình dung mẫu P sẽ đại diện cho các chuỗi mật khẩu có thứ tự như sau: {abctung210313, abctung210314, abctung210813, abctung210814, abctung250313, abctung250314, abctung250813, abctung250814, abcminh210313, abcminh210314, abcminh210813, abcminh210814, abcminh250313, abcminh250314, abcminh250813, abcminh250814, abctrung210313, abctrung210314, (adsbygoogle = window.adsbygoogle || []).push({});

30

abctrung210813, abctrung210814, abctrung250313, abctrung250314, abctrung250813, abctrung250814}.

Trong thực tế để biểu diễn cấu trúc mật khẩu cô đọng và biểu đạt hơn, có th2>> để xem xét các cấu trúc loại trừ dạng P = S1 | S2 hoặc cấu trúc lặp P = S* giống như trong các biểu thức chính quy (regular expression). Tuy nhiên trong khuôn khổ của luận văn và xem xét tính chất của bài toán biểu diễn mật khẩu ta tạm thời chỉ quan tâm tới dạng cấu trúc mật khẩu nêu trên. Hơn nữa chúng ta cũng đặt một ràng buộc cho cấu trúc mật khẩu này là nó không chứa các cấu trúc đệ quy dạng P = S1PS2 (hoặc P1 = S1P2S2; P2 = S3P1S4).

Chuẩn hóa mẫu.

Việc cho phép các mẫu mật khẩu chứa những mẫu khác được định nghĩa trước giúp người sử dụng dễ dàng biểu diễn cấu trúc mật khẩu hơn với một tập mẫu định nghĩa trước. Tuy nhiên việc sử dụng cấu trúc lồng như vậy cũng khiến cho giải thuật sinh mật khẩu trở nên phức tạp. Chính vì vậy chúng ta xem xét một dạng chuẩn của mẫu mật khẩu là dạng chỉ chứa các siêu ký tự đại diện cho từ điển. Các nhóm ký tự khác sẽ được chuyển về dạng chuẩn (ký tự từ điển) này như sau:

1. Chuỗi liên tục tối đa các ký tự cuối w sẽ chuyển về thành một siêu ký tự từ điển mới D, với từ điển D = {w} được bổ sung thêm vào danh sách từ điển.

2. Siêu ký tự đại diện mẫu P = S, sẽ được chuyển về thành xâu S’ là dạng chuẩn của S.

2.3 Sinh không gian mật khẩu từ cấu trúc mật khẩu và từ điển

Trong phần này tôi đề xuất giải thuật sinh không gian mật khẩu từ cấu trúc mật khẩu và tập từ điển đã được định nghĩa trước genpws(D,PP,P)

Đầu vào cho giải thuật bao gồm:

1. Tập từ điển D = {D1,…,Dn}, với Di là một từ điển có dạng DNi = {wi

1,…,wi

ni) trong đó DNI là siêu ký hiệu đại diện cho từ điển Di và ni

31

2. Tập mẫu định nghĩa trước PP = {PP1,…,PPm} với mẫu PPi có dạng PPNi = Si, trong đó PPNi là siêu ký tự đại diện của mẫu, Si là xâu ký tự biểu diễn mẫu. Để đơn giản cho việc nhập dữ liệu và chuyển đổi cấu trúc, tôi đề xuất biển diễn một xâu mẫu theo định dạng như sau:

S = C1C2…Cn

Trong đó:

3. Cấu trúc mật khẩu là một danh sách có thứ tự P = {P1,…,Pk} các xâu mẫu với định dạng như mô tả bên trên.

Đầu ra cho giải thuật: là một danh sách có thứ tự mật khẩu phù hợp với các cấu trúc được định nghĩa trên đầu vào.

Thông thường danh sách mật khẩu này rất lớn, đôi khi không thể lưu trữ trong bộ nhớ của một máy tính. Hơn nữa, quá trình kiểm tra mật khẩu thường được thực hiện trên các hệ thống tính toán hiệu năng cao, phân tán. Do vậy, để thuận tiện cho việc phân chia công việc kiểm tra mật khẩu này, tôi đề xuất một hàm sinh mật khẩu khác có dạng genpws_partial(D,PP,P, from, count) trong đó D, PP, P là tập từ điển, tập mẫu định nghĩa trước và cấu trúc mật khẩu như giải thuật genpws. from và count là thứ tự bắt đầu của mật khẩu cần sinh và số lượng mật khẩu cần sinh.

Giải thuật được chia làm các pha sau:

Pha 1: Đọc dữ liệu đầu vào và phân tích chuyển đổi thành cấu trúc bên trong (parsing)

Pha 2: Chuẩn hóa cấu trúc mật khẩu Pha 3: Sinh mật khẩu theo thứ tự

2.3.1 Đọc dữ liệu đầu vào và phân tích chuyển đổi thành cấu trúc bên trong

Nhiệm vụ chính của pha này là chuyển đổi các dữ liệu đầu vào, thường biểu diễn dưới dạng xâu ký tự và tệp dữ liệu thành các cấu trúc bên trong, trong đó bao gồm:

32

1. Tập từ điển D: là danh sách các từ điển {D1,…, Dn} với n là số lượng từ điển. Mỗi từ điển Di chứa một danh sách từ {wi

1,wi

ni} với ni là số lượng từ trong từ điển Di. (adsbygoogle = window.adsbygoogle || []).push({});

2. Tập mẫu định nghĩa trước PP: với PPN là danh sách tên mẫu {PPN1,PPNm}, m là số lượng mẫu được định nghĩa trước và S là danh sách mẫu {S1,…Sm}. Mỗi mẫu S là một danh sách ký hiệu có định dạng:

type: nhận một trong các giá trị {final, dic, pat} tương ứng với xâu ký tự cuối, ký hiệu đại diện từ điển; ký hiệu đại diện mẫu định nghĩa trước.

value: xâu ký tự cuối trong trường hợp type = final; tên/thứ tự từ điển trong trường hợp type = dic; tên/thứ tự mẫu định nghĩa trước trong trường hợp type = pat.

3. Cấu trúc mật khẩu P: {P1,…,Pk} trong đó Pi là mẫu mật khẩu theo khuôn dạng mô tả trên.

2.3.2 Chuẩn hóa cấu trúc mật khẩu

Giải thuật chuẩn hóa cấu trúc mật khẩu stdpat(P) được định nghĩa một cách đệ quy như sau:

stdpat(#{w}S) = ${DN}stdpat(S) với DN là ký hiệu đại diện cho một từ điển mới có môt từ DN = {w} được bổ sung vào tập từ điển D

std2>> pat(${N}S) = ${N}stdpat(S)

stdpat(%{N}S)=stdpat(PP)stdpat(S) với PP là chuỗi biểu diễn mẫu định nghĩa trước tương ứng với tên N.

Sau quá trình chuẩn hóa, cấu trúc mật khẩu sẽ có dạng một danh sách mẫu chuẩn hóa {P’1,P’k} trong đó P’i là mẫu chuẩn hóa có bao gồm một dánh sách ký hiệu đại diện từ điển có dạng D1…Dki

Ngoài ra, để phục vụ cho việc sinh mật khẩu theo đúng thứ tự trong một khoảng cho trước, tôi định nghĩa hàm numpws(S) với S = D1…Dl để tính số lương mật khẩu mật khẩu có thể sinh ra từ chuỗi S:

33

numpws(D1…Dl) = size(D1) x … x size(Dl) trong đó size(D) là hàm lấy kích thước của từ điển D.

Mỗi mẫu Pi trong danh sách mẫu {P1,…,Pk} thuộc cấu trúc mật khẩu được bổ sung thêm thông tin:

start: thứ tự mật khẩu đầu tiên của mẫu count: số lượng mật khẩu của mẫu Trong đó:

start(Pi) = count(P1) + … + count(Pi-1) count(Pi) = numpws(Pi)

2.3.3 Sinh mật khẩu theo thứ tự

Giải thuật sinh mật khẩu theo thứ tự được định nghĩa như sau: Function genpws_partial(D,PP,P,start, count)

Begin

Đọc dữ liệu Chuẩn hóa mẫu tìm mẫu i đầu tiên i:= 1;

while (start(Pi) + count(Pi) < start) i := i + 1;

s := start – start(Pi);

c := min(count, count(Pi));

repeat

result := result @ genpws_pat_partial(Pi, s, c); count := count – c;

i := i +1; s := 0;

c := min(count, count(Pi)); until c = 0;

34 End

Trong đó genpws_pat_partial(P,start, count) là giải thuật sinh c mật khẩu từ vị trí s của mẫu P. Giả sử P là chuỗi D1…DL, việc sinh mật khẩu trong mẫu sẽ bắt đầu từ các từ trong từ điển Di tại vị trí posi như sau:

Với từ điển DL: posl =start mod size(Dl) (adsbygoogle = window.adsbygoogle || []).push({});

Với từ điển Di: posi = (start div (size(Di+1)x..x size(Dl))) mod size(Di) Giải thuật genpws_pat_partial(P,start, count) được mô tả như sau:

Function genpws_pat_partial(D1…Dl, start, count) Begin

// Tính vị trí bắt đầu sinh của các từ trong từng từ điển posl = start mod size(Dl);

i = l - 1; While i >= 1 Begin

start = start div size(Di+1); posi = start mod size(Di); i = i -1 ; End; // Sinh từ điển C = 0; While c < count Begin

Result = result @ D1[pos1]…Dl[posl]; j = l;

While j >= 1 Begin

35 posj = posj + 1; If posj >= size(Dj) Begin posj = 0; j = j – 1; End Else break; End End return result; End 2.4 Cài đặt thử nghiệm 2.4.1 Dữ liệu đầu vào

Dữ liệu đầu vào được đặt trong thư mục data, định dạng json, được tổ chức như sau:

pattern.json: lưu trữ thông tin về các cấu trúc mật khẩu và các mẫu định nghĩa sẵn. dictpasswd.json: các mật khẩu dạng từ điển hay được sử dụng.

metadata.json : lưu trữ thông tin về những thông tin tài khoản đã được thu thập và lưu trữ, bao gồm một số định danh và địa chỉ file lưu thông tin, gồm các trường sau:

accID: số định danh tài khoản khi lưu trữ

datafile: đường dẫn tương đối đến file lưu trữ thông tin tính từ thư mục data. account.json : lưu trữ thông tin đã được thu thập cho từng tài khoản, bao gồm các trường sau (có thể lặp lại, khi đó module đọc dữ liệu sẽ tự động thêm vào từ điển tương ứng.)

FIRST: tên

MIDDLE: tên đệm LAST: tên họ DD: ngày

36 MM: tháng

YYYY: năm sinh

MOBILE: số điện thoại di động WORK: số điện thoại cố định

2.4.2 Cấu trúc của chương trình

Chương trình được cài đặt bằng ngôn ngữ python, được chia thành các module sau: 1. Module đọc dữ liệu: data_load.py

Module này chứa đối tượng DataLoader. chức năng đọc dữ liệu từ các tập tin được lưu trữ trong thư mục data để phục vụ sinh không gian mật khẩu.

2. Module sinh mật khẩu: passwd_gen.py

Module này chứa đối tượng PasswordSpace, chức năng bao gồm (1) cài đặt các phương thức sinh mật khẩu đã nêu trong chương 3 với các thông tin được lưu trữ và đọc vào bộ nhớ qua module đọc dữ liệu.

Do yêu cầu quá trình được thực hiện trên hệ thống phân tán, ta sẽ thực hiện hai module đọc dữ liệu và module sinh mật khẩu trên node master, sau đó dữ liệu sẽ được chuyển cho các agent chạy trên các node worker để thử mật khẩu.

3. Module kiểm thử mật khẩu: agent.py

Module này chứa đối tượng Agent. Đối tượng Agent sẽ nhận dữ liệu từ Master node, sau đó kiểm thử từng mật khẩu trong không gian mật khẩu bằng cách thử kết nối đến địa chỉ email với các thông số cho sẵn và một mật khẩu trong không gian mật khẩu. Nếu mailserver thông báo kết nối thành công thì ta kết luận mật khẩu thử là mật khẩu đúng.

2.4.3 Thử nghiệm

2.4.3.1 Dữ liệu thử nghiệm

Chúng tôi thực hiện thử nghiệm sinh không gian mật khẩu với các tham số sau:

Tập từ điển D: (adsbygoogle = window.adsbygoogle || []).push({});

('FIRST', ['la', 'dung']), ('LAST', ['nguyen', 'hoang'])

37 ('MIDDLE', ['thi', 'van'])

('DD', ['2', '02']) ('MM', ['10', '07'])

('YYYY', ['1982', '82', '92']) ('MOBILE', ['0922222']), ('WORK', ['0434444'])

Tập mẫu định nghĩa trước PP: 'NAME_0': '${FIRST}${LAST}' 'NAME_1': '${FIRST}${MIDDLE}${LAST}' 'DATE_1': '${MM}${DD}${YYYY}' 'DATE_0': '${DD}${MM}${YYYY}' Tập cấu trúc mật khẩu P: ('P1', '%{NAME_0}%{DATE_0}') ('P2', '#{1234}#{___}%{DATE_0}') ('P3', '%{DATE_0}%{NAME_0}') ('P4', '%{NAME_1}%{DATE_0}%{DATE_1}') 2.4.3.2 Kết quả thử nghiệm

1. Sinh không gian mật khẩu

Chương trình sinh ra không gian mật khẩu tương ứng với những thông tin đã nhập vào. Kích thước không gian mật khẩu đã sinh là 1280 mật khẩu. Kết quả minh họa:

38

Hình 9: Kết quả sinh không gian mật khẩu

2. Sinh mật khẩu theo thứ tự

Chương trình sinh ra một nhóm các mật khẩu theo thứ tự từ mật khẩu thứ 20, sinh 1000 mật khẩu. Kết quả minh họa:

39

Chương 3 – XÂY DỰNG HỆ THỐNG THÁM MẬT KHẨU EMAIL

Để đơn rút ngắn thời gian thử mật khẩu đã được sinh ra ở chương 2, tôi lựa chọn giải pháp xây dựng hệ thống thám mật khẩu email trên môi trường phân tán vì đây là cách hợp lý đem lại hiệu quả.

3.1 Kiến trúc hệ thống

Hình 10: Sơ đồ kiến trúc hệ thống thám mật khẩu email

Với yêu cầu hệ thống được thực hiện trên môi trường phân tán, hệ thống được thiết kế thử nghiệm như sau:

Hệ thống thử nghiệm gồm 3 node: 1 Master node, 2 Worker node. Master node và Worker node liên lạc với nhau và phân chia công việc thông qua RabbitMQ. Rabbit MQ là một trong những hệ thống truyền thông điệp AMPQ rất phổ biến, sử dụng với python qua module Pika. RabbitMQ được xây dựng trên nền tảng ngôn ngữ Erlang, đảm bảo khả năng song song hóa tốt và chịu tải cao. Tôi

40

nhận thấy RabbitMQ đáp ứng được nhu cầu giao tiếp giữa các node trong bài toán này.

Master node thực hiện đọc dữ liệu, sinh không gian mật khẩu, chuyển thông tin cho Worker node. Trong phạm vi của luận văn là chứng minh tính hiệu quả của việc sinh mật khẩu dựa trên thói quen của người dùng, để đơn giản hóa quá trình thực hiện, tại một thời điểm hệ thống chỉ làm việc với 1 account duy nhất. Có nghĩa là Master node chỉ sinh dữ liệu cho 1 account và các Worker node chỉ thử mật khẩu cho 1 account.

Worker node nhận dữ liệu từ Master node, sau đó kiểm thử các mật khẩu trong không gian mật khẩu bằng cách thử tạo kết nối đến tài khoản tương ứng trên mailserver.

Nếu phát hiện mật khẩu đúng, Worker node thông báo cho Master node ngừng quá trình sinh mật khẩu thử, đồng thời ngừng quá trình thử mật khẩu trên Worker node còn lại.

3.2 Xây dựng agent kiểm tra mật khẩu cho email:

Agent được xây dựng bằng ngôn ngữ Python, sử dụng các module tương ứng để thực hiện giao tiếp qua giao thức AMQP.

Một phần của tài liệu Thám mã trên các hệ thống email (Trang 29)