Hướng dẫn dùng boxes py python

Create boxes and more with a laser cutter!

Boxes.py is an Open Source box generator written in Python. It features both finished parametrized generators as well as a Python API for writing your own. It features finger and (flat) dovetail joints, flex cuts, holes and slots for screws, hinges, gears, pulleys and much more.

Khoảng mười năm sau câu hỏi ban đầu, Python 3.8.0 đi kèm với việc kiểm tra . Nó có thể giúp được gì không? Hãy giới hạn cuộc thảo luận thành việc ghi trên ổ cứng để đơn giản hơn - và xem:

from sys import addaudithook
def block_mischief(event,arg):
    if 'WRITE_LOCK' in globals() and ((event=='open' and arg[1]!='r') 
            or event.split('.')[0] in ['subprocess', 'os', 'shutil', 'winreg']): raise IOError('file write forbidden')

addaudithook(block_mischief)

Cho đến nay execcó thể dễ dàng ghi vào đĩa:

exec("open('/tmp/FILE','w').write('pwned by l33t h4xx0rz')", dict(locals()))

Nhưng chúng tôi có thể cấm tùy ý, để không người dùng xấu nào có thể truy cập vào đĩa từ mã được cung cấp cho exec(). Các mô-đun Pythonic thích numpyhoặc picklecuối cùng sử dụng quyền truy cập tệp của Python, vì vậy chúng cũng bị cấm ghi vào đĩa. Các lệnh gọi chương trình bên ngoài cũng đã bị vô hiệu hóa một cách rõ ràng.

WRITE_LOCK = True
exec("open('/tmp/FILE','w').write('pwned by l33t h4xx0rz')", dict(locals()))
exec("open('/tmp/FILE','a').write('pwned by l33t h4xx0rz')", dict(locals()))
exec("numpy.savetxt('/tmp/FILE', numpy.eye(3))", dict(locals()))
exec("import subprocess; subprocess.call('echo PWNED >> /tmp/FILE', shell=True)",     dict(locals()))

Nỗ lực loại bỏ khóa từ bên trong exec()dường như là vô ích, vì hook kiểm tra sử dụng một bản sao khác của localsnó không thể truy cập được đối với mã chạy bởi exec. Hãy chứng minh tôi sai.

exec("print('muhehehe'); del WRITE_LOCK; open('/tmp/FILE','w')", dict(locals()))
...
OSError: file write forbidden

Tất nhiên, mã cấp cao nhất có thể kích hoạt lại I / O tệp.

del WRITE_LOCK
exec("open('/tmp/FILE','w')", dict(locals()))

Sandboxing trong Cpython đã được chứng minh là cực kỳ khó và nhiều lần thử trước đó đã thất bại. Cách tiếp cận này cũng không hoàn toàn an toàn, ví dụ: truy cập web công cộng:

  1. có lẽ các mô-đun biên dịch giả định sử dụng lệnh gọi hệ điều hành trực tiếp không thể được kiểm tra bởi Cpython - nên đưa vào danh sách trắng các mô-đun pythonic tinh khiết an toàn.

  2. Chắc chắn vẫn có khả năng gặp sự cố hoặc quá tải trình thông dịch Cpython.

  3. Có thể vẫn còn một số lỗ hổng để ghi các tệp trên ổ cứng. Nhưng tôi không thể sử dụng bất kỳ thủ thuật né tránh hộp cát thông thường nào để ghi một byte duy nhất. Có thể nói "bề mặt tấn công" của hệ sinh thái Python giảm xuống một danh sách hẹp các sự kiện được (không) cho phép: https://docs.python.org/3/library/audit_events.html

Tôi rất biết ơn bất kỳ ai đã chỉ cho tôi những sai sót của phương pháp này.


CHỈNH SỬA: Vì vậy, điều này cũng không an toàn ! Tôi rất cảm ơn @Emu vì cách hack thông minh của anh ấy bằng cách sử dụng tính năng bắt ngoại lệ và xem xét nội tâm:

#!/usr/bin/python3.8
from sys import addaudithook
def block_mischief(event,arg):
    if 'WRITE_LOCK' in globals() and ((event=='open' and arg[1]!='r') or event.split('.')[0] in ['subprocess', 'os', 'shutil', 'winreg']):
        raise IOError('file write forbidden')

addaudithook(block_mischief)
WRITE_LOCK = True
exec("""
import sys
def r(a, b):
    try:
        raise Exception()
    except:
        del sys.exc_info()[2].tb_frame.f_back.f_globals['WRITE_LOCK']
import sys
w = type('evil',(object,),{'__ne__':r})()
sys.audit('open', None, w)
open('/tmp/FILE','w').write('pwned by l33t h4xx0rz')""", dict(locals()))

