# OpenVAS
Dưới đây là tài liệu kỹ thuật chi tiết về công cụ OpenVAS (https://www.openvas.org/), bao gồm các nội dung như cài đặt trên Kali Linux, cập nhật OpenVAS, quét mục tiêu theo nhiều cách khác nhau, sử dụng Python để tương tác với API của OpenVAS, và cách viết script NASL.
## 1. Cài đặt OpenVAS trên Kali Linux
OpenVAS là một công cụ quét lỗ hổng mạng mở và miễn phí, được sử dụng rộng rãi trong các hoạt động kiểm tra an ninh. Dưới đây là hướng dẫn chi tiết để cài đặt OpenVAS trên Kali Linux:
### Bước 1: Cập nhật hệ thống
Trước khi cài đặt OpenVAS, cần cập nhật và nâng cấp hệ thống Kali Linux để đảm bảo tính tương thích và ổn định:
```bash
sudo apt update
sudo apt upgrade -y
sudo apt dist-upgrade -y
```
### Bước 2: Cài đặt OpenVAS
OpenVAS có sẵn trong kho gói của Kali Linux. Sử dụng lệnh sau để cài đặt:
```bash
sudo apt install openvas
```

### Bước 3: Cấu hình và thiết lập OpenVAS
Sau khi cài đặt, cần chạy script cấu hình để thiết lập OpenVAS và tải xuống các Network Vulnerability Tests (NVTs):
```bash
sudo gvm-setup
```

- **Lưu ý**: Bước này có thể mất một thời gian (khoảng 10 phút) vì OpenVAS cần tải xuống hơn 50.000 NVTs.
- Kết thúc quá trình, OpenVAS sẽ tự động tạo một tài khoản admin và hiển thị mật khẩu được tạo ngẫu nhiên. Hãy ghi lại mật khẩu này.
### Bước 4: Kiểm tra cài đặt
Để đảm bảo OpenVAS đã được cài đặt đúng, sử dụng lệnh:
```bash
sudo gvm-check-setup
```

### Bước 5: Khởi động OpenVAS
Khởi động các dịch vụ của OpenVAS:
```bash
sudo gvm-start
```
### Bước 6: Truy cập giao diện web
Sau khi khởi động, truy cập giao diện web của OpenVAS tại địa chỉ:
```
https://localhost:9392
```
- Sử dụng tài khoản admin và mật khẩu được tạo trong bước 3 để đăng nhập.

### Bước 7: Quản lý người dùng (Tùy chọn)
- **Tạo người dùng mới**:
```bash
sudo runuser -u _gvm -- gvmd --create-user=admin2 --new-password=12345
```
- **Đổi mật khẩu người dùng hiện tại**:
```bash
sudo runuser -u _gvm -- gvmd --user=admin --new-password=new_password
```
**Nguồn tham khảo**: [GeeksforGeeks - Installing OpenVAS on Kali Linux](https://www.geeksforgeeks.org/installation-guide/installing-openvas-on-kali-linux/)
## 2. Cập nhật OpenVAS
Việc cập nhật OpenVAS bao gồm nâng cấp phiên bản và cập nhật các lỗ hổng (vulnerabilities, CVE). Dưới đây là các bước cập nhật (_gvm ở đây là user hãy đảm bảo user này đã tồn tại):
### Bước 1: Cập nhật thông tin lỗ hổng từ các feed công khai
Chạy lệnh sau để đồng bộ hóa feed GVMD_DATA:
```bash
sudo -u _gvm greenbone-feed-sync --type GVMD_DATA
```
### Bước 2: Cập nhật NVTs
Để cập nhật các Network Vulnerability Tests (NVTs), sử dụng lệnh:
```bash
sudo -u _gvm greenbone-nvt-sync
```
- Lệnh này sẽ đồng bộ hóa NVTs từ Greenbone Security Feed hoặc Greenbone Community Feed.

### Bước 3: Cập nhật dữ liệu SCAP và CERT
Ngoài NVTs, OpenVAS cũng cần cập nhật dữ liệu SCAP (Security Content Automation Protocol) và CERT:
```bash
sudo -u _gvm greenbone-feed-sync --type SCAP
sudo -u _gvm greenbone-feed-sync --type CERT
```

### Bước 4: Kiểm tra trạng thái cập nhật
Sau khi cập nhật, có thể kiểm tra trạng thái của các feed trong giao diện web của OpenVAS:
- Truy cập `https://localhost:9392`.
- Đi đến `Administration -> Feed Status`.
- Đảm bảo tất cả các feed đều được cập nhật và hiển thị trạng thái "Current".
**Nguồn tham khảo**: [Claudiokuenzler.com - How to manually update the security feeds in GVM](https://www.claudiokuenzler.com/blog/1261/how-to-update-security-feeds-gvm-greenbone-vulnerability-management-openvas)
## 3. Quét mục tiêu với OpenVAS
OpenVAS (nay là Greenbone Vulnerability Management – GVM) hỗ trợ nhiều kiểu quét: theo CVE, giao thức, dịch vụ ứng dụng, điều chỉnh tốc độ, và có thể vận hành qua proxy SOCKS5 (như ProxyChains). Các ví dụ dưới đây dựa trên thông tin chính thức từ Greenbone.
### 3.1 Quét theo CVE (CVE Scan)
#### Vì sao cần thực hiện CVE Scan:
- CVE Scan là dạng **scanner dự đoán** dựa trên thông tin về CPE (phần mềm/hệ điều hành) thu được từ các kết quả quét trước đó và so đối chiếu với cơ sở dữ liệu CVE.
- Cần chạy full scan trước, sau đó mới có thể chạy CVE scan chính xác.
#### Các bước thực hiện:
1. Truy cập **Configuration → Scan Configs**, clone hoặc chọn cấu hình “Full and fast”.
2. Tạo task quét full scan, bật **Add results to Assets = Yes**.


**Lưu ý:** Máy target hiện đang host 2 container vuln đó là :
https://github.com/xbow-engineering/validation-benchmarks/tree/main/benchmarks/XBEN-005-24
và https://github.com/vulhub/vulhub/tree/master/activemq/CVE-2023-46604
Kết quả sau khi quét:


3. Sau khi quét xong, tạo task mới:
- **Scanner**: chọn “CVE scanner”
- **Target**: dùng lại mục tiêu vừa quét

4. Start task và xem báo cáo.

Mặc dù đã đầy đủ CPE từ lần scan trước nhưng không hiểu đã phát sinh vấn đề gì khiến CVE Scanner không thể tìm được host và không quét thành công
### 3.2. Quét theo giao thức
Để quét các lỗ hổng liên quan đến một giao thức cụ thể (ví dụ: SSH, HTTP, DNS, Redis), cần chọn hoặc tạo cấu hình quét bao gồm các NVT liên quan đến giao thức đó.
#### Cách thực hiện:
- **Bước 1**: Đăng nhập vào giao diện web của OpenVAS (`https://localhost:9392`).
- **Bước 2**: Đi đến `Configuration -> Scan Configs` và tạo một cấu hình quét mới bằng cách nhấp vào biểu tượng ("New Scan Config"). Đặt tên, ví dụ: "HTTP_Scan" hoặc "SSH_Scan".
- **Bước 3**: Trong phần "Edit Scan Config", chọn các nhóm NVT liên quan:
- **Ví dụ đối với HTTP**: Chọn nhóm "Web Servers", "Web Application Abuses".

- Thực hiện tương tự với DNS/Redis/SSH.
- **Bước 4**: Tạo danh sách cổng tại `Configuration -> Port Lists`:
- HTTP: "T:80, T:443, T:8080, T:8443".
- SSH: "T:22".
- DNS: "T:53, U:53".
- Redis: "T:6379".

- **Bước 5**: Tạo mục tiêu tại `Scans -> Targets`, nhập IP (ví dụ: `192.168.1.100`) và liên kết danh sách cổng. Nếu quét SSH, thêm thông tin xác thực SSH tại `Configuration -> Credentials` (tên người dùng, mật khẩu hoặc khóa SSH).


- **Bước 6**: Tạo nhiệm vụ tại `Scans -> Tasks`, chọn mục tiêu và cấu hình quét tùy chỉnh, sau đó nhấp "Start" để bắt đầu quét.


### 3.3. Quét theo dịch vụ hoặc ứng dụng
Để quét các lỗ hổng liên quan đến một dịch vụ hoặc ứng dụng cụ thể (ví dụ: Apache Tomcat, MySQL),cần tạo cấu hình quét tùy chỉnh bao gồm các Network Vulnerability Tests (NVTs) liên quan đến dịch vụ hoặc ứng dụng đó. Điều này giúp tập trung vào các lỗ hổng cụ thể và tối ưu hóa hiệu suất quét.
#### Cách thực hiện:
- **Bước 1**: Đi đến `Configuration -> Scan Configs` và nhấp vào biểu tượng "New" để tạo cấu hình quét mới. Đặt tên cho cấu hình, ví dụ: "Tomcat_Scan" cho Apache Tomcat hoặc "MySQL_Scan" cho MySQL.
- **Bước 2**: Trong phần "Edit Scan Config", chọn các nhóm NVT (Network Vulnerability Test Families) liên quan đến dịch vụ hoặc ứng dụng:
- **Ví dụ đối với MySQL**: Chọn nhóm "Databases".

- **Bước 4**: Tạo danh sách cổng tại `Configuration -> Port Lists` để tập trung vào cổng liên quan đến dịch vụ:
- Đối với MySQL: "T:3306".

- **Bước 5**: Tạo mục tiêu tại `Scans -> Targets`, nhập địa chỉ IP hoặc phạm vi của hệ thống muốn quét. Nếu quét yêu cầu xác thực (như SSH hoặc SMB), thêm thông tin xác thực tại `Configuration -> Credentials`.

- **Bước 6**: Tạo nhiệm vụ tại `Scans -> Tasks`, chọn mục tiêu và cấu hình quét tùy chỉnh, sau đó nhấp "Start" để bắt đầu quét.

#### Lưu ý quan trọng:
- **Không nên sử dụng cấu hình quét tùy chỉnh nếu không cần thiết**: Các cấu hình mặc định như "Full and Fast" thường đủ cho hầu hết các trường hợp. Chỉ nên tùy chỉnh khi có lý do cụ thể, như quét một dịch vụ đặc biệt hoặc giảm tải cho mục tiêu.
- **Rủi ro khi quét tùy chỉnh**: Nếu không chọn đúng NVTs, có thể bỏ sót một số lỗ hổng. Do đó, hãy đảm bảo rằng đã nghiên cứu kỹ về các NVTs liên quan đến dịch vụ hoặc ứng dụng mục tiêu.
- **Sử dụng công cụ hỗ trợ**: Trước khi quét, có thể sử dụng công cụ như Nmap để khám phá các cổng mở và dịch vụ đang chạy trên mục tiêu. Ví dụ:
```bash
nmap -sn -oA nmap-subnet-86 192.168.92.0/24
grep Up nmap-subnet-86.gnmap | cut -d " " -f 2 > live-hosts.txt
```
Sau đó, nhập danh sách các host vào OpenVAS tại `Configuration -> Targets`.
### 3.4. Điều chỉnh tốc độ quét
OpenVAS cho phép điều chỉnh tốc độ quét để tối ưu hóa hiệu suất hoặc giảm tải trên mục tiêu.
#### Cách thực hiện:
- **Bước 1**: Đi đến `Configuration -> Scan Configs` và chỉnh sửa một cấu hình quét.
- **Bước 2**: Trong phần "Scanner Preferences", điều chỉnh các tham số trong đó.
- **Bước 3**: Lưu cấu hình và sử dụng nó trong nhiệm vụ quét.
### 3.5. Quét với proxy (SOCKS5)
Để quét qua proxy SOCKS5, cần cấu hình OpenVAS hoặc sử dụng công cụ như `proxychains`.
#### Cách thực hiện (Sử dụng proxychains):
- **Bước 1**: Cài đặt `proxychains`:
```bash
sudo apt install proxychains
```
- **Bước 2**: Chỉnh sửa file cấu hình `/etc/proxychains.conf` để thêm proxy SOCKS5:
```plaintext
socks5 127.0.0.1 1080
```
- **Bước 3**: Chạy OpenVAS qua `proxychains`:
```bash
proxychains openvas
```
- **Bước 4**: Tạo và chạy nhiệm vụ quét như bình thường.
#### Cách thực hiện (Cấu hình trực tiếp trong OpenVAS):
- **Bước 1**: Chỉnh sửa file cấu hình của OpenVAS tại `/etc/openvas/openvassd.conf`:
```plaintext
socks_use_proxy = yes
socks_proxy_host = 127.0.0.1
socks_proxy_port = 1080
socks_proxy_type = SOCKS5
socks_proxy_userid = username
socks_proxy_password = password
```
- **Bước 2**: Khởi động lại dịch vụ OpenVAS:
```bash
sudo systemctl restart openvas-scanner
```
- **Bước 3**: Tạo và chạy nhiệm vụ quét như bình thường.
**Nguồn tham khảo**:
- [What is the difference between the openvas default scanner and cve scanner](https://forum.greenbone.net/t/what-is-the-difference-beween-the-openvas-default-scanner-and-the-cve-scanner/8555)
- [Hacking Tutorials - Vulnerability Scanning with OpenVAS 9 part 4: Custom scan configurations](https://www.hackingtutorials.org/scanning-tutorials/openvas-9-part-4-custom-scan-configurations/)
- [Rapid7 Blog - How to Use OpenVAS to Audit the Security of Your Network (2/2)](https://www.rapid7.com/blog/post/2016/11/22/how-to-use-openvas-to-audit-the-security-of-your-network-22/)
- [Security Newspaper - How to configure, run and automate OpenVAS: Free Vulnerability Scanner](https://www.securitynewspaper.com/2020/12/19/how-to-configure-run-and-automate-openvas-free-vulnerability-scanner/)
## 4\. Tương tác với Greenbone (OpenVAS) bằng Python API
Tự động hóa các tác vụ quét lỗ hổng bằng cách tương tác với API của Greenbone Vulnerability Management (GVM) thông qua Giao thức Quản lý Greenbone (GMP). Thư viện `python-gvm` là công cụ hiện đại và được khuyên dùng cho Python 3 để thực hiện việc này.
### 4.1. Cài đặt thư viện
Để bắt đầu, hãy cài đặt thư viện `python-gvm` và `lxml` để xử lý dữ liệu XML.
```bash
pip install python-gvm lxml
```
- **Lưu ý quan trọng**: Thư viện `openvas-lib` cũ hơn đã không còn được duy trì và chỉ tương thích với Python 2.7. **Không nên sử dụng `openvas-lib`** cho các hệ thống GVM/OpenVAS hiện đại.
-----
### 4.2. Kết nối và thực hiện quét
Quy trình tự động hóa một phiên quét cơ bản bao gồm các bước: kết nối, xác thực, tạo mục tiêu, tạo và khởi chạy tác vụ.
#### 4.2.1. Cách tìm ID trên giao diện Web (GSA)
Trước khi chạy script, cần lấy các ID sau từ giao diện web GVM:
1. **`SCANNER_ID`**:
* Đi đến menu **Administration** -\> **Scanners**.
* Nhấn vào máy quét muốn dùng (ví dụ: "OpenVAS Default").
* Sao chép ID từ cuối URL trên thanh địa chỉ.
2. **`SCAN_CONFIG_ID`**:
* Đi đến menu **Scans** -\> **Scan Configs**.
* Nhấn vào cấu hình quét muốn dùng (ví dụ: "Full and fast").
* Sao chép ID từ cuối URL.
3. **`PORT_LIST_ID`**:
* Đi đến menu **Configuration** -\> **Port Lists**.
* Nhấn vào danh sách cổng muốn dùng (ví dụ: "All IANA assigned TCP").
* Sao chép ID từ cuối URL.
#### 4.2.2. Ví dụ: Script hoàn chỉnh để chạy một tác vụ quét
Đây là script hoàn chỉnh sử dụng phương pháp gán ID thủ công.
```python
from gvm.connections import UnixSocketConnection
from gvm.protocols.gmp import Gmp
from gvm.transforms import EtreeTransform
from gvm.errors import GvmError
import datetime
from xml.etree import ElementTree
# --- THAY ĐỔI CÁC BIẾN NÀY ---
TARGET_IP = "192.168.92.129" # IP mục tiêu cần quét
# Dán các ID lấy từ giao diện web vào đây
SCANNER_ID = "YOUR_SCANNER_ID_HERE"
SCAN_CONFIG_ID = "YOUR_SCAN_CONFIG_ID_HERE"
PORT_LIST_ID = "YOUR_PORT_LIST_ID_HERE"
# Điền thông tin đăng nhập GVM
GVM_USER = "admin"
GVM_PASSWORD = "your_password_here"
# -----------------------------
try:
connection = UnixSocketConnection()
transform = EtreeTransform()
with Gmp(connection, transform=transform) as gmp:
# 1. Xác thực
gmp.authenticate(GVM_USER, GVM_PASSWORD)
print("Kết nối và xác thực thành công!")
# 2. Tạo mục tiêu (Target) với tên duy nhất
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
target_name = f"Target {TARGET_IP} ({timestamp})"
response = gmp.create_target(
name=target_name,
hosts=[TARGET_IP],
port_list_id=PORT_LIST_ID
)
# Kiểm tra trạng thái phản hồi. "201" là mã cho "Created"
if response.get('status') != '201':
error_message = ElementTree.tostring(response, encoding='unicode')
raise Exception(f"Không thể tạo Target. Phản hồi từ GVM:\n{error_message}")
target_id = response.get("id")
print(f"Đã tạo Target '{target_name}' với ID: {target_id}")
# 3. Tạo và khởi chạy tác vụ (Task)
task_name = f"Scan for {target_name}"
task_id = gmp.create_task(
name=task_name,
config_id=SCAN_CONFIG_ID,
target_id=target_id,
scanner_id=SCANNER_ID
).get("id")
print(f"Đã tạo Task '{task_name}' với ID: {task_id}")
gmp.start_task(task_id)
print(f"Đã bắt đầu quá trình quét! Theo dõi tiến trình trong GSA.")
except GvmError as e:
print(f"Lỗi GVM: {e}")
except Exception as e:
print(f"Đã xảy ra lỗi: {e}")
```



### 4.3. Quét nhiều mục tiêu cùng lúc, mỗi mục tiêu là một task riêng
Sử dụng `threading` để khởi chạy nhiều tác vụ quét song song.
```python
import threading
import datetime
from gvm.connections import UnixSocketConnection
from gvm.protocols.gmp import Gmp
from gvm.transforms import EtreeTransform
from xml.etree import ElementTree
def scan_target(host, scanner_id, config_id, port_list_id, user, password):
"""Hàm để quét một mục tiêu duy nhất."""
try:
connection = UnixSocketConnection()
with Gmp(connection, transform=EtreeTransform()) as gmp:
gmp.authenticate(user, password)
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
target_name = f"Target {host} ({timestamp})"
response = gmp.create_target(
name=target_name, hosts=[host], port_list_id=port_list_id
)
if response.get('status') != '201':
error_message = ElementTree.tostring(response, encoding='unicode')
print(f"Lỗi khi tạo target cho {host}: {error_message}")
return
target_id = response.get("id")
task_id = gmp.create_task(
name=f"Scan {target_name}",
config_id=config_id,
target_id=target_id,
scanner_id=scanner_id
).get("id")
gmp.start_task(task_id)
print(f"Đã bắt đầu quét cho {host} (Task ID: {task_id})")
except Exception as e:
print(f"Lỗi khi quét {host}: {e}")
# --- Luồng chính ---
# Điền các thông tin cần thiết vào đây
GVM_USER = "admin"
GVM_PASSWORD = "your_password_here"
SCANNER_ID = "YOUR_SCANNER_ID_HERE"
SCAN_CONFIG_ID = "YOUR_SCAN_CONFIG_ID_HERE"
PORT_LIST_ID = "YOUR_PORT_LIST_ID_HERE"
targets = ["192.168.1.101", "192.168.1.102", "10.0.0.5"]
threads = []
for target_ip in targets:
args = (target_ip, SCANNER_ID, SCAN_CONFIG_ID, PORT_LIST_ID, GVM_USER, GVM_PASSWORD)
thread = threading.Thread(target=scan_target, args=args)
threads.append(thread)
thread.start()
# Chờ tất cả các luồng hoàn thành
for thread in threads:
thread.join()
print("\nTất cả các tác vụ quét đã được khởi chạy.")
```
- **Lưu ý**: Việc chạy quá nhiều luồng có thể làm quá tải máy chủ GVM. Hãy theo dõi tài nguyên hệ thống (CPU, RAM) và điều chỉnh số lượng luồng đồng thời cho phù hợp.


### 4.4. Lấy ra thông tin dạng JSON
GVM API cung cấp báo cáo gốc dưới dạng XML. Từ file XML này, chúng ta có thể dễ dàng chuyển đổi sang định dạng JSON để xử lý.
Đầu tiên, chúng ta sẽ tải báo cáo dạng XML.
**Lưu ý** : tạm thời nó đang bị bug gì đó có thể tải report từ web trực tiếp nhưng không thể tải từ gvm-cli cũng như script python. @@
```python
import base64
from gvm.connections import UnixSocketConnection
from gvm.protocols.gmp import Gmp
from gvm.transforms import EtreeTransform
# Điền thông tin đăng nhập
GVM_USER = "admin"
GVM_PASSWORD = "your_password_here"
try:
connection = UnixSocketConnection()
transform = EtreeTransform()
with Gmp(connection, transform=transform) as gmp:
gmp.authenticate(GVM_USER, GVM_PASSWORD)
# Lấy báo cáo mới nhất đã hoàn thành
reports_xml = gmp.get_reports(filter_string="sort-reverse=created rows=1 status=Done")
report_element = reports_xml.find(".//report")
if report_element is None:
print("Không tìm thấy báo cáo nào đã hoàn thành.")
else:
report_id = report_element.get("id")
print(f"Tìm thấy báo cáo ID: {report_id}. Đang tiến hành tải xuống...")
# Lấy ID của định dạng báo cáo XML
report_formats = gmp.get_report_formats()
xml_format_element = report_formats.find('.//report_format[name="XML"]')
if xml_format_element is None:
raise ValueError("Không tìm thấy định dạng báo cáo XML.")
xml_format_id = xml_format_element.get('id')
# Yêu cầu tải báo cáo với định dạng đã chọn
response = gmp.get_report(report_id=report_id, report_format_id=xml_format_id)
# Lấy nội dung báo cáo được mã hóa base64
report_content_base64 = response.find(".//report").text
# Giải mã và lưu ra file XML
report_data = base64.b64decode(report_content_base64)
file_path = f"report-{report_id}.xml"
with open(file_path, 'wb') as f:
f.write(report_data)
print(f"Báo cáo XML đã được lưu thành công tại: {file_path}")
except Exception as e:
print(f"Đã xảy ra lỗi: {e}")
```
#### Chuyển đổi từ XML sang JSON
Sau khi đã có file XML, dùng thư viện `xmltodict` để chuyển đổi nó sang JSON một cách dễ dàng.
1. **Cài đặt thư viện:**
```bash
pip install xmltodict
```
2. **Đoạn code chuyển đổi:**
```python
import xmltodict
import json
# Tên file XML đã tải về
xml_file_path = 'report-your-report-id.xml'
json_file_path = xml_file_path.replace('.xml', '.json')
try:
with open(xml_file_path, 'r', encoding='utf-8') as xml_file:
# Đọc file XML và chuyển thành dictionary
data_dict = xmltodict.parse(xml_file.read())
# Chuyển dictionary thành chuỗi JSON
json_data = json.dumps(data_dict, indent=4)
with open(json_file_path, 'w', encoding='utf-8') as json_file:
json_file.write(json_data)
print(f"Đã chuyển đổi thành công sang file JSON: {json_file_path}")
except FileNotFoundError:
print(f"Lỗi: Không tìm thấy file {xml_file_path}")
except Exception as e:
print(f"Đã xảy ra lỗi khi chuyển đổi: {e}")
```
#### Lưu ý quan trọng
- **Quyền truy cập**: Khi sử dụng `UnixSocketConnection`, script của cần quyền đọc/ghi trên file socket của `gsad`. Cách tốt nhất là thêm người dùng hiện tại vào nhóm `_gvm`:
```bash
sudo usermod -aG _gvm $(whoami)
```
Sau đó, cần **đăng xuất và đăng nhập lại** để thay đổi có hiệu lực.
- **Xác thực (Authentication)**: Như đã thấy, nhiều hệ thống GVM yêu cầu xác thực ngay cả khi kết nối qua socket. Luôn đảm bảo lệnh `gmp.authenticate()` được gọi sau khi kết nối.
- **Cập nhật thư viện**: Giữ cho `python-gvm` luôn ở phiên bản mới nhất để đảm bảo tính tương thích và nhận các bản sửa lỗi.
```bash
pip install --upgrade python-gvm
```
**Nguồn tham khảo**:
- [PyPI - openvas-lib](https://pypi.org/project/openvas-lib/)
- [GitHub - python-gvm](https://github.com/greenbone/python-gvm)
## 5\. Hướng dẫn viết Script NASL cho Greenbone/OpenVAS
**Lưu ý**: Phần 5 đang bị lỗi không tải được compat.inc nên các code .nasl không thể chạy được thành công 😢
**NASL** (Nessus Attack Scripting Language) là ngôn ngữ kịch bản được sử dụng để viết các bài kiểm tra lỗ hổng mạng (gọi là **NVT** - Network Vulnerability Test) cho máy quét lỗ hổng OpenVAS, thành phần cốt lõi của Greenbone Vulnerability Manager (GVM).
### 5.1. Cấu trúc cơ bản của một Script NASL
Một script NASL tiêu chuẩn bao gồm hai phần chính: phần khai báo thông tin và phần logic kiểm tra.
```nasl
# Luôn bắt đầu bằng việc include thư viện tương thích
include("compat.inc");
# Phần 1: Khai báo thông tin (metadata) của script
# Khối này chỉ được thực thi khi scanner cần đọc thông tin về NVT
if(description)
{
# ID duy nhất cho NVT, nằm trong dải private (100000 - 999999)
script_id(100001);
script_version("1.0"); # Phiên bản script
script_cvs_date("$Date$"); # Ngày cập nhật cuối
# Tên và các mô tả chi tiết về NVT
script_name(english:"Tên của bài kiểm tra");
script_summary(english:"Tóm tắt ngắn gọn về mục đích của script.");
script_set_attribute(attribute:"synopsis", value:"Mô tả vấn đề trong một câu.");
script_set_attribute(attribute:"description", value:"Mô tả chi tiết về lỗ hổng, rủi ro và những gì script này thực hiện.");
script_set_attribute(attribute:"solution", value:"Hướng dẫn chi tiết cách khắc phục lỗ hổng.");
script_set_attribute(attribute:"plugin_type", value:"local"); # hoặc "remote"
# Phân loại và thông tin tham chiếu
script_family(english:"Tên họ của NVT (ví dụ: Debian Local Security Checks)");
script_copyright(english:"(c) 2025 Tên Copyright");
script_category(ACT_GATHER_INFO); # Loại hành động: thu thập thông tin, tấn công, DoS, v.v.
script_dependencies("gather-package-list.nasl"); # Script này chỉ chạy sau khi script dependency đã chạy
script_require_keys("Host/local_checks_enabled", "Host/Debian/dpkg-l"); # Yêu cầu các key này phải có trong KB (Knowledge Base)
# Đánh giá điểm CVSS
script_set_cvss_base_vector("CVSS2#AV:N/AC:L/Au:N/C:P/I:P/A:P");
script_set_cvss3_base_vector("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L");
script_end_attributes(); # Kết thúc khối khai báo
# Thoát ngay sau khi khai báo để không chạy phần logic
exit(0);
}
# Phần 2: Logic kiểm tra lỗ hổng
# Code ở đây chỉ thực thi trong quá trình quét thực tế
include("audit.inc");
include("global_settings.inc");
# ... các thư viện cần thiết khác ...
# Bắt đầu code logic
port = get_kb_item("Services/www");
if (!port) port = 80;
if (!get_port_state(port)) audit(AUDIT_PORT_CLOSED, port);
# Thực hiện kiểm tra
# ...
# Báo cáo kết quả
if (vulnerable)
{
security_message(port:port, data:"Mô tả kết quả tìm thấy.");
exit(0);
}
# Nếu không tìm thấy lỗ hổng, ghi nhận là đã kiểm tra
audit(AUDIT_HOST_NOT, "bị ảnh hưởng");
```
### 5.2. Ví dụ : Kiểm tra HTTP Header nhạy cảm
Script này kết nối tới một web server, lấy các header HTTP và cảnh báo nếu có header `Server` hoặc `X-Powered-By` vì chúng làm lộ thông tin về công nghệ đang sử dụng.
```nasl
# Example_http.nasl
include("compat.inc");
if (description)
{
script_id(100011);
script_version("1.1");
script_name(english:"Check for Sensitive Information in HTTP Headers");
script_summary(english:"Kiểm tra các HTTP header như 'Server' và 'X-Powered-By'.");
script_set_attribute(attribute:"synopsis", value:"Web server tiết lộ thông tin phiên bản phần mềm.");
script_set_attribute(attribute:"description", value:"Phản hồi HTTP từ web server chứa các header 'Server' hoặc 'X-Powered-By'. Những header này có thể tiết lộ phiên bản phần mềm đang chạy, giúp kẻ tấn công xác định các lỗ hổng đã biết.");
script_set_attribute(attribute:"solution", value:"Cấu hình web server để loại bỏ hoặc thay đổi giá trị của các header 'Server' và 'X-Powered-By' khỏi các phản hồi HTTP.");
script_set_attribute(attribute:"plugin_type", value:"remote");
script_end_attributes();
script_category(ACT_GATHER_INFO);
script_family(english:"Web Servers");
script_copyright(english:"(c) 2025 Your Name");
exit(0);
}
include("http.inc");
include("audit.inc");
# Lấy port web đang mở, mặc định là 80
port = get_http_port(default:80);
# Nếu port không mở, thoát
if (!get_port_state(port))
{
audit(AUDIT_PORT_CLOSED, port);
}
# Gửi yêu cầu và lấy headers
res = http_send_recv3(method:"GET", item:"/", port:port);
if (isnull(res))
{
audit(AUDIT_RESP_NOT, port);
}
# Tìm các header nhạy cảm
banner = tolower(res[2]); # Lấy phần header và chuyển thành chữ thường
found = FALSE;
report = "";
if ("server:" >< banner)
{
server_header = egrep(pattern:"^server:.*", string:res[2]);
if(server_header) {
report += '- Tìm thấy header "Server":\n' + server_header + '\n';
found = TRUE;
}
}
if ("x-powered-by:" >< banner)
{
xpb_header = egrep(pattern:"^x-powered-by:.*", string:res[2]);
if(xpb_header) {
report += '- Tìm thấy header "X-Powered-By":\n' + xpb_header + '\n';
found = TRUE;
}
}
# Nếu tìm thấy, tạo báo cáo
if (found)
{
security_report_v4(
port: port,
severity: SECURITY_NOTE, # Mức độ NOTE (thông tin)
extra: report
);
}
else
{
audit(AUDIT_HOST_NOT, "tiết lộ thông tin qua các header nhạy cảm");
}
```
### 5.3. Hướng dẫn chạy Ví dụ kiểm tra HTTP Header
Phần này sẽ hướng dẫn cách chạy script ở mục 5.2 để kiểm tra các header nhạy cảm trên một máy chủ web.
#### Bước 1: Chuẩn bị môi trường
1. **Script NASL**: Lưu lại đoạn code từ mục 5.2 vào một file có tên là `http_header_check.nasl`.
2. **Máy chủ web mục tiêu**: set up một web đơn giản cùng mạng NAT
#### Bước 2: Kiểm tra và Debug từ Dòng lệnh
Bây giờ, chúng ta sẽ dùng `openvas-nasl` để chạy thử script của với máy chủ web vừa tạo.
* Mở một terminal khác .
* Chạy lệnh sau, thay `/path/to/your/` bằng đường dẫn thực tế đến file `http_header_check.nasl` .
<!-- end list -->
```bash
# -t 192.168.92.129: Chỉ định mục tiêu
# -p 80: Chỉ định cổng cần quét
# -i : chỉ định đường dẫn include, thường là /var/lib/openvas/plugins
# -X: Chế độ debug
sudo openvas-nasl -X -i /var/lib/openvas/plugins -t 192.168.92.129 -p 80 /path/to/your/http_header_check.nasl
```
#### Bước 3: Triển khai và Quét với GVM
Khi script đã chạy đúng từ dòng lệnh, có thể thêm nó vào GVM để sử dụng trong các phiên quét tự động.
1. **Sao chép script vào thư mục plugins**:
```bash
sudo cp /path/to/your/http_header_check.nasl /var/lib/openvas/plugins/
```
2. **Cập nhật GVM để nhận script mới**: Cách đảm bảo nhất là khởi động lại dịch vụ `gvmd`.
```bash
sudo systemctl restart gvmd
```
Hãy đợi khoảng một phút để dịch vụ khởi động lại hoàn toàn.
3. **Sử dụng trong Giao diện Web (GSA)**:
* Đăng nhập vào GSA.
* Tạo một **Scan Config** mới (hoặc sao chép một cái có sẵn). Tìm NVT bằng OID **`100011`** hoặc tên **`Check for Sensitive Information in HTTP Headers`** và đảm bảo nó được kích hoạt trong cấu hình.
* Tạo một **Task** mới.
* **Target**: Nhập IP của máy chủ web muốn quét (ví dụ: `127.0.0.1`).
* **Scan Config**: Chọn cấu hình vừa tạo ở trên.
* Chạy Task và xem kết quả báo cáo. Báo cáo sẽ hiển thị một lỗ hổng mức độ "Note" nếu nó tìm thấy các header nhạy cảm.
### Tài liệu tham khảo
* **Greenbone Community Forum**:
* [https://community.greenbone.net/](https://community.greenbone.net/)
* **NASL Reference Guide (Cũ nhưng hữu ích)**:
* [The Nessus Attack Scripting Language Reference Guide](https://docslib.org/doc/13863270/The-Nessus-Attack-Scripting-Language-Reference-Guide)
* **Kho NVT chính thức**:
* [https://github.com/greenbone/nvt-feed](https://www.google.com/search?q=https://github.com/greenbone/nvt-feed)