Advertisement

Responsive Advertisement

Advent of Cyber 3 (2021) - Day 7

 Task 12  [Day 7] Web Exploitation Migration Without Security

Nhóm phát triển xử lý các yêu cầu quà tặng từ Trẻ em đã chuyển sang công nghệ mới. Khi làm như vậy, họ đã để ứng dụng của mình dễ bị tấn công và Grinch Enterprises hiện kiểm soát quyền truy cập vào hệ thống. May mắn thay, doanh nghiệp Grinch đã quên vá hệ thống để bạn có thể sử dụng cùng một lỗ hổng để lấy các yêu cầu quà tặng cho học sinh.



Mục tiêu học tập

  • NoSQL là gì?
  • Hiểu cơ sở dữ liệu NoSQL
  • Hiểu tại sao NoSQL xảy ra
  • Hiểu tiêm NoSQL là gì
  • Sử dụng NoSQL Injection để bỏ qua biểu mẫu đăng nhập

NoSQL là gì

Cơ sở dữ liệu NoSQL đề cập đến cơ sở dữ liệu không quan hệ, viết tắt của non SQL và Not only SQL. Nó là một hệ thống lưu trữ dữ liệu và truy xuất dữ liệu. Cơ sở dữ liệu NoSQL ngày nay được sử dụng phổ biến cho các thiết bị Dữ liệu lớn và IoT do các tính năng mạnh mẽ của chúng như truy vấn nhanh, dễ sử dụng cho các nhà phát triển, mở rộng quy mô dễ dàng và cấu trúc dữ liệu linh hoạt.

Hôm nay, chúng ta sẽ trình bày các khái niệm cơ bản về cơ sở dữ liệu NoSQL và thu thập thông tin, liệt kê và khai thác các lỗ hổng NoSQL.

Hiểu NoSQL

Có thể bao gồm nhiều loại cơ sở dữ liệu NoSQL, bao gồm MongoDB, Couchbase, RavenDB, v.v. Tuy nhiên, trong nhiệm vụ này, chúng ta sẽ tập trung vào cơ sở dữ liệu MongoDB, một cơ sở dữ liệu NoSQL lưu trữ tài liệu miễn phí và phổ biến.

Tương tự như cơ sở dữ liệu quan hệ (chẳng hạn như MySQL và MSSQL), MongoDB bao gồm cơ sở dữ liệu, bảng, trường nhưng với các tên khác nhau.

  • Collections tương tự như các bảng hoặc dạng xem trong MySQL và MSSQL.
  • Documents tương tự như các hàng hoặc bản ghi trong MySQL và MSSQL.
  • Fields tương tự như các cột trong MySQL và MSSQL.

Biểu đồ sau đây cho thấy một ví dụ trực quan về các thuật ngữ này vì chúng ta có một cơ sở dữ liệu tên là AoC3 có hai bộ sưu tập: người dùng, vai trò. Bộ sưu tập người dùng có hai tài liệu (2 bản ghi). Tài liệu trong MongoDB là các đối tượng được lưu trữ ở định dạng gọi là BSON, hỗ trợ các kiểu dữ liệu JSON để lưu trữ tài liệu.


Ngoài ra, sẽ hữu ích khi xem nhanh và so sánh các toán tử truy vấn giữa MongoDB và MySQL:

  • $and tương tự AND trong MySQL
  • $or tương tự OR trong MySQL
  • $eq tương tự  = trong MySQL

Tương tác với máy chủ MongoDB

Chú ýĐể theo dõi quá trình tương tác với máy chủ MongoDB, vui lòng triển khai máy được đính kèm và sử dụng AttackBox hoặc kết nối với VPN để đăng nhập vào máy chủ SSH. Sử dụng thông tin đăng nhập sau:thm:tryhackme.

Terminal
user@machine$ ssh thm@MACHINE_IP -p 2222

Trước khi chúng ta đi sâu vào chi tiết của NoSQL injection, điều quan trọng là phải hiểu cách MongoDB hoạt động theo nghĩa chung. Hãy bắt đầu với việc kết nối với MongoDB trên máy mục tiêu đã triển khai của chúng tôi bằng cách sử dụng cổng mặc định 27017. Chúng tôi sẽ tạo cơ sở dữ liệu mới và các bộ sưu tập cũng như tài liệu.

MongoDB
user@machine$ mongo
connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("1273eab2-4dae-42a8-8f67-a133b870872b") }
MongoDB server version: 4.4.10

Bây giờ, hãy sử dụng lệnh show để liệt kê tất cả các cơ sở dữ liệu mà chúng ta có trong MongoDB trên máy mục tiêu của chúng ta:

MongoDB
> show databases
admin     0.000GB
config    0.000GB
local     0.000GB
logindb   0.000GB
thm-test  0.000GB
thmdb     0.000GB

Tiếp theo, nếu chúng ta muốn kết nối với một cơ sở dữ liệu, chúng ta có thể thực hiện việc này bằng cách sử dụng lệnh use. Tuy nhiên, chúng tôi cũng sẽ hướng dẫn cách tạo cơ sở dữ liệu mới với các bộ sưu tập và dữ liệu. Để tạo một cơ sở dữ liệu mới, chúng ta cũng sử dụng lệnh sử dụng tương tự để tạo và kết nối với nó. Do đó, lệnh sử dụng được sử dụng để kết nối với cơ sở dữ liệu nếu nó tồn tại hoặc tạo một cơ sở dữ liệu mới nếu nó không tồn tại. Khi cơ sở dữ liệu được tạo, chúng ta có thể tạo hai bộ sưu tập mới, người dùng và vai trò được đặt tên bằng cách sử dụng hàm db.createCollection(), sau đó hiển thị tất cả các bộ sưu tập có sẵn trong cơ sở dữ liệu.

MongoDB
> use AoC3
switched to db AoC3
> db.createCollection("users")
{ "ok" : 1 }
> db.createCollection("roles")
{ "ok" : 1 }
> db.getCollectionNames();
[ "roles", "users" ]

Tiếp theo, chúng tôi tạo một tài liệu trong bộ sưu tập người dùng và chèn dữ liệu vào đó.

MongoDB
> db.users.insert({id:"1", username: "admin", email: "admin@thm.labs", password: "idk2021!"})
WriteResult({ "nInserted" : 1 })
> db.users.insert({id:"2", username: "user", email: "user@thm.labs", password: "password1!"})
WriteResult({ "nInserted" : 1 })
>
> db.users.find()
{ "_id" : ObjectId("6183dc871ebe3f0c4b779a31"), "id" : "1", "username" : "admin", "email" : "admin@thm.labs", "password" : "idk2021!" }
{ "_id" : ObjectId("6183dc911ebe3f0c4b779a32"), "id" : "2", "username" : "user", "email" : "user@thm.labs", "password" : "password1!" }

Chúng tôi đã tạo thành công hai tài liệu vào bộ sưu tập của người dùng và sau đó hiển thị các tài liệu có sẵn trong bộ sưu tập bằng cách sử dụng db.users.find (). Lưu ý rằng MongoDB tự động tạo một ID duy nhất được gọi là _id cho mỗi tài liệu trong bộ sưu tập từ đầu ra ở trên. Hãy cũng cố gắng cập nhật tài liệu cũng như xóa nó bằng các lệnh MongoDB. Chúng tôi sẽ sử dụng hàm db. <collection> .update để cập nhật tài liệu với id = 2 và cập nhật tên người dùng thành tryhackme và cuối cùng hiển thị tất cả tài liệu để đảm bảo tài liệu của chúng tôi được cập nhật.

MongoDB
> db.users.update({id:"2"}, {$set: {username: "tryhackme"}});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.users.find()
{ "_id" : ObjectId("6183dc871ebe3f0c4b779a31"), "id" : "1", "username" : "admin", "email" : "admin@thm.labs", "password" : "idk2021!" }
{ "_id" : ObjectId("6183dc911ebe3f0c4b779a32"), "id" : "2", "username" : "tryhackme", "email" : "user@thm.labs", "password" : "password1!" }

Cuối cùng, hãy xóa tài liệu bằng cách sử dụng db.users.remove() và sau đó thả db.users.drop() vào bộ sưu tập như sau,

MongoDB
> db.users.remove({'id':'2'})
WriteResult({ "nRemoved" : 1 })
> db.users.find()
{ "_id" : ObjectId("6183dc871ebe3f0c4b779a31"), "id" : "1", "username" : "admin", "email" : "admin@thm.labs", "password" : "idk2021!" }
> db.users.drop()
true

Bây giờ chúng ta đã biết cách tương tác với máy chủ MongoDB, hãy quan sát xung quanh bằng cách sử dụng các lệnh MongoDB mà chúng ta đã học và tìm cờ để trả lời Câu hỏi 1!

NoSQL Injection là gì?

