Tải bản đầy đủ (.docx) (42 trang)

XÂY DỰNG PLUGIN CHO NESSUS

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (482.33 KB, 42 trang )

Lời mở đầu
Trong quá trình bảo mật hệ thống mạng cho một công ty hay tổ chức việc sử
dụng các công cụ mạnh để kiểm tra hay phát hiện các lỗi bảo mật nhằm nâng cao
tính an toàn của hệ thống và toàn mạng là rất quan trọng. Trong đó Nessus và
GFI LanGuard là hai trong số các chương trình rà soát lỗ hổng bảo mật mạng
hàng đầu hiện nay. Nhưng GFI LanGuard là một phần mềm thương mại, trong
khi đó Nessus lại là một phần mềm miễn phí hoàn toàn cho người dùng cá nhân,
với cơ sở dữ liệu về các lỗ hổng có thể được rất phong phú cho cả hệ thống chạy
Window hay Linux và được cập nhật thường xuyên. Theo thống kê của trang
sectools.org, Nessus là phần mềm quét lỗ hổng bảo mật phổ biến nhất trong các
năm 2000, 2003 và 2006. Hãng Tenable ước tính rằng nó được sử dụng rộng rãi
bởi hơn 75000 tổ chức trên toàn thế giới. Việc dò tìm các lỗ hổng bảo mật đóng
một vai trò rất quan trọng với các quản trị viên hệ thống, các chuyên gia bảo mật
v.v… nhằm tìm ra các biện pháp tăng cường bảo mật cho hệ thống, và cả những
kẻ muốn tấn công thực sự. Tuy nhiên việc tìm thêm các lỗ hổng mới tương đối
khó khăn, một phần do các lỗ hổng cũ sau khi công bố một thời gian, các nhà sản
xuất sẽ tìm cách “vá” lại những lổ hổng đó, một phần do những người tìm ra
những lỗ hổng mới đó không muốn công khai rộng rãi.
Việc dò quét các lỗ hổng của Nessus được thực hiện dựa trên hai thành phần
chính là Nessus Engine và Nessus Plugin. Nessus Engine đóng vai trò như một
trình biên dịch để thực hiện các câu lệnh của Nessus Plugin. Công cụ để xây
dựng các plugin đó chính là ngôn ngữ kịch bản NASL (Nessus Attrack Scripting
Language).
Nội dung của báo cáo được chia làm 2 phần:
Chương 1: Tìm hiểu về các thành phần, cách cài đặt và sử dụng Nessus.
Chương 2: Tìm hiểu ngôn ngữ NASL, tiến tới tự xây dựng plugin cho
Nessus.
1


Do thời gian tìm hiểu ngắn và kiến thức còn hạn chế, nên một số nội dung như


Nessus Engine, nhóm sẽ không đi sâu vào nghiên cứu.

CHƯƠNG 1. TỔNG QUAN VỀ NESSUS
1.1 LỊCH SỬ HÌNH THÀNH VÀ PHÁT TRIỂN CỦA NESSUS
Ban đầu, Nessus là một dựa án nguồn mở “Nessus Project”, được đề xuất bởi
Renaud Deraison vào năm 1998, mã nguồn của các thành phần đều được công
bố công khai (các phiên bản Nessus 2 trở về trước). Từ tháng 10 năm 2005,
Tenable Network Security, một công ty do Renaud Deraison đồng sáng lập, đã
phát hành Nessus 3 dưới dạng mã nguồn đóng. Tháng 8 năm 2008, hãng
Tenable đưa ra phiên bản cho phép người dùng cá nhân được sử dụng đầy đủ
các plugin. Tháng 4 năm 2009, hãng phát hành Nessus 4.0.0, đến tháng 2 năm
2012 phát hành Nessus 5.0.
Nessus có thể chạy trên nhiều nền tảng hệ điều hành khác nhau, bao gồm cả
UNIX, Linux, Mac OS X, Windows. Hiện tại phiên bản Nessus 5.0 chạy trên
giao diện web, do đó có thể dễ dàng truy cập, sử dụng trên mọi hệ điều hành.
1.2 CÁC THÀNH PHẦN CỦA NESSUS
Nessus có các thành phần chính:
- Nessus Engine: nhận, thực thi và trả lời lại các yêu cầu quét của người
dùng. Việc quét các lỗ hổng được thực hiện theo các chỉ dẫn của các
plugin (một tập các câu lệnh script của ngôn ngữ kịch bản NASL).
- Nessus Plugin: hệ thống file của ngôn ngữ kịch bản NASL, gồm các file
định nghĩa .inc và file kịch bản .nasl.
- Nessus Server (nessusd): thực hiện nhận các yêu cầu quét của người
dùng, sau đó phân tích, tổng hợp, trả lại kết quả cho Nessus client.
- Nessus Client: hiển thị kết quả quét lại cho người dùng thông qua trình
duyệt web. - Nessus Knowledge Base: “Cơ sở dữ liệu đã biết” của Nessus
2


cho phép các plugin sau tận dụng dữ liệu kết quả của Plugin trước đó. Điều

này giúp Nessus dễ dàng mở rộng và tăng tốc độ thực thi.
1.2.1 Kiến trúc của Nessus với mô hình Client-Server
Ban đầu, Server sẽ tổng hợp tất cả các lỗi bảo mật hiện nay. Khi một máy tính
Client yều cầu được kiểm tra các lỗi có tồn tại trên máy tính của mình hay
không, Tìm hiểu xây dựng Plugin cho Nessus sử dụng NASL Trang 9 đầu tiên
chúng phải được kiểm tra xem có kết nối tới server hay không, sau khi đã kiểm
tra kết nối chúng sẽ được quét tùy thuộc vào các mức độ yêu cầu khi quét.
Mô hình này sẽ dựa vào kết quả sau khi máy Client yêu cầu kiểm tra, và dựa
vào những lỗi đã được xác định có thể đưa ra những những hướng giải quyết
một cách nhanh nhất.

