Mình đã "hack" trang vi.heroquizz.com như thế nào ?
TIL
633
White

Nguyễn Việt Hưng viết ngày 15/12/2016

Lời nói đầu

Thực sự thì bài viết này chỉ cảnh báo những vấn đề phát sinh khi ta xử lý data ở phía client side chứ không liên quan tới các lỗ hổng bảo mật như XSS, SQL Injection...hay những thứ giống vậy.

Nảy sinh kế hoạch xấu xa

Vào môt buổi tối "đẹp trời" ( ý là hông quá nóng cũng hông quá lạnh :laughing: ) mình có vào thử 1 đường link dẫn tới trang game là heroquizz.com, game cũng khá đơn giản là người bạn của mình sẽ tạo 1 bài test và nhiệm vụ của mình là làm bài test xem mình hiểu người đó tới đâu. Nhưng kết quả sau khi làm bài test của thằng bạn thân thì 9 / 15 wtf ? nên mình nảy ý định "hack" trò này :satisfied:

Bắt đầu nghiên cứu

Vào bài test của một đứa bạn khác, mình không ngần ngại inspect element ngay và kết quả thu được:
alt
Oh quá ngon rồi nó gọi hàm js khi click chuột :laughing: chắc là có cơ hội rồi !
Coi thử hàm AnswerQuestion mặt mũi ra sao nào:
alt
Vừa nhìn vào ý nghĩ đầu tiên hiện ra trong đầu mình: "Đù ! ai code mà xấu thế trời ! code indent gì đây ? " (cuồng code đẹp hehe)
Bỏ qua đống code xấu mình tiến tới phần đẹp nhất của function này đó là cái điều kiện:

if (r != r_good)
{
    $('#r'+q+'_'+r).addClass('ma_bad');
    $('#r'+q+'_'+r+' .my_answer_boolicon').show();
}

Nhìn điều kiện này thì hiểu ngay là nó sẽ so sánh parameter thứ 2 và parameter cuối của function nếu khác nhau thì 1 phần tử nào đó sẽ được add class là "ma_bad" , hừm nghe tên class là biết trước tương lai rồi ! Mình quay sang trả lời sai 1 câu thử class được add là gì và kết quả đúng như dự đoán:
alt
Ngon ! vậy là nó xét câu trả lời đúng và sai như vậy ! nào ta tiếp tục xem thêm phần dưới:

q_current = q_current + 1;
list_data = list_data+q_real+","+r+"|";

if (q_current <= q_total_need)
{
    $('#q'+q).hide();
    $('#after_q'+q).hide();
    ShowNextQuestion(q_current);
}
else
{
    document.location.href='/go/239312866442093/972?r=u421rtthjt&data='+list_data;
}

Đọc sơ qua đã đoán ra được là nó kiểm tra câu hỏi hiện tại là câu số mấy , nếu lớn hơn tổng số câu hỏi trong bài test thì nó sẽ đi tới 1 đường link với data truyền vào được lưu trữ trong biến list_data mà biến list_data sau khi xây dựng có dạng chính nó + parameter thứ 3 + "," + kết quả (thực chất là parameter thứ 4 do kết quả sẽ được so sánh với parameter thứ 4 và nếu đúng thì hắn mới cho vào biến kết quả) + "|"
Như vậy vd trả lời đúng 2 câu thì list_data có dạng (ví dụ thôi không phải lúc nào cũng vậy):

"1,2|2,1|"

Xây dựng mã khai thác

Hừm vậy cứ xem parameter của function mà chọn thôi chứ việc gì phải xây dựng cả code khai thác ? Hihi tính mình cũng khá lười nên cũng muốn mọi việc dễ dàng hơn nên mình bắt tay vào xây dựng 1 script đơn giản để khai thác.

var regexp = /AnswerQuestion\(\d{1,2},\s\d{1,2},\s\d{1,2},\s\d{1,2}\)/g;
var source = $("#inside2").html() + "";
var match, answerArr = [];
var raw = [];
var result = [];
while ((match = regexp.exec(source)) != null) {
    answerArr.push(match[0]);
}
for(var i = 0; i < answerArr.length; i++){
    answerArr[i] = answerArr[i].replace("AnswerQuestion(","").replace(" ","").replace(")","").split(",").slice(2);
}
function buildResult(arr){
    for(var k = 0; k < arr.length; k++){
        result[k] = arr[k].join() + "|";
    }   
}
buildResult(answerArr);
function replaceAll(str,needed, replacement) {
    return str.replace(new RegExp(needed, 'g'), replacement);
};
function unique(arr){
    var u = {}, a = [];
    for(var i = 0; i < arr.length; i++){
        if(u.hasOwnProperty(arr[i])) {
            continue;
        }
        a.push(arr[i]);
        u[arr[i]] = 1;
    }
    return a;
}
function win(link){
    var r = replaceAll(unique(result).join("")," ","");
    document.location.href=link+r;
}

Đoạn code trên có công việc nó sẽ lấy code từ div có id = "inside2" sau đó bóc tách html lấy điều kiện onclick ra bằng cách sử dụng 1 regular expression đơn giản sau đó tách chúng ra và chỉ lấy 2 parameter cuối và rồi join chúng lại với | .Sau đó mình nhận ra là có 2 đáp án tức là có 2 điều kiện onclick thế nên khi lấy như thế thì sẽ có 2 string bị trùng lặp:
alt

Hừm thế thì ta chỉ cần lấy 1 thứ mà thôi hay nói đúng hơn là ta sẽ cần bỏ đi những phần tử bị trùng lặp và chỉ giữ lại 1
thế nên mình thêm hàm unique để lọc các phần tử trùng lặp đồng thời thêm hàm replace all để lọc khoảng trắng giữ dấu , và đáp án !

sau đó ta build ra được đoạn string hoàn chỉnh:
alt
Giờ làm gì nữa ? coi cô dâu 8 tuổi thôi ! Hhihi đùa chút cho bớt căng thẳng nãy giờ đọc bài :joy:
Tất nhiên giờ ta sẽ thử send đoạn string ta build được tới file xử lý và xem kết quả ra sao ! nhưng tiếc là đoạn file xử lý biến đổi không ngừng nên chỉ có thể paste = tay thế nên hàm win ra đời, well đỡ hơn là bấm từng câu hehe.
alt
Thành công rực rỡ :satisfied:
alt

Bài viết tới đây thôi, bug này vẫn chưa được fix nên mọi người có thể dùng để chơi thoải mái nhé hihi.

Nguyễn Việt Hưng 15-12-2016

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

Nguyễn Việt Hưng

1 bài viết.
0 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Bài viết liên quan
White
0 2
fCC: Technical Documentation Page note So I have finished the HTML part of this exercise and I want to come here to lament about the lengthy HTML ...
HungHayHo viết 5 tháng trước
0 2
White
20 1
Toán tử XOR có tính chất: + A XOR A = 0 + 0 XOR A = A Với tính chất này, có thể cài đặt bài toán sau với độ phức tạp O(N) về runtime, và với O(1)...
kiennt viết 2 năm trước
20 1
White
9 0
Có một tuyên ngôn cho chủ nghĩa tối giản trong ngành phần mềm. Link: http://minifesto.org/ Fight for Pareto's law, look for the 20% of effort th...
Cẩm Huỳnh viết 2 tháng trước
9 0
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
1 bài viết.
0 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!