Bây giờ chúng ta đã có kiến thức cơ bản về cách xử lý các lệnh MongoDB để tạo cơ sở dữ liệu và bộ sưu tập cũng như chèn, cập nhật và xóa tài liệu, chúng ta sẽ thảo luận về việc tiêm NoSQL và các rủi ro khi có lỗ hổng bảo mật như vậy trong ứng dụng. NoSQL injection là một lỗ hổng bảo mật web cho phép kẻ tấn công có quyền kiểm soát cơ sở dữ liệu. Việc đưa vào NoSQL xảy ra bằng cách gửi các truy vấn thông qua đầu vào ứng dụng web không đáng tin cậy và chưa được lọc, dẫn đến thông tin trái phép bị rò rỉ. Ngoài ra, kẻ tấn công có thể sử dụng NoSQL injection để thực hiện các hoạt động khác nhau như sửa đổi dữ liệu, nâng cấp đặc quyền, tấn công DoS và các hoạt động khác.

Bỏ qua các trang đăng nhập!

Logic của các trang đăng nhập là tương tự trong hầu hết các cơ sở dữ liệu: đầu tiên, kết nối với cơ sở dữ liệu và sau đó tìm tên người dùng và mật khẩu nhất định; nếu chúng tồn tại trong bộ sưu tập (trong cơ sở dữ liệu), thì chúng ta có một mục nhập hợp lệ. Sau đây là truy vấn được sử dụng trong các ứng dụng web được sử dụng trên trang đăng nhập của chúng tôi: hàm db.users.find({query}) hoặc db.users.findOne(query) trong đó query là dữ liệu JSON được gửi qua ứng dụng: {"username": "admin", "password": "adminpass"}. Lưu ý rằng khi chúng tôi cung cấp thông tin đăng nhập chính xác, một tài liệu sẽ trả về, trong khi nhận được trả lời rỗng khi cung cấp thông tin đăng nhập sai khi không có thông tin nào khớp!

MongoDB
> db.users.findOne({username: "admin", password: "adminpass"})
{
        "_id" : ObjectId("6183ef6292dea43d75f0c820"),
        "id" : "1",
        "username" : "admin",
        "email" : "admin@thm.labs",
        "password" : "adminpass"
}
> db.users.findOne({username: "admin", password: "adminpasss"})
null

Trước khi khai thác NoSQL injection, có những toán tử MongoDB mà chúng ta cần làm quen được sử dụng nhiều trong việc đưa vào, đó là:

$eq - khớp các bản ghi bằng một giá trị nhất định

$ne khớp các bản ghi không bằng một giá trị nhất định

$gt - khớp các bản ghi lớn hơn một giá trị nhất định.

$where - khớp các bản ghi dựa trên điều kiện Javascript

$exists - khớp các bản ghi có một trường nhất định

$regex - khớp các bản ghi đáp ứng các biểu thức chính quy nhất định.

Truy cập MongoDB website để biết thêm thông tin về các nhà khai thác MongoDB. Tiếp theo, chúng tôi sẽ khai thác logic của truy vấn đăng nhập bằng cách chèn một đối tượng JSON bao gồm một trong các toán tử NoSQL, đó là $ne

MongoDB
> db.users.findOne({username: "admin", password: {"$ne":"xyz"}})
{
        "_id" : ObjectId("6183ef6292dea43d75f0c820"),
        "id" : "1",
        "username" : "admin",
        "email" : "admin@thm.labs",
        "password" : "adminpass"
}

Chúng ta đưa  ra JSON {"$ne": "XYZ"}  trong trường mật khẩu và chúng tôi đã thay đổi logic thành như sau:

  • Chúng tôi đang yêu cầu MongoDB tìm một tài liệu (người dùng) có tên người dùng bằng admin và mật khẩu thay bằng xyz, điều này biến câu lệnh này thành TRUE vì mật khẩu của quản trị viên không phải là xyz.

Kết quả là chúng tôi đã truy xuất thành công tài liệu từ MongoDB vì logic của câu lệnh của chúng tôi là đúng. Bằng cách áp dụng khái niệm này đối với trang đăng nhập của ứng dụng web, chúng tôi sẽ có thể bỏ qua trang đăng nhập.

Bây giờ, giả sử chúng ta có muốn đăng nhập vào hệ thống với tư cách người dùng khác không phải là quản trị viên hay không. Trong trường hợp này, chúng tôi cũng có thể đưa vào trường tên người dùng như sau,

MongoDB
> db.users.findOne({username:{"$ne":"admin"},password:{"$ne":"xyz"}})
{
        "_id" : ObjectId("6183ef5b92dea43d75f0c81f"),
        "id" : "2",
        "username" : "user",
        "email" : "user@thm.labs",
        "password" : "password1!"
}