Hình 1.1 Mô hình kiến trúc Nessus dạng Client-Server
1.2.2 Mô hình Nessus Knowledge Base
Mô hình Nessus Knowledge Base là gì?
- Mô hình này khá đơn giản nó thu thập danh sách các lỗi bảo mật khác đang
được thử nghiệm. Nó cho phép bổ sung, hoặc chia sẻ những thông tin về hệ
thống đang được kiểm tra.
Phương thức hoạt động của Nessus Knowledge Base:
Giả sử chúng ta thực hiện quét kiểm tra lỗi bảo mật trên trang Server
kma.com, quá trình kiểm tra hoàn tất và không thấy một lỗi bảo mật nào có
3


trên đó. Lúc này Nessus Knowledge Base được tạo ra cho máy chủ này
(/usr/local/var/nessus/users/mh/ kbs/kma.com) cho thấy khoảng 1800 lỗi,
Người ta phải nhớ rằng Nessus Knowledge Base cũng chỉ có khoảng 1725 lỗi
đã được trusted. Và những thông số đó được sử dụng cho những nghiên cứu
sau này để đảm bảo rằng liên tục cập nhật những lỗi bảo mật mới nhất.
1.2.3 Mô hình Nessus Plugin
Nessus Plugin là gì?

- Là một chương trình dùng để kiểm tra tính bảo mật của một trang web từ xa,
máy tính cục bộ hay những thiết bị bảo vệ thông tin...
Hoạt động của Nessus Plugin:
Mô hình hoạt động của Nessus Plugin khá đơn giản, ta có thể dùng gia diện
hoặc dùng command line để quét. Bằng việc sử dụng Plugin đã có sẵn sau khi
cài để kiểm tra tính bảo mật.

Hình 1.2 Mô hình hoạt động của Nessus Plugin.

4


CHƯƠNG 2. TÌM HIỂU VỀ NGÔN NGỮ NASL
2.1 TỔNG QUAN VỀ NGÔN NGỮ NASL
2.1.1 Lịch sử ngôn ngữ NASL
Vào năm 1998, phiên bản đầu tiên của Nessus được phát hành với khả năng
kiểm tra khoảng 50 lỗi bảo mật, nó còn được biết như các plugin. Những
plugin này được cài đặt như các thư viện dùng chung, được viết bằng ngôn
ngữ lập trình C, với phần mở rộng .nes. Mục đích của phương pháp này nhằm
phân tách riêng module đảm nhận việc quét (engine scanning) với các module
hướng dẫn, chỉ thị quét. Điều này giúp cho Nessus có kiến trúc modul và dễ
dàng mở rộng. Vào thời điểm đó, việc dùng các thư viện dùng chung để viết
các plugin có rất nhiều ý nghĩa, giúp nhanh chóng tạo các plugin dựa trên
những chương trình C sẵn có.
Tác giả đã viết một script nhỏ gọi là "plugin-factory" giúp biên dịch các
plugin viết bằng C sang các thư viện dùng chung (.nes). Ý tưởng là khi người
dùng muốn update các plugin, họ sẽ download các plugin viết bằng C mới nhất
trên web, sau đó biên dịch và cài đặt chúng. Quá trình này mang lại nhiều nguy
cơ không an toàn về bảo mật, vì thế ý tưởng không được phát triển.
Sau khi tìm kiếm các ngôn ngữ script hiện tại, Perl có lẽ là ngôn ngữ tốt nhất

để viết các plugin cho Nessus, tuy nhiên vào thời điểm đó Perl có một số hạn
chế:




Chiếm dung lượng bộ nhớ lớn.
Không hỗ trợ tốt quá trình gửi/nhận các gói tin thô (raw packet).
Không có cách nào đáng tin cậy để kiểm tra dưới các máy ảo cơ bản.

Điểm cuối cùng là quan trọng nhất. Từ một góc nhìn mức cao, mỗi một quá
trình quét đều giống nhau: nó kết nối đến một số cổng trên máy khách từ xa,
thực hiện một số tác vụ, sau đó suy ra máy khách từ xa có dễ bị tổn thương với
một số luật đã cho trước hay không. Cách tốt nhất là điều chỉnh tất cả các tác
vụ quét, để không phải điều chỉnh chúng một cách riêng rẽ, chuyển cho máy
5


ảo thực hiện. Ví dụ, khi ta thêm khả năng hỗ trợ SSL vào trong Nessus, ta
không phải sửa từng plugin, ta chỉ cần chỉnh sửa hàm socket thực hiện kết nối.
Một mối quan tâm khác tới việc dùng Perl làm ngôn ngữ để viết các Plugin là
các hàm bổ sung chỉ tồn tại qua các plugin bên ngoài. Những module này lại
yêu cầu những gói và hàm thư viện hệ thống riêng. Tác giả đã quyết định viết
một ngôn ngữ Script mới gọi là NASL dùng riêng cho Nessus (Nessus Attrack
Scripting Language), với các mục tiêu hướng đến:










Mỗi script được chứa trong một file.
Dễ cài đặt với người dùng cuối.
Dễ tìm hiểu cho các nhà phân phối, phát triển.
Chiếm ít dung lượng bộ nhớ.
Thiết kế riêng cho quét lỗ hổng an ninh mạng.
Độ bảo mật cao.
Dễ chỉnh sửa và mở rộng.
Hỗ trợ đa ngôn ngữ.

Kết quả là ngôn ngữ NASL1 được ra đời, trong đó có một số điểm chưa được
hoàn thiện: nó rất chậm và quá lỏng lẻo về các lỗi cú pháp, nhưng tổng thể nó
đã làm tốt công việc của mình. Hơn 1000 lỗi kiểm tra bảo mật được viết bởi
NASL1. Ban đầu tốc độ không phải là điều đáng quan tâm nhất, bởi thời gian
để thiết lập một phiên kết nối TCP luôn mất nhiều hơn là thời gian trình thông
dịch NASL xử lý, phân tích cú pháp mã plugin.
Tuy nhiên, khi số lượng plugin tăng lên, người dùng bắt đầu sử dụng Nessus
quét nhiều host hơn, NASL1 thực sự trở nên chậm cho những tác vụ này. Mã
nguồn gốc khó mở rộng, và quyết định đơn giản là viết lại NASL.
Vào năm 2001, thư viện libnasl được viết lại bởi Michel Arboi để mở rộng
ngôn ngữ, và sửa chữa những khuyết điểm của NASL1. Thư viện viết lại này,
được gọi với tên NASL2, trở thành thành phần lớn nhất trong Nessus 2.0. Kể
từ phiên bản 3.0, ngôn ngữ NASL2 được tích hợp vào trong engine. Những ưu
điểm của NASL2:


