01/10/2018, 17:01

Hỏi về cách chống phá hoại javascript

Em xin chào mọi người

Em đang nghịch cái asp , chuyện là em có làm các hàm javascript để thực hiện 1 số công việc phục vụ chính cho ajax ( cụ thể là thêm xóa sửa giỏ hàng ) , chuyện không có gì cho tới khi em vô tình xem được 1 bài viết khi nói về js, khi em tạo hàm chạy trên web , người phá hoại hoàn toàn có thể dùng các hàm này để phá rối web , đây là ví dụ điển hình của em ạ :

Đầu tiên em làm thêm xóa sửa gộp vô chung cái hàm , em lấy ví dụ là hàm sửa :

function CatNhapGioHang(maSP, soLuong, tenSP, Loai) {
    //Loại == 1 : Sửa
    if (Loai == 1) {
        $.ajax({
            url: '/Cart/SuaGioHang',
            type: 'POST',
            data: JSON.stringify({ 'MaSP': maSP, 'SoLuong': soLuong }),
            dataType: 'json',
            contentType: 'application/json; charset=utf-8',
            success: function (data) {
                if (data == "true") {
                    Reload();
                }
            },
            error: function () {
            }
        });  

Em cho web chạy lên và gọi hàm này từ cửa sổ console của trình duyệt :

Và kết quả là em ăn hành sml :

Cho em hỏi những trường hợp thế này em phải giải quyết thế nào ạ?
Em xin chân thành cảm ơn ạ

Đào An viết 19:14 ngày 01/10/2018
  1. Làm rối (obfuscation) javascript. https://stackoverflow.com/questions/194397/how-can-i-obfuscate-protect-javascript
  2. Validation trên server.
*grab popcorn* viết 19:02 ngày 01/10/2018

Bạn phải kiểm tra quyền hạn của user trước khi thực thi function của bạn.
Xem ai được phép xóa sửa, ai thì không.

Bước này gọi là authorization

Nguyễn Văn Vương viết 19:12 ngày 01/10/2018

Nếu có sai sót thì bỏ qua cho em vì em rất giốt tiếng anh, em tìm hiểu thì cũng có 1 số tool hỗ trợ việc này nhưng trên stackoverflow họ cũng cảnh báo dùng cách em tạm hiểu là " Làm rối" này cũng tự làm khó coder , khiến việc debug trở nên khó khăn hơn , việc này có thực sự ảnh hưởng nhiều không ạ ?
Em có Validation đó chứ ạ , nhưng em muốn hỏi thử xem có cách nào kiểu kiểu như giấu luôn cái script không ấy mà . Em cũng có tìm hiểu qua nhưng gần như kết quả trả về là bất khả thi vì trình duyệt sẽ load script về để chạy ( theo em hiểu là vậy )

Em cảm ơn bác nhiều ạ

Lam Pham viết 19:10 ngày 01/10/2018

Nếu người khác gọi được hàm của bạn ở console của trình duyệt, thì có nghĩa là hàm đó có phạm vi toàn cục (global scope).

Vì vậy, để ngăn chặn thì bạn chỉ cần đưa tất cả hàm và biến của bạn khỏi global scope, bằng cách sử dụng IFFE.

Ví dụ như sau:

(()=>{
  function sayHi() {
    console.log("Hi!!!");
  }
})()

sayHi(); // => ReferenceError: sayHi is not defined

Không biết câu trả lời này có đúng với ý của bạn không?

Nguyễn Văn Vương viết 19:04 ngày 01/10/2018

dạ em có authorization ạ , cụ thể là ở những chức năng k cần đăng nhập ( như mua hàng ) thì em tạm bỏ qua , còn chức năng nào cần đăng nhập thì em làm như sau :

  1. Khi đăng nhập em sẽ lưu 1 thứ em gọi là token này vào cookie và cơ sở dữ liệu
  2. Mỗi khi thực hiện lệnh thêm/xóa/sửa em đều lấy cookie này lên để kiểm tra so sánh với sever , so sánh được thì em thực hiện chức năng .
    Nhưng em cảm thấy việc này không hay lắm vì lần nào cũng phải validate với sever cả, em nghĩ mà ví dụ như em test 1, 2 cái request thì không sao nhưng nếu về sau giả vờ có cả hàng ngàn request thì việc này liệu có dẫn tới bị chậm không ạ ?

Trên đây là thắc mắc của em mong được bác giải đáp ạ .
Em xin chân thành cảm ơn

Người bị bơ viết 19:14 ngày 01/10/2018

Bạn có giấu thì hay làm rối code khi thực hiện 1 request thì mình vẫn có thể bật tab Network trong chrome và theo dỏi (xhr). Validate vẫn tốt hơn : )

Đào An viết 19:08 ngày 01/10/2018

Bạn có thể code mọi thứ chạy xong xuôi, thì mới “làm rối” nên ko ảnh hưởng đến quá trình code đâu.
Cơ mà dù có “làm rối” thì cao thủ cũng gỡ rối đc hết . Tốt nhất validation trên server là đc, ở client thì kệ xác chúng nó, muốn sửa gì thì sửa thôi.

Nguyễn Văn Vương viết 19:01 ngày 01/10/2018

(()=>{

Bác cho em hỏi thêm vì JS em lưu ở 1 file riêng và vì 1 hàm em phải nhai đi nhai lại nhiều lần ở nhiều trang , nếu đưa nó thành cục bộ thì em đâu thể dùng ở nhiều trang phải không ạ ?

Nguyễn Văn Vương viết 19:06 ngày 01/10/2018

Vâng em nghĩ 1 chiều quá , em cảm ơn bác đã chỉ dạy ạ .

Nguyễn Văn Vương viết 19:07 ngày 01/10/2018

vâng ạ , cho em hỏi thêm như vậy em phải validate tới 2 lần cả ở client lẫn sever phải không ạ ?
Tại client em validate để chắc chắn người dùng phổ thông không nhập sai .
Tại sever để cố gắng chống lại “thế lực bóng tối”
em nghĩ vậy có đúng với thực tế không ạ , lúc đầu làm thì em cứ làm theo video hướng dẫn thôi , lúc sau em xem lại thì thấy nhiều thứ phải xem lại quá

Đào An viết 19:11 ngày 01/10/2018

Đúng rồi đó bạn, validate ở client để giảm tải request đến server nữa.
Còn ko thì bạn có thể validate ở mỗi server không cũng đc à.

Nguyễn Văn Vương viết 19:01 ngày 01/10/2018

Dạ thôi tại em đang học không phải làm nên cố gắng tý ạ
Em cảm ơn bác nhiều ạ

null viết 19:10 ngày 01/10/2018

Kiểm tra auth và validate là bắt buộc rồi, chỉ cần dùng session để lấy thông tin người dùng hiện tại.
Token mã hoá thông tin cilent+auth, lưu vào cookie và database để tự đăng nhập lại khi session hết hạn.
Tất cả quyền truy cập sẽ được lưu vào cache hoặc một file nào đó, gọi là access control lists. Nó phải được cập nhật khi phân quyền bị thay đổi. Khi bạn kiểm tra quyền thêm sửa xoá là bạn kiểm tra session với acl chứ không nên với database.

Bình thường không ai đi đọc script và dùng script của bạn để phá cả, người ta sẽ theo dõi network để lấy request luôn, sau đó lặp lại nó là xong.
Kiểu tấn công này gọi là csrf. Để chống lại nó, trong form data của bạn phải có một field luôn thay đổi mà bạn kiểm tra được.
Có thể tạo ngẫu nhiên một cặp key+value mã hoá mỗi khi tạo form, lưu vào session. Sau đó kiểm tra key với value khi người dùng gửi request.
Nếu dùng ajax thì sau khi kết thúc request, nhớ kèm theo key mới trong response được trả về.

Nguyễn Văn Vương viết 19:13 ngày 01/10/2018

Dạ xin phép bác cho em hỏi thêm 1 chút ạ :
Trước em có tìm hiểu session, cookie và local storage thì em thấy cái nào cũng có cái giở của nó và không cái nào mang tính toàn vẹn , em thắc mắc nếu em lưu phân quyền vô cookie thì nếu nó bị đánh cắp thì rủi ro có phải sẽ cao hơn không ạ . Hiện tại em đang làm theo kiểu để sever gồng gánh , nghĩa là mỗi khi chuyển trang hay làm mới trang thì em đều validate cookie với server, em biết thế là tội cho cái server nhưng với trình độ hiện tại em chưa nghĩ ra được cách nào hơn cả , mong bác chỉ bảo .
Em có nghĩ tới việc dùng google captcha để validate form coi như là một key nhưng em không cài được trên local host để test , em có nghĩ tới việc cho sinh số ngẫu nhiên từ 1000-9999 rồi rùng nó để validate nhưng em vẫn đang tìm hiểu cách hay hơn ạ .
Cuối cùng em xin chân thành cảm ơn bác đã chỉ bảo , em sẽ tìm hiểu và cải thiện ạ.

null viết 19:07 ngày 01/10/2018

Không lưu phân quyền vô cookie, chỉ nên sử dụng cookie cho việc đăng nhập lại sau khi session hết hạn.
Không nên dùng captcha để bảo mật form. Đúng là có tác dụng thật, nhưng sẽ gây phiền phức cho người dùng.

Mình sẽ ví dụ cho bạn mẫu mình hay dùng, mẫu này đã được tối giản để bạn dễ theo dõi.

Database

  • Roles: id, name
    Dùng để chia cấp bậc như Admin, Manager, Member.
  • Users: id, id_role, username, password
    Thông tin người dùng.
  • RememberTokens: id_user, token, user_agent
    Lưu token sau khi đăng nhập thành công.
  • Permissions: id_role, controller, action
    Xác định quyền theo cấp bậc.

Đăng nhập lần đầu

Khi người dùng đăng nhập thành công, bạn lấy username + password + user_agent(thông tin trình duyệt) và mã hóa chúng để tạo token, có thể dùng md5 để mã hóa.
Lưu vào cookie id_usertoken vừa tạo. Đồng thời cũng ghi vào RememberTokens.

Tạo session auth chứa id_userid_role.

Phân quyền bằng ACL

ACL có thể lưu trong cache là tốt nhất, nếu không được thì lưu thành file, dù sao vẫn sẽ tốt hơn truy cập vào database.
Khi chưa có ACL thì bạn truy cập Permissions để lấy và tạo ACL chứa toàn bộ dữ liệu của nó. Ví dụ thế này:

  admin|products|seach
  admin|products|create
  admin|products|update
  admin|products|delete

manager|products|seach
manager|products|create
manager|products|update

 member|products|seach

Khi người dùng thực hiện thao tác nào đó ta sẽ có được controlleraction, thêm id_role trong session nữa là đủ để bạn so sánh với ACL. Nếu không tồn tại trong ACL thì cấm hết.

Đăng nhập trở lại bằng cookie

Session hết hạn, và cookie vẫn còn.
Lấy id_user từ cookie, kiểm tra tồn tại trong Users và lấy được thông tin người dùng.
Dùng usernamepassword vừa lấy, cộng thêm user_agent của trình duyệt hiện tại là bạn tạo được token.
Kiểm tra token vừa tạo đó với cái đang lưu trong cookie.
Có được tokenid_user rồi thì kiểm tra RememberTokens.

Khi các thông tin đã đúng thì tạo lại session auth.

Đăng xuất

Người dùng đăng xuất thì xóa cookie, session và dữ liệu trong RememberTokens.


Chống CSRF

Tạo chuỗi ngẫu nhiên mỗi khi nhập form, đồng thời ghi vào form nhập liệu của người dùng. Ví dụ: abcXYZ

<input type="hidden" name="token" value="abcXYZ">

Khi người dùng gửi request thì kiểm tra token, đồng thời xóa nó khỏi session.

Ví dụ đơn giản để bạn hình dung, chứ thực tế không nên dùng như vậy. Ngoài token người ta còn tạo thêm session token_time giới hạn thời gian. Còn token thì dùng các hàm băm như bcrypt để mã hóa, bạn sẽ có 2 chuỗi token khác nhau cho session và form, an toàn hơn.

Hiểu nguyên tắc thì có thể viết được, nhưng bạn nên dùng các thư viện đã được nhiều người kiểm chứng. Vừa bảo mật, vừa tránh được vấn đề hiệu suất.

Nguyễn Văn Vương viết 19:07 ngày 01/10/2018

Em cảm ơn bác , bác nhiệt tình quá , em sẽ tham khào và phát triển thêm, cảm ơn bác rất nhiều ạ .

Nguyễn Nhân viết 19:14 ngày 01/10/2018

Bạn dùng chứng thực Authentication Header cho ajax. Hoặc dùng anonymous function.

Bài liên quan
0