Tôi đoán rằng kiểm toán + subprocessing là con đường để đi, nhưng đừng sử dụng nó trên máy sản xuất:

https://bitbucket.org/fdominec/experimental_sandbox_in_cpython38/src/master/sandbox_experiment.py

4 hữu ích 0 bình luận chia sẻ

LAB 20: Dùng Python lấy danh sách thông tin các thiết bị trong fabric SD-WAN của Cisco

I. Mô tả:

  • Học viên thực hiện kết nối đến Sandbox SD-WAN (vManage), viết code để lấy danh sách thông tin các thiết bị bằng ngôn ngữ Python.
  • Máy PC phải đáp ứng yêu cầu đã cài đặt trạm làm việc cho developer.

II. Yêu cầu kĩ thuật:

  • Cài đặt thư viện requests, tabulate, click trên máy tính.
  • Kết nối đến Sandbox SD-WAN (https://sandboxsdwan.cisco.com:8443/)
  • Viết code bằng Python thực hiện yêu cầu:
  • Đăng nhập và xác thực
  • GET requests, POST requests
  • Lấy danh sách thông tin các thiết bị trong Controller

III. Các bước thực hiện:

Bước 1: Cài đặt thư viện

- Bấm tổ hợp phím Win+R để chạy cmd

- Trong màn hình cmd gõ : python –m pip install requests tabulate click –user

            Bước 2: Viết code đăng nhập và xác thực

Import các thư viện cần thiết và tắt cảnh báo

import requests

import sys

import json

import click

from tabulate import tabulate

import SD_WAN_INFO

requests.packages.urllib3.disable_warnings()

Tạo file SD_WAN_INFO.py chứa thông tin kết nối và thông tin đăng nhập, ghi các thông tin như hình dưới, sau đó lưu lại và đóng file

Trở về file trước, ta khai báo các thông tin của Sandbox SD-WAN, các biến SDWAN_IP,USERNAME,PASSWORD sẽ lấy giá trị từ file SD_WAN.py đã tạo ở trên.

SDWAN_IP = SD_WAN_INFO.IP

SDWAN_USERNAME = SD_WAN_INFO.USERNAME

SDWAN_PASSWORD = SD_WAN_INFO.PASSWORD

Tiếp theo chúng ta sẽ tạo một class rest_api_lib và tạo contructor __init__ của class (lưu ý ngoài các tham số truyền vào chúng ta luôn phải thêm self đại diện cho instance của class và với nó chúng ta có thể kết nối đến các thuộc tính và phương thức của class đó.

class rest_api_lib:

      def __init__(self, vmanage_ip, username, password):

            self.vmanage_ip = vmanage_ip

            self.session = {}

            self.login(self.vmanage_ip, username, password)

Định nghĩa phương thức login và khai báo login_url

      def login(self, vmanage_ip, username, password):

            """Login to vmanage"""

            base_url_str = 'https://%s:8443/'%vmanage_ip

            login_action = '/j_security_check'

            login_url = base_url_str + login_action

Khai báo login_data chứa username và password để gửi lên xác thực

            login_data = {'j_username' : username, 'j_password' : password}

Chúng ta sẽ dùng phương thức session từ thư viện request để tạo một phiên làm việc mới, trong phiên làm việc vừa tạo đó gửi yêu cầu post để đưa thông tin đến login_url.

            sess = requests.session()       

            login_response = sess.post(url=login_url, data=login_data, verify=False)

Để đảm bảo xác thực thành công chúng ta sẽ kiểm tra nội dung trả về và nếu nội dung trả về có tag

thì nghĩa là đăng nhập thất bại. Nếu muốn xem đăng nhập thất bại thì nội dung trả về sẽ như thì sửa lại mật khẩu và bỏ dấu # đầu dòng của đoạn code dưới này.' in login_response.content:

            print ("Login Failed")

            #print(login_response.content)

            sys.exit(0)

Gắn session sess vào làm giá trị của thuộc tính session của class

            self.session[vmanage_ip] = sess

Bước 3: Viết code GET requests

Định nghĩa phương thức get_request, trong đây chúng ta sẽ phải tạo một url mới, tham số api truyền vào tùy mục đích sử dụng nên chúng ta sẽ dùng %s để url có thể thay đổi dễ dàng. Ta sẽ dùng tiếp session vừa được xác thực thành công để gọi các API tiếp theo mà không cần phải gửi kèm theo username, password; get để gửi yêu cầu lên server và nhận lời đáp lại, sau đó gắn thông tin từ lời đáp lại vào biến response. Để lấy dữ liệu, ta sẽ dùng response.content gắn vào biến data và đây cũng là giá trị trả về của phương thức get_request này.

     def get_request(self, api):

           url = "https://%s:8443/dataservice/%s"%(self.vmanage_ip, api)

           response = self.session[self.vmanage_ip].get(url, verify=False)

           data = response.content

           return data

            Bước 4: Viết code POST requests

Phương thức post_request này tương tự với phương thức get_request ở trên nhưng khác ở chỗ post dùng để gửi yêu cầu tạo tài nguyên mới trên server. Và có thêm tham số đầu vào là payload và headers. Payload là nơi sẽ chứa đựng các thông tin gửi kèm theo khi gửi yêu cầu post. Headers khai báo kiểu nội dung là application/json.

    def post_request(self, api, payload, headers={'Content-Type': 'application/json'}):

          url = "https://%s:8443/dataservice/%s"%(self.vmanage_ip, api)

          payload = json.dumps(payload)

          print(payload)

          response = self.session[self.vmanage_ip].post(url=url, data=payload, headers=headers, verify=False)

         data = response.json()

         return data

            Bước 5: Viết code lấy danh sách thông tin các thiết bị

Tạo instance của class là sdwanp và truyền các tham số SDWAN_IP, SDWAN_USERNAME, SDWAN_PASSWORD

sdwanp = rest_api_lib(SDWAN_IP, SDWAN_USERNAME, SDWAN_PASSWORD)

Khi muốn cấu hình nhiều decorator @click.command() thì phải sử dụng group() để tạo nhiều decorator trong cùng một đoạn script.

@click.group()

def cli():

    pass

Tạo decorator @click.command() cấu hình Click để làm việc với hàm Python ngay sau decorator. Click.echo() dùng để in ra màn hình. Json.loads() dùng để giải mã đối tượng json thành đối tượng trong python.

@click.command()

def device_list():

      """Retrieve and return network devices list."""

      click.echo("Retrieving the devices.")

      response = json.loads(sdwanp.get_request('device'))

      items = response['data']

Khai báo headers để hiển thị trong bảng và khai báo list table. Tạo vòng lặp cứ mỗi item trong biến items chứa dữ liệu này thì sẽ được ghi thêm vào list table. Tiếp theo chúng ta sẽ dùng hàm tabulate để xuất ra màn hình bảng danh sách thông tin các thiết bị trong fabric của SD-WAN.

      headers = ["Host-Name", "Device Type", "Device ID", "System IP", "Site ID", "Version", "Device Model"]

      table = list()

      for item in items:

            tr = [item['host-name'], item['device-type'], item['uuid'], item['system-ip'], item['site-id'], item['version'], item['device-model']]

            table.append(tr)

      try:

            click.echo(tabulate(table, headers, tablefmt="fancy_grid"))

      except UnicodeEncodeError:

            click.echo(tabulate(table, headers, tablefmt="grid"))

Cuối cùng là thêm command device_list vào cli() và viết hàm main

cli.add_command(device_list)

if __name__ == "__main__":

    cli()

Để chạy chương trình này, chúng ta sẽ vào cmd, đi đến thư mục đặt file python, chạy chương trình sdwan.py

Kết quả:

Để ý phần Usage có hướng dẫn cách sử dụng click, hiện tại commands hiện có là device-list nên trong cmd chúng ta sẽ gõ: >sdwan.py device-list

Kết quả là chúng ta lấy được danh sách các thiết bị hiện có trong mạng fabric SD-WAN.


Thông tin khác

  • » LAB 18: Thực thi chính sách QoS trong Cisco SD-WAN (08.04.2021)
  • » LAB 19: Sử dụng Postman tương tác với SD-WAN REST API (08.04.2021)
  • » LAB 17: Viết chính sách dữ liệu Data Policy để ảnh hưởng đến việc lựa chọn đường dẫn ưu tiên cho các ứng dụng. (05.04.2021)
  • » REST-BASED APIS (05.04.2021)
  • » Các bước chuẩn bị để thực hành devnet cho máy sử dụng hđh Windows, gồm 7 bước: (02.04.2021)
  • » Setup WSL 1 (02.04.2021)
  • » GIỚI THIỆU MÔN HỌC ADVANCED ROUTING (31.03.2021)
  • » CHƯƠNG 2: CHU TRÌNH PHÁT TRIỂN PHẦN MỀM (30.03.2021)