Script được gói gọn: mỗi script NASL chứa cả code để kiểm tra các luật

và các chỉ dẫn cho plugin của chính nó. Các file script có phần mở rộng
đơn giản là .nasl.

6















Dễ cài đặt với người dùng cuối: NASL có dạng tự đóng gói, có thể cấu
hình sử dụng với thư viện OpenSSL. Người dùng có thể dùng trình biên
dịch GCC và GNI Bison (bison) dễ dàng xây dựng và cài đặt trình thông
dịch NASL.
Dễ dàng tìm hiểu với các nhà phân phối, phát triển: NASL trông rất giống
C, với một vài điểm của Perl. Nếu chúng ta đã từng lập trình với những
ngôn ngữ trên, thì việc học NASL khá dễ. Điểm khác biệt lớn nhất giữa
NASL và C là nó không có phần con trỏ và quản lý bộ nhớ.
Chiếm ít dung lượng bộ nhớ: Thông thường, Nessus chỉ yêu cầu vài trăm
KB bộ nhớ, nó có thể load được nhiều plugin đồng thời.
Thiết kế dành riêng cho kiểm tra bảo mật mạng: NASL được thiết kế để

thiết lập kết nối, gửi nhận dữ liệu, xử lý kết quả. Nó có số lượng lớn các
hàm thư viện cài đặt cho các giao thức mức cao. Ví dụ như các giao thức
SMB, NFS, RPC, SMTP, HTTP, v.v… Tất cả những thư viện này đều
được viết bằng NASL.
Độ bảo mật cao: NASL không thể truy cập vào hệ thống file cục bộ, thực
hiện các câu lệnh hệ thống, hoặc kết nối tới một máy khách bên thứ 3 (nó
chỉ có thể kết nối tới host đang thực hiện kiểm tra). Việc không có con trỏ
và quản lý bộ nhớ, giúp nó tránh được các lỗi như tràn bộ đệm. Điều này
làm cho NASL trở thành một ngôn ngữ rất an toàn và giảm thời gian thiết
kế những plugin mới.
Dễ chỉnh sửa và mở rộng: Phiên bản của trình thông dịch NASL có ngôn
ngữ rất trong sáng, giúp việc thêm các toán tử và hàm mới rất dễ, có khả
năng tương thích ngược với các thư viện cũ.
Hỗ trợ đa ngôn ngữ: NASL hỗ trợ đa ngôn ngữ, nhưng giới hạn ở các
ngôn ngữ có thể mã hóa với bảng ký tự ASCII. Có nhiều ngôn ngữ như
Nhật Bản, không thể biểu diễn bằng bảng mã ASCII mở rộng.

2.1.2 Điểm khác biệt giữa NASL1 và NASL2
• NASL2 sử dụng trình phân tích cú pháp Bison, nó chặt chẽ hơn và có
thể xử lý những kiểu diễn đạt phức tạp.
• NASL2 có nhiều hàm xây dựng sẵn (mặc dù hầu hết những hàm này đều
có thể chuyển tương thích với NASL1).
• NASL2 có nhiều toán tử được tích hợp.
• NASL2 nhanh hơn (khoản tầm 16 lần).
• Hầu hết script NASL2 không thể chạy với NASL1.
7





Một vài script NASL1 không thể chạy với NASL2 (nhưng việc sửa
tương đối dễ dàng). NASL2 có hàm chức năng xử lý mảng.

2.1.3 NASL2 ngôn ngữ thông dịch, tựa C
“Thông dịch” là đặc điểm chung các ngôn ngữ script. Nhưng NASL2 có một
thuận lợi lớn cho những người muốn tìm hiểu, đó là cú pháp của nó gần giống
ngôn ngữ lập trình C (từ cách khai báo biến, các toán tử, vòng lặp, v.v…). Nó
không có các thành phần phức tạp như trong C (biến con trỏ, quản lý vòng lặp),
khiến cho ngữ pháp của NASL2 trở nên đơn giản, dễ hiểu hơn.
Ví dụ nội dung của một file script test-yahoo.nasl:

8


Ta có thể chạy thử một script NASL2 bằng câu lệnh đơn giản từ command-line:
nasl –t 192.168.1.100 test-yahoo.nasl
2.2 CẤU TRÚC NGÔN NGỮ NASL2
2.2.1 Sơ bộ về quy tắc viết chương trình
• Chú thích bắt đầu tính từ dấu “#” ở đầu dòng, khi đó nó sẽ được trình
thông dịch bỏ qua.
• Có thể thêm các khoảng trắng tùy ý giữa 2 từ, toán tử. Khoảng trắng ở
đây có thể là dấu cách, tab.
• Chuỗi được phân tích bởi bộ phân tích từ vựng, sau đó trả lại kết quả
phân tích ngữ pháp.
- Bộ phân tích sẽ trả lại thông báo quá dài, nếu nó gặp kiểu diễn tả
như a+++++b, khi đó nó sẽ hiểu thành a++ ++ + b hoặc (a++ ++) +
b giống như trong ANSI C. Khi đó ta nên viết a++ + ++b
- Không thể thêm khoảng trắng vào giữa chuỗi đa ký tự. Ví dụ x =
a + +; sẽ không được chấp nhận, nên viết x = a ++;
2.2.2 Cú pháp

Cú pháp các câu lệnh của NASL:











[decl_list]instr_decl
instr_decl instr_decl_list
[instr_decl]instr
func_decl;
[func_decl]function identifier ( arg_decl ) block
[arg_decl]/*nothing*/
arg_decl_1
[arg_decl_1]identifier
identifier , arg_decl_1
[block]{ instr_list }
{}
[instr_list]instr
instr instr_list
[instr]s_instr ;
block
if_block
loop
[s_instr]aff

9






















post_pre_incr
rep
func_call
ret
inc
loc
glob