Nếu đây là một trang đăng nhập, chúng tôi sẽ đăng nhập với tư cách không phải là quản trị viên, mà là người dùng. Chúng tôi đã chèn hai đối tượng JSON vào tên người dùng cũng như các trường mật khẩu: chúng tôi đang yêu cầu MongoDB tìm một tài liệu mà tên người dùng của nó không bằng admin và mật khẩu của nó không bằng xyz, điều này trả về câu lệnh là true.

Khai thác NoSQL injection

Để khai thác NoSQL injection trong ứng dụng web, trước tiên, bạn cần tìm một điểm nhập không khử trùng đầu vào của người dùng. Tiếp theo, bạn cần hiểu cách ứng dụng web chuyển yêu cầu đến cơ sở dữ liệu! Khi bạn tìm thấy một điểm vào, các truy vấn vượt qua có thể khác nhau. Đôi khi, ứng dụng web chấp nhận đầu vào của người dùng thông qua truy vấn GET hoặc POST và đôi khi ứng dụng web chấp nhận đối tượng JSON, như trường hợp của các API.

Chèn một truy vấn NoSQL có các dạng khác nhau nếu chúng ta xử lý các truy vấn GET hoặc POST với các đối tượng JSON nhưng vẫn có cùng một khái niệm. Hãy thảo luận về cách đưa vào các yêu cầu GET hoặc POST thông thường. Để tương tác với MongoDB qua GET hoặc POST bằng cách chèn một mảng toán tử MongoDB để khớp với phản đối JSON để khớp với Khóa: Giá trị. Sau đây là một ví dụ về cách đưa vào qua URL:

  http://example.thm.labs/search?username=admin&role[$ne]=user

Lưu ý rằng chúng tôi đưa toán tử MongoDB [$ ne] (không bằng nhau) vào tham số vai trò. Chúng ta cũng có thể sử dụng khái niệm tương tự để chuyển các toán tử MongoDB trong các yêu cầu POST.

Chúng tôi đã xây dựng một ứng dụng web sân chơi để tìm kiếm (những) người dùng với một vai trò cụ thể! Để thực hiện tiêm NoSQL, trước tiên, bạn cần bỏ qua trang đăng nhập, như chúng ta đã thảo luận trong phần trước.

Hãy xem trường hợp bình thường mà chúng ta tìm kiếm tên người dùng ngang bằng với vai trò người dùng.

  http://example.thm.labs/search?username=ben&role=user

Do đó, ứng dụng web trả về kết quả mong đợi từ MongoDB. Bây giờ chúng ta hãy tiêm MongoDB để cho thấy kết quả bất ngờ! Chúng tôi sẽ cố gắng liệt kê tất cả các tên người dùng có vai trò người dùng!

  http://example.thm.labs/search?username[$ne]=ben&role=user

Kết quả là ứng dụng web sẽ trả về nhiều bản ghi từ MongoDB thỏa mãn truy vấn. Đó là thời gian thực hành; bây giờ hãy đảm bảo rằng bạn đã triển khai máy đính kèm và AttackBox (để sử dụng Burp), cố gắng liệt kê tất cả các tên người dùng có vai trò khách. Tìm lá cờ và trả lời câu hỏi số 2 bên dưới

Bạn có thể truy cập và truy cập trang web qua đường dẫn sau: http://LAB_WEB_URL.p.thmlabs.com hoặc http: // MACHINE_IP trong trường hợp bạn đang sử dụng AttackBox.


Tài nguyên bổ sung
Bạn có thể tìm hiểu ở SQL injection và Command Injection trên TryHackMe.

Thực hiện deploy máy victim khai thác MongoDB


Answer the questions below


Interact with the MongoDB server to find the flag. What is the flag?

We discussed how to bypass login pages as an admin. Can you log into the application that Grinch Enterprise controls as admin and retrieve the flag?

Use the knowledge given in AoC3 day 4 to setup and run Burp Suite proxy to intercept the HTTP request for the login page. Then modify the POST parameter.

Phần này sử dụng burpsuit để tìm ra mật khẩu admin và lấy cờ


Once you are logged in, use the gift search page to list all usernames that have guest roles. What is the flag?

Thực hiện ở phần ô search thực hiện bắt request và chỉnh sửa như sau


Sau khi forward sẽ thu được cờ



Use the gift search page to perform NoSQL injection and retrieve the mcskidy record. What is the details record?

Tiếp theo thực hiện search với user mcskidy và chỉnh sửa burpsuit


Sau khi forwad sẽ thu được cờ cuối



Post a Comment

0 Comments