Thiết Lập Cho xp_cmdshell

Vũ Huy Tâm

SQL Server là hệ quản trị dữ liệu, khả năng chính của nó là lưu trữ và truy xuất dữ liệu. Tuy nhiên đôi lúc bạn cần thực hiện một số thao tác của windows từ SQL Server, ví dụ khi bạn cần viết sql script để copy file từ folder này sang folder khác; hoặc tự động restore từ file backup mới nhất dựa theo ngày tạo (tên file không biết trước). SQL Server cung cấp thủ tục xp_cmdshell trong master database để làm việc này.
Để có thể gọi đến xp_cmdshell đòi hỏi một vài bước thiết lập.
Nếu bạn là DBA với quyền sysadmin, bạn cần cấu hình lại server để bật xp_cmdshell (khi SQL Server mới cài đặt tính năng này bị tắt):

EXEC SP_CONFIGURE 'show advanced option', 1
RECONFIGURE
GO
EXEC SP_CONFIGURE 'xp_cmdshell', 1
RECONFIGURE
GO

Sau đó, với quyền sysadmin bạn có thể dùng xp_cmdshell:

EXEC xp_cmdshell 'dir c:\'

Với sysadmin như vậy là xong. Nhưng nếu một người khác (giả sử với sql login là xeko) không có quyền sysadmin mà đăng nhập vào và thử xp_cmdshell, kể cả sau khi bạn đã cấu hình lại server hệ thống vẫn tiếp tục báo lỗi. Có hai vấn đề bạn cần giải quyết.
Thứ nhất, đây là một tác vụ nằm ngoài SQL Server, vì thế mỗi khi có yêu cầu như vậy SQL Server sẽ cần tạo 1 tiến trình trong window để window thực hiện. Tiến trình này cần một window account để có thể chạy, vậy là account nào? Nếu bạn là sysadmin, SQL Server sẽ lấy luôn account đang chạy SQL Service. Nhưng với một non-sysadmin như xeko, SQL Server không đủ tin tưởng để dùng account đó, và như vậy là không có account nào, tất nhiên window sẽ từ chối thực hiện. Để lấp vào khoảng trống đó, bạn cần tạo một proxy account và ánh xạ đến một window account thực, để chỉ thị cho SQL Server khi chạy xp_cmdshell hãy lôi account này ra dùng:

EXEC sp_xp_cmdshell_proxy_account 'WinDomain\nobita','password' --thay bằng domain account và password thật

Sau khi chạy lệnh trên, trong Management Studio nếu bạn mở rộng node Security/Credentials, bạn sẽ thấy một dòng ##xp_cmdshell_proxy_account##.
Thứ hai, bạn phải cấp quyền thực hiện thủ tục xp_cmdshell cho xeko:

USE master
GO
--Tạo user xeko trong master database nếu chưa có
CREATE USER xeko FROM LOGIN xeko WITH default_schema = dbo
GO
GRANT EXECUTE ON xp_cmdshell TO xeko

Và từ đó xeko có thể chạy xp_cmdshell. Một vài lưu ý sau cùng:

  • Bạn có thể truyền tham số cho xp_cmdshell như một thủ tục thông thường:
    DECLARE @cmd VARCHAR(100), @drive CHAR(2)
    SET @drive = 'C:'
    SET @cmd = 'dir '+@drive
    EXEC xp_cmdshell @cmd
  • Các lệnh bạn chạy trong xp_cmdshell đều được thực hiện bằng account Windomain\nobita và tuân theo quyền hạn của account này. Ví dụ nếu nobita không có quyền ghi lên ổ D, lệnh sau sẽ trả về thông báo không thực hiện được:
    EXEC xp_cmdshell 'copy C:\file.txt D:\'
  • xp_cmdshell tạo ra một lỗ hổng về bảo mật, theo đó hacker nếu chiếm được quyền vào SQL Server và thực hiện xp_cmdshell (tất nhiên phải thông qua một login có quyền exec xp_cmdshell như xeko) có thể tiếp tục phá hoại hoặc đánh cắp dữ liệu nằm ngoài SQL Server. Đây là một đe dọa đáng kể bạn cần lưu ý và cân nhắc giữa sự tiện lợi và an ninh hệ thống. Bạn có thể giảm bớt nguy cơ này bằng cách chỉ bật xp_cmdshell trên các SQL Server không tương tác trực tiếp với web server, và hạn chế tối đa quyền trên mạng cho Windomain\nobita.



  • Tags:

2 Comments
Posted on 14/3/2014 | Categories: Bảo mật, Database Administration, Uncategorized

Các bài viết tương tự

Comments
  • Nguyễn Quốc Bộ (16/04/2014 2:34 am)

    Dear Anh Tâm
    Em có một vướng mắc nhỏ mong được anh và mọi người ở đây giúp đỡ như sau :
    Em có hai bảng : bảng lưu các loại lỗi sản phẩm “loisanpham(maloi,tenloi)” và bảng ghi dữ liệu chi tiết các loại lỗi xảy ra đối với từng máy sản xuất theo ngày “thongkeloi (ID,tenmayloi,maloi,ngayloi,soluongloi),mỗi bản ghi trong bảng thongkeloi được xem là 1 lần xảy ra lỗi,các lỗi k xảy ra thì không insert vào đây.

    maloi : mã lỗi
    tenloi : tên lỗi như sước bề mặt,vỡ..
    tenmayloi : tên máy lỗi như máy cắt số 1, máy cắt số 2…
    ngayloi: ngày lỗi như 14/04/2014

    Yêu cầu đặt ra như sau : Thống kê từng loại lỗi theo máy,theo ngày theo mẫu sau,các lỗi không xảy ra cũng thông kê kết quả là 0 :

    tenmayloi tenloi solanloi
    Máy cắt số 1——lỗi bề mặt—–5
    Máy cắt số 1——Vỡ————–0
    Máy cắt số 2——lỗi bề mặt—- 0
    Máy cắt số 3——Vỡ————–10

    Mọi người hướng dẫn em viết câu query với ạ

    Thanks !

  • Map Network Driver phục vụ Backup dữ liệu tự động (01/07/2014 2:48 am)

    Chào anh.
    Em có 1 máy bàn cài SQL Server 2008 R2, Win7 và database A lưu trên máy này.
    Bây giờ em muốn tạo full backup database A (lúc 1h sáng) sang 1 server khác. Server này đã lên Domain.
    Cấu hình SQL server em để Log on as: NetworkService.
    Hiện tại em không thể Map Network drive để SQL Server có thể nhận được ổ đĩa mạng phục vụ việc backup được.
    Mong anh hướng dẫn em cách Map Network Drive khi server lên domain anh nhé.
    Cảm ơn anh.

Leave a Reply

Hướng dẫn: Để nhập mã T-SQL bạn dùng thẻ <pre lang="tsql"> và </pre>.
Ví dụ: <pre lang="tsql">SELECT * FROM MyTable</pre>