break
Continue
/*nothing*/
[ret]return expr
return
[if_block]if ( expr ) instr
if ( expr ) instr else instr
[loop]for_loop
while_loop
repeat_loop
foreach_loop
[for_loop]for ( aff_func ; expr ; aff_func ) instr
[while_loop]while ( expr ) instr
[repeat_loop]repeat instr until expr ;
[foreach_loop]foreach identifier ( array ) instr
[array]expr
[aff_func]aff
post_pre_incr
func_call
/*nothing */
[rep]func_call x expr
[string]STRING1
STRING2
[inc]include ( string )
[func_call]identifier ( arg_list )
[arg_list]arg_list_1
/*nothing*/
[arg_list_1]arg
arg , arg_list_1
[arg]expr

identifier : expr
[aff]lvalue = expr
lvalue += expr
lvalue -= expr
lvalue *= expr
lvalue /= expr
10
















lvalue %= expr
lvalue >>= expr
lvalue >>>= expr
lvalue <<= expr
[lvalue]identifier
array_elem
[identifier]IDENTIFIER

x
[array_elem]identifier
[ array_index ] [array_index]expr
[post_pre_incr]++ lvalue
- lvalue
lvalue ++
lvalue –
[expr]( expr )
logic_expr
arith_expr
bit_expr
post_pre_incr
compar
INTEGER
STRING2
STRING1
var
aff
cst_array
ipaddr
[logic_expr]expr and expr
! expr
expr or expr
[arith_expr]expr + expr
expr - expr
- expr
expr * expr
expr / expr
expr % expr
expr ** expr

[bit_expr]~ expr
expr & expr
expr ^ expr
expr | expr
expr >> expr
expr >>> expr
11


















expr << expr
[compar]expr >< expr
expr >!< expr
expr =~ string
expr !~ string

expr < expr
expr > expr
expr == expr
expr != expr
expr >= expr
expr <= expr
[var]identifier
num_arg
array_elem
func_call
[ipaddr]INTEGER . INTEGER . INTEGER . INTEGER
[num_arg]$INTEGER
$*
[cst_array][ l_array ]
[l_array]array_data
array_data , l_array
[array_data]atom
string => atom
[atom]integer
string [loc]local_var arg_decl
[glob]global_var arg_decl
[INTEGER] số nguyên - là một chuối số thập phân, hoặc bắt đầu bằng 0
cho hệ cơ số 8, hoặc 0x cho hệ cơ số 16.
[IDENTIFIER] định danh - là một chuỗi ký tự (chữ hoa, chữ thường, số,
dấu gạch dưới).
[STRING1] là một chuỗi ký tự giữa 2 dấu nháy đơn.
[STRING2] là một chuỗi ký tự giữa 2 dấu nháy kép.

2.2.3 Kiểu dữ liệu
NASL2 có các kiểu dữ liệu sau:

1. Kiểu số nguyên: mọi chuỗi bao gồm các chữ số, có thể có thêm dấu ở đầu
(+,-) để phân biệt số dương, số âm. NASL2 sử dụng cú pháp của C, hệ cơ số
8 bắt đầu bằng 0 và hệ 16 bắt đầu bằng 0x, ví dụ: 0x10 = 020 = 16
2. Kiểu chuỗi: có 2 dạng chuỗi, chuỗi không thể chuyển đổi và chuỗi có thể
chuyển đổi.
a) Chuỗi không thể chuyển đổi: là chuỗi được nhập vào giữa 2 dấu
nháy kép, ví dụ “abcde”, khi đó mọi ký tự của chuỗi đều được giữa
12


nguyên, dấu gạch chéo ngược vẫn giữ nguyên là dấu gạch chéo ngược.
Có thể chuyển sang chuỗi có thể chuyển đổi bằng các hàm xử lý chuỗi.
b) Chuỗi có thể chuyển đổi: là chuỗi được nhập vào giữa 2 dấu nháy
đơn, ví dụ „abcd\n‟, khi đó một vài ký tự của chuỗi sẽ được tự động
chuyển đổi.
3. Mảng: Hỗ trợ mảng một chiều, phần tử đầu tiên được đánh thứ tự là [0],
có thể dùng mảng để chứa dữ liệu kiểu số nguyên hoặc kiểu chuỗi.
4. Kiểu NULL: được gán cho các biến chưa khởi tạo giá trị.
5. Kiểu Boolean (kiểu lôgic): cho giá trị 0 – FALSE, 1- TRUE. Một vài giá
trị được tự động gán:





Giá trị không được định nghĩa hoặc Null là FALSE.
Số nguyên là TRUE nếu không rỗng, 0 là FALSE.
Chuỗi là TRUE nếu không rỗng và khác “0”.
Mảng luôn mang giá trị TRUE, cho dù có rỗng hay không.


2.2.4 Các toán tử
2.2.4.1 Các toán tử thông thường
• = dùng để gán giá trị. Ví dụ:
- x = 42; gán giá trị 42 vào biến x
- x = y; gán giá trị y cho x
• [] dùng đánh chỉ số mảng

- Một biến không thể vừa mang giá trị kiểu “nguyên tử” (như integer,
string, null) vừa mang giá trị kiểu mảng ở cùng một thời điểm. Nếu ta
chuyển đổi kiểu, giá trị trước đó sẽ bị mất.
- Có thể dùng để tách giá trị của một chuỗi. Ví dụ: s = “abcde” , khi
đó s[2] = “c”
- y[1]=42; tạo một mảng y, và gán giá trị 42 cho phần tử thứ hai của
mảng. Nếu y không phải là một mảng, đó là giá trị đàu tiên không
được định nghĩa.

13


2.2.4.2 Các phép toán số học
NASL2 không có quy định chặt chẽ về kiểu số nguyên. Trình thông dịch cài đặt
với kiểu “int” nguyên mẫu của C, là kiểu 32 bit trên hầu hết các hệ thống, hoặc
64 bit trên một số hệ thống khác. Không có cơ chế bảo vệ chống tràn số.








+ phép cộng 2 số nguyên.
- phép trừ 2 số nguyên.
* phép nhân 2 số nguyên.
/ phép chia lấy phần nguyên. Chú ý rằng NASL2 không có kiểu số thực.
Phép chia cho 0 sẽ trả lại 0 hoặc gây lỗi trình thông dịch.
% phép chia lấy phần dư.
** phép mũ, lũy thừa.

2.2.4.3 Các toán tử tựa C
NASL2 cài đặt một số phép toán giống C.





++ phép tăng giá trị biến lên 1 đơn vị, ví dụ: (++x) hoặc (x++) .Ý nghĩa
tương tự như trong C.
- giảm giá trị biến đi 1 đơn vị, ví dụ: (-x) hoặc (x-). Trong C phép toán
này là (--x) hoặc (x--).
+= -= *= %= có ý nghĩa tương tự như trong C.
<<= và >>= , có thêm >>>=

2.2.4.4 Toán tử xử lý chuỗi
• + phép cộng chuỗi, tuy nhiên nên sử dụng với các hàm xử lý chuỗi.
• - phép trừ chuỗi, nó loại bỏ các chuỗi đầu tiên mà nó tìm thấy trong chuỗi
cần trừ. Ví dụ: ‘abcd’ – ‘bc’ sẽ được ‘ad’.
• [] dùng tách ký tự từ chuỗi. Ví dụ s = ‘abcde’, khi đó s[2] = ‘c’.
• >< so sánh chuỗi trùng khớp, nếu một trong 2 chuỗi có chứa chuỗi còn lại
sẽ cho kết quả là TRUE, ngược lại là FALSE. „abcde‟ >< „bc‟ là TRUE,
„abcde‟ >< „xxxx‟ là FALSE

• >!< so sánh chuỗi không trùng khớp, nó sẽ trả về kết quả TRUE nếu
chuỗi này không chứa chuỗi kia, ngược lại là FALSE. „abcde‟ >!<
„xxxx‟ là TRUE, „abcde‟ >!< „bc‟ là FALSE.
• =~ (regex match) tương tự như khi gọi hàm trong ereg nhưng nhanh hơn,
bởi vì kiểu diễn đạt thông thường được biên dịch một lần khi script được
phân tích.
• s =~ “[ab]*x+” tương đương với ereg(string:s, pattern:"[ab]*x+", icase:1)
• !~ (regex don‟t match) tương tự như trên.
14


2.2.4.5 Toán tử so sánh
• == mang giá trị TRUE nếu 2 giá trị so sánh bằng nhau, ngược lại là
FALSE.
• != mang giá trị TRUE nếu 2 giá trị so sánh khác nhau, ngược lại là
FALSE.
• > so sánh lơn hơn.
• >= so sánh lớn hơn hoặc bằng.
• < so sánh nhỏ hơn.
• <= so sánh nhỏ hơn hoặc bằng.
2.2.4.6 Toán tử lôgic
• ! phép “not” lôgic. Ví dụ: !x=TRUE, nếu x=FALSE.
• && phép “and” lôgic.
• || phép “or” lôgic.
2.2.4.7 Phép toán xử lý bit
• ~ phép “not” bit. Ví dụ: ~0=1, ~1=0
• & phép “and” bit. Ví dụ: 1 &1 =1, 1 & 0 =0.
• | phép “or” bit.
• ^ phép “xor” bit.
• << phép dịch trái bit

• >> phép dịch phải bit.
• >>> phép chuyển bit dấu sang phải, thay bằng 0.
2.2.4.8 Các phép xử lý đặc biệt
• break có thể (nhưng không nên sử dụng) dùng để thoát khỏi hàm trong
script.
• Nếu các đối số khác kiểu, phép + sẽ tiến hành chuyển đổi kiểu tự động.
- Với chuỗi có thể chuyển đổi: “AB\n” + „de‟ sẽ được „AB\\nde‟
(trong đó “AB\n” là chuỗi không chuyển đổi, „de‟ là chuỗi có thể
chuyển đổi).
- Nếu một trong 2 đối số là kiểu chuỗi không chuyển đổi, đối số còn
lại sẽ được tự động chuyển thành kiểu chuỗi không chuyển đổi:
“ABC” + 2 sẽ được “ABC2”.
- Nếu một trong các đối số là kiểu nguyên, đối số còn lại sẽ được
chuyển sang kiểu nguyên, kết quả cuối cùng là kiểu nguyên.
- Trong các trường hợp khác, giá trị NULL được trả về.
• Phép trừ có cùng kiểu chuyển đổi như đối với phép cộng.
• Không nên sử dụng các biến chưa được khởi tạo. Tuy nhiên để các script
cũ có thể hoạt động, giá trị NULL được định nghĩa thành 0 hoặc “” (kiểu
15


integer hoặc chuỗi). Đó là lý do tại sao ta nên sử dụng isnull để kiểm tra
xem biến đã được định nghĩa và khởi tạo hay chưa.
2.2.5 Độ ưu tiên các phép toán
Độ ưu tiên từ cao xuống thấp:
Bảng 2.1 Độ ưu tiên của các phép toán.

STT
1
2

3
4
5
6
7
8
9
10
11
12
13
14

Phép toán
++ -**
~!
*/%
+<< >> >>>
&
^
|
< <= > >= == != <> =~ !
~ >!< ><
&&
||
= += -= *= /= %= <<=
>>= >>>=

Trình tự kết hợp
Không

Phải qua trái
Trái qua phải
Trái qua phải
Trái qua phải
Trái qua phải
Trái qua phải
Trái qua phải
Trái qua phải
Trái qua phải
Không
Trái qua phải
Trái qua phải
Phải qua trái

2.2.6 Vòng lặp và các câu lệnh điều khiển
• for (expr1; cond; expr2) block;tương tự như trong C, tương đương với
expr1; while(condition) block; expr2;
Ví dụ in các giá trị từ 1 đến 10: for(i=1;i<=10;i++) display(i,'{\n');
• foreach var (array) block;lặp với tất cả các phần tử trong mảng. Chú ý
biến vòng lặp var có giá trị được lưu trữ trong mảng, không phải chỉ số
của mảng. Nếu ta muốn dùng chỉ số, dùng lệnh: foreach var (keys(array))
block;
• while(cond) block; thực hiện khối lệnh khi điều kiện kiểm tra là TRUE,
dừng việc thực hiện nếu điều kiện kiểm tra là FALSE.

16









repeat block; until (cond); thực hiện khối lệnh cho đến khi điều kiện
kiểm tra là TRUE. Khối lệnh được thực hiện ít nhất một lần (khác với
while, có thể khối lệnh chưa được thực hiện lần nào).
break dùng để thoát khỏi vòng lặp hiện tại, nếu ta không ở trong vòng
lặp, kết quả là không xác định.
continue bỏ qua điều kiện kiểm tra, nhảy đến vòng lặp tiếp theo. Nếu
không ở trong vòng lặp, kết quả là không xác định.
return trả về kết quả của hàm hiện tại.

2.2.7 Khai báo biến, hàm
2.2.7.1 Khai báo biến
NASL1 chỉ có biến toàn cục. NASL2 sử dụng biến toàn cục và biến cục bộ.
Biến cục bộ được tạo bên trong hàm, và được giải phóng khi hàm trả về kết quả.
Khi trình thông dịch kiểm tra biến nào đó, nó sẽ kiểm tra trong hàm hiện tại
trước, sau đó kiểm tra các hàm bao trùm bên ngoài khác, cho tới khi đến hàm
chứa biến toàn cục.
Thông thường ta không cần phải khai báo biến: hoặc là do nó đã tồn tại, hoặc ta
đã sử dụng nó trong hàm hiện tại, hoặc nó đang được gọi bởi một hàm khác.
Tuy nhiên, điều này trở nên nguy hiểm trong một vài trường hợp:




Nếu bạn muốn thay đổi tới biến cục bộ từ bên trong một hàm mà không
thể chắc chắn biến được tạo ở hàm ngoài cùng, hoặc được tạo như biến
cục bộ trong hàm gọi đến.

Nếu bạn muốn chắc chắc rằng mình đang tạo một biến cục bộ mà không
ghi đè lên biến toàn cục trùng tên.

Để thực hiện, ta có thể khai báo biến như sau:



local_var var;
global_var var;

Nếu biến đã tồn tại trong hàm chỉ định, ta sẽ nhận được thông điệp báo lỗi,
nhưng nó vẫn hoạt động được.
2.2.7.2 Khai báo hàm
• function_name (argname1, argname2) block;

17


Chú ý danh sách đối số có thể trống, nhưng phải có tên hàm. Các đối số có thể
dùng trực tiếp mà không cần phải khai báo.
2.2.7.3 Lấy đối số của hàm
Trong một hàm NASL, các đối số được định tên, có thể truy cập bởi mọi biến
cục bộ. Các đối số không được định tên, được cài đặt thông qua mảng đặc biệt
_FCT_ANON_ARGS. Những biến này sẽ mang giá trị NULL với các trình
thông dịch dưới NASL_LEVEL 2190. Ta nên khai báo ở đầu script nếu cần
dùng hàm này:
if (NASL_LEVEL < 2190) exit(0); # _FCT_ANON_ARGS is not implemented
1. Thiết lập tới giá trị _FCT_ANON_ARGS chưa được định nghĩa. Lúc
này, bộ nhớ bị lãng phí, mà không thể đọc lại giá trị.
2. Sử dụng _FCT_ANON_ARGS để đọc các đối số được định tên cũng

không tốt. Lúc này, có sự bảo vệ, giá trị NULL được trả lại.
2.2.7.4 Gọi hàm
Sau đây là ví dụ về hàm có đối số được định tên:

Ví dụ về hàm có đối số không được định tên:

18


2.3 THƯ VIỆN NASL
2.3.1 Các hằng số được định nghĩa từ trước
Hằng thực ra là các biến, ta có thể chỉnh sửa lại giá trị trong script. Sau đây là
một số hằng được định nghĩa trước:






Hằng lôgic
• ALSE=0
• TRUE=1
Các loại plugin
• ACT_INIT: plugin chỉ thiết lập vài KB các mục (các loại biến
toàn cục cho tất cả các plugin).
• ACT_SCANNER: plugin này làm nhiệm vụ quét cổng hoặc một
vài tác vụ tương tự (như ping).
• ACT_SETTINGS: giống ACT_INIT nhưng chạy sau khi bộ quét
thực hiện, khi chúng ta chắc chắn rằng máy host vẫn đang hoạt
động.

• ACT_GATHER_INFO: plugin định danh dịch vụ, thu thập dữ
liệu, xử lý banner, v.v…
• ACT_ATTACK: plugin khởi động phần mềm tấn công, ví dụ
phần mềm quét các thư mục web.
• ACT_MIXED_ATTACK: plugin khởi động tấn công mà có thể
gây ra các tác dụng nguy hiểm khác (gây ra hỏng hầu hết các dịch
vụ thời gian).
• ACT_DESTRUCTIVE_ATTACK: plugin cố gắng tiêu hủy dữ
liệu hoặc khởi động tấn công nguy hiểm (ví dụ việc kiểm tra lỗi
tràn bộ đệm có thể gây ra hỏng hóc với các dịch vụ dễ bị tổn
thương).
• ACT_DENIAL: plugin cố gắng gây ra hỏng hóc dịch vụ.
• ACT_KILL_HOST: plugin cố gắng gây ra hỏng hóc cho máy
đích, hoặc vô hiệu một vài dịch vụ quan trọng.
• ACT_FLOOD: plugin cố gắng gây ra hỏng hóc cho máy đích,
hoặc vô hiệu hóa bằng cách gây ngập lụt với các gói tin hoặc
request không xác định. Nó có thể ảnh hưởng tới mạng, gây hỏng
hóc cho thiết bị định tuyến, chuyển mạch hoặc lọc gói trên đường
đi.
Hằng Network
• Nessus “encapsulation” (đóng gói)
19


ENCAPS_IP = 1; đây là giá trị “transport” cho TCP socket.
ENCAPS_SSLv23 = 2; đây là giá trị “transport” cho kết nối
SSL trong chế độ tương thích. Chú ý plugin find_service sẽ
không bao giờ khai báo cổng với loại đóng gói này, tuy nhiên ta
vẫn có thể dùng nó trong script.
 ENCAPS_SSLv2 = 3; phiên bản SSL cũ chỉ hỗ trợ chứng chỉ

phía máy chủ.
 ENCAPS_SSLv3 = 4; phiên bản SSL mới, hỗ trợ chứng chỉ
phía máy chủ và máy client, hỗ trợ nhiều phương pháp mã hóa.
 ENCAPS_TLSv1 = 5; TLSv1 được định nghĩa trong RFC 2246,
đôi khi người ta gọi nó là “SSL v3.1”.
• Sockets options
 MSG_OOB; tùy chọn socket, dùng gửi dữ liệu.
• Raw sockets
 IPPROTO_ICMP; được định nghĩa như trong file header của
C.
 IPPROTO_IGMP
 IPPROTO_IP
 IPPROTO_TCP
 IPPROTO_UDP
 pcap_timeout = 5
 TH_ACK = 0x10; Cờ TCP xác định gói tin hợp lệ.
 TH_FIN = 0x01; Cờ TCP xác định gói tin báo kết thúc phiên kết
nối.
 TH_PUSH = 0x08
 TH_RST = 0x04; Cờ TCP xác định kết nối bị từ chối hoặc reset
lại.
 TH_SYN = 0x02; Khởi tạo quá trình bắt tay 3 bước.
 TH_URG = 0x20; Cờ TCP xác định gói tin chứa dữ liệu quan
trọng.
Các hằng khác
• NULL giá trị không được định nghĩa.
Nessusd glue
• Description được thiết lập thành 1 khi nessusd phân tích script lần
đầu (lấy tên, chỉ dẫn, tóm tắt, v.v…), thành 0 khi nó chạy.
• COMMAND_LINE được thiết lập thành 0 khi script được chạy

bởi nessusd hoặc thành 1 khi nó chạy bởi trình thông dịch nasl.






20


2.3.2 Các hàm tích hợp sẵn
Các hàm được tích hợp sẵn bao gồm hàm có đối số và hàm không có đối số.
Một vài hàm kết hợp cả hai.
2.3.2.1 Các hàm cơ bản (Knowledge base functions)
Các hàm này được dùng cho các plugin tương tác.






set_kb_item tạo danh mục mới trong KB (Knowledge base).
Nó nhận 2 chuỗi đối số: tên và giá trị. Thực hiện khoản mục vài lần tạo ra
một danh sách.
get_kb_item nhận khoản mục từ KB.
Nó nhận đối số không được định tên (tên của khoản mục KB). Nếu khoản
mục là một danh sách, plugin sẽ chia nhỏ cho các tiến trình con, và sử
dụng giá trị khác. Nessus sẽ ghi nhớ tiến trình con nhận giá trị nào: đọc
một khoản mục trùng tên, nó sẽ không chia nhỏ lần nữa. Ta không nên sử
dụng hàm này khi có vài kết nối đang mở, tránh diễn ra tình trạng có

nhiều tiến trình cùng cố gắng đọc ghi vào cùng một socket.
get_kb_list nhận nhiều khoản mục từ KB. Nó nhận đối số không được
định danh, có thể tên danh mục KB hoặc mặt nạ. Giá trị trả về là một kết
quả tóm lược, ví dụ một mảng với khả năng có 2 chỉ số, vì vậy ta cần
chuyển đổi nó với make_list() hoặc sử dụng foreach để truy cập mỗi phần
tử (hàm make_array cho phép tạo ra những bảng băm như vậy).
Ví dụ sử dụng hàm get_kb_list:



replace_kb_item thêm khoản mục mới vào trong KB hoặc thay thế giá
trị cũ.
Nó nhận 2 đối số được định danh: tên và giá trị.
Thực hiện khoản mục một vài lần không tạo ra danh sách, nó chỉ ghi đè
giá trị cũ.
21


Hàm này không được định nghĩa lại trong mọi phiên bản của Nessus, để
an toàn ta cần kiểm tra giá trị đã được định nghĩa trước đó bằng cách gọi
đến hàm này hoặc sử dụng hàm replace_or_set_kb_item của NASL.
2.3.2.2 Các hàm báo cáo
Những hàm này gửi lại thông tin cho Nessus deamon.









scanner_status báo cáo quá trình quét cổng (nếu plugin là plugin quét
cổng). Nó nhận 2 đối số nguyên:
- current, số cổng đang quét.
- total, tổng số cổng cần quét.
security_note gửi kết quả các thông tin khác.
Nó nhận đối số là một số nguyên (số hiệu cổng), hoặc vài đối số được
định danh khác:
- data là dữ liệu báo cáo dạng text.
- port là số hiệu cổng TCP hoặc UDP của dịch vụ
- proto (hoặc protocol) tên giao thức (mặc định là “tcp”, giá trị khác
là “udp”).
security_hole báo cáo về các lỗ hổng nghiêm trọng.
Nó có thể nhận một đối số không được định danh là một số nguyên (số
hiệu cổng), hoặc một vài đối số được định danh khác:
- data là dữ liệu báo cáo dạng text.
- port là số hiệu cổng TCP hoặc UDP của dịch vụ
- proto (hoặc protocol) tên giao thức (mặc định là “tcp”, giá trị khác
là “udp”).
security_warning báo cáo về các lỗ hổng nhẹ.
Nó có thể nhận một đối số không được định danh là một số nguyên (số
hiệu cổng), hoặc một vài đối số được định danh khác:
- data là dữ liệu báo cáo dạng text.
- port là số hiệu cổng TCP hoặc UDP của dịch vụ
- proto (hoặc protocol) tên giao thức (mặc định là “tcp”, giá trị khác
là “udp”).

2.3.2.3 Các hàm chỉ dẫn
Với tất cả các hàm, ngoại trừ hàm script_get_preference chỉ được sử dụng trong
phần chỉ dẫn của plugin, ví dụ một khối lệnh được chạy khi biến description

mang giá trị 1. Nó chỉ có ý nghĩa trong môi trường Nessus, không có tác dụng
khi plugin chỉ chạy với trình thông dịch nasl.

22

















script_add_preference thêm các lựa chọn vào plugin. Nó nhận 3 đối số
được định danh:
o name là tên tùy chọn
o type kiểu tùy chọn, có thể là:
- checkbox
- entry
- password
- radio
o value là giá trị mặc định (yes hoặc no cho hộp chọn checkbox,

chuỗi ký tự cho khoản mục hoặc mật khẩu). Ví dụ:
script_add_preference (name:"Reverse traversal", type:"radio",
value:"none; Basic; Long URL");
script_bugtraq_id nó nhận một hoặc nhiều đối số nguyên không được
định danh.
script_category thiết lập loại plugin.
Thông thường nó nhận đối số nguyên không được định danh là một trong
các hằng được định nghĩa trước (ACT_xxx):
o ACT_INIT
o ACT_SCANNER
o ACT_SETTINGS
o ACT_GATHER_INFO
o ACT_ATTACK
o ACT_MIXED_ATTACK
o ACT_DESTRUCTIVE_ATTACK
o ACT_DENIAL
o ACT_KILL_HOST
script_copyright thiết lập chuỗi bản quyền của plugin (thường là tên tác
giả).
Nó nhận đối số kiểu chuỗi bất kỳ, hoặc một vài chuỗi được định danh
khác: english, francais, deutsch, portuguese.
script_cve_id thiết lập CVE IDs cho các lỗ hổng kiểm tra bởi script. Nó
có thể nhận bất kỳ đối số là số hoặc chuỗi không định danh. Nó thường
có dạng như “CVE-2002-042” hoặc “CAN-2003-666”.
script_dependencie thiết lập danh sách script cần chạy trước khi chạy
script này. Nó có thể nhận bất kỳ đối số là số hoặc chuỗi không định
danh.
script_dependencies có ý nghĩa giống như script_dependencie.

23

























script_description thiết lập chỉ dẫn của plugin. Nó nhận chuỗi bất kỳ
làm đối số, hoặc một trong các chuỗi được xác định trước: english,
francais, deutsch, portuguese. Giá trị mặc định là english.
script_exclude_keys thiết lập danh sách “KB item” không được chạy ở
script này trong chế độ tối ưu hóa.
script_family thiết lập các plugin cùng họ.

script_get_preference đọc các tùy chọn. Nó nhận chuỗi bất kỳ làm đối
số. Nó có thể trả về kết quả là chuỗi rỗng, nếu ta chỉ chạy script với trình
thông dịch nasl.
script_get_preference_file_content đọc các tùy chọn về file. Nó nhận
chuỗi bất kỳ làm đối số, kết quả trả về là nội dung file đã được chuyển từ
máy trạm Nessus tới máy chủ.
Chú ý: script script_get_preference_file_content và
script_get_preference_file_location được giới hạn chỉ chạy với các
plugin tin cậy.
script_get_preference_file_location nó chỉ có tác dụng nếu kiểu xử lý là
kiểu file. Nó sẽ trả về đường dẫn của file copy. Hàm
script_get_preference sẽ luôn trả về đường dẫn của file trên máy trạm,
điều này cũng không thực sự cần thiết.
script_id thiết lập số nguyên để định danh script.
script_name thiết lập tên của plugin.
script_require_keys thiết lập danh sách trong “KB item” cần phải chạy
khi chạy script này ở chế độ tối ưu.
script_require_ports thiết lập danh sách các cổng TCP cần mở khi chạy
script này ở chế độ tối ưu.
script_require_udp_ports thiết lập danh sách cổng UDP cần mở khi
chạy script này ở chế độ tối ưu.
script_summary thiết lập chỉ dẫn tóm tắt của plugin.
script_timeout thiết lập thời gian thoát của plugin. Nó nhận số nguyên
bất kỳ làm đối số. Nếu giá trị này được thiết lập thành 0 hoặc -1, thời gian
timeout bằng vô cùng.
script_version thiết lập phiên bản của plugin. Nó nhận chuỗi bất kỳ làm
đối số.

2.3.2.4 Các hàm gắn kết
get_preference nhận chuỗi bất kỳ làm đối số, và trả lại giá trị được ưu tiên.

Hàm này cần thiết khi cần nhận vài tùy chọn từ server. Ví dụ:
24


p = get_preference('port_range'); # returns something like 1-65535
2.3.2.5 Các hàm về mạng
Chú ý kiểu dữ liệu socket được sử dụng trong các hàm này thực ra là số nguyên.
Trong trường hợp có lỗi, tất cả các hàm trả về một giá trị có thể thông dịch là
FALSE.
















close đóng socket.
end_denial không cần đối số, trả về TRUE nếu máy host vẫn đang hoạt
động (alive), FALSE nếu nó chết. Ta cần gọi hàm start_denial trước khi
kiểm tra.
ftp_get_pasv_port gửi câu lệnh “PASV” tới socket đang mở. Phân tích

dữ liệu nhận được, trả lại số hiệu cổng thụ động đã chọn. Nó nhận một
đối số định danh: socket.
get_host_name không cần đối số, trả lại tên máy host đang quét.
get_host_ip không cần đối số, trả lại địa chỉ IP máy đích.
get_host_open_port không cần đối số, trả lại tên số hiệu các cổng TCP
đang mở trên máy đích.
get_port_transport nhận số nguyên bất kỳ (socket) làm đối số, trả lại giá
trị đóng gói (encapsulation).
get_port_state nhận số nguyên bất kỳ (số hiệu cổng TCP), trả lại TRUE
nếu cổng đó đang mở, FALSE ngược lại.
Một vài cổng TCP sẽ không biết được trạng thái, do không thể quét được.
Cách ứng xử của hàm này có thể chỉnh sửa lại, coi các cổng không quét
được như đã đóng, với tùy chọn toàn cục. Khi tùy chọn này được thiết lập
lại (default), hàm sẽ trả về giá trị TRUE với các cổng không biết trạng
thái, FALSE khi ta đặt thiết lập như trên.
get_source_port nhận số nguyên bất kỳ làm đối số (TCP socket), trả lại
số hiệu cổng nguồn (ví dụ cổng server Nessus).
get_tcp_port_state tương tự như get_port_state.
get_udp_port_state trả lại giá trị TRUE nếu cổng UDP đang mở,
FALSE ngược lại. Chú ý việc quét cổng UDP có thể không đáng tin cậy.
islocalhost không cần đối số, trả lại TRUE nếu máy đích là chính máy
local, ngược lại FALSE.
islocalnet không cần đối số, trả lại TRUE nếu máy đích cùng mạng với
máy local, ngược lại FALSE.

25


Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×