Pentest Playbook

Python Request 모듈화

1. Description

Python의 Request 라이브러리를 사용해서 특정 URL을 대상으로 request를 전달할 때, 매번 Header값과 Data값을 형식에 맞춰서 지정해줘야 하는 불편함이 있다.

불편함을 조금이나마 해소하기 위해서 request 요청에 사용되는 값들을 간단하게 모듈화한 내용이다.

  1. Burp Suite 도구에서의 요청 패킷 헤더
    헤더 값은 일반적으로 a:b를 기준으로 구분된다. 이 값을 Python 스크립트에 적용할 때 "a":"b"를 기준으로 변경이 필요하다.
    GET /wiki/favicon.ico HTTP/1.1
    Host: redacted.com
    Accept-Language: ko-KR,ko;q=0.9
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36
    
  2. Request로 요청 데이터 전송 방식
    data 값은 =,&"a":"b" 기준으로 변경이 필요하다.
    GET /wiki/Snippets/python-request?test=data&tset1=data1
    
    POST /wiki/Snippets/python-request
    ...SNIP...
    test=data&tset1=data1
    

2. 전체 코드

헤더와 데이터를 별도의 파일로 모듈화해서 사용하면 메인 파일의 코드를 늘리지 않고 조금은 편하게 사용할 수 있다.

#------------------------------------------------
# main.py
#------------------------------------------------
from headers_module import get_headers, get_data
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

#...코드생략...

def main():
    print(f"Module headers Result")
    print(get_headers())

    print(f"Module data Result")
    print(get_data())

if __name__ == "__main__":
    main()
#------------------------------------------------
# header_module.py
#------------------------------------------------

def get_headers() -> dict:
    # 원문 헤더 문자열 변환
    header_data = """
        Host: example.com
        Cookie: SESSIONID=asdfasdfasdfasdfasdf;
        Content-Length: 1982
        Content-Type: application/x-www-form-urlencoded
        User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36
        Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
        Sec-Fetch-Site: same-origin
        Connection: keep-alive
    """
    return parse_headers(header_data)

def parse_headers(header_data: str) -> dict:
    # HTTP 헤더를 Dictionary로 파싱
    headers = {}

    for line in header_data.strip().splitlines():
        if ": " in line:
            key, value = line.split(": ", 1)
            headers[key.strip()] = value.strip()
    return headers

"""매개변수를 data 형식으로 변환 (고정된 값일 경우 사용)"""
def get_data() -> dict:
    # 원문 데이터 문자열 변환
    data_string = "test=data&test1=data1&test2=data2"
    return parse_data(data_string)

def parse_data(data_string: str) -> dict:
    # URL 데이터를 Dictionary로 파싱
    datas = {}

    params = data_string.split('&')
    for param in params:
        if '=' in param:
            key, value = param.split('=', 1)
            datas[key] = value

    return datas

#BurpSuite Proxy Setting
def get_proxy():
    proxy_set = {"http": "127.0.0.1:8080","https": "127.0.0.1:8080"}
    return proxy_set

3. 실행 결과

Module headers Result
{'Host': 'example.com', 'Cookie': 'SESSIONID=asdfasdfasdfasdfasdf;', 'Content-Length': '1982', 'Content-Type': 'application/x-www-form-urlencoded', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', 'Sec-Fetch-Site': 'same-origin', 'Connection': 'keep-alive'}

Module data Result
{'test': 'data', 'test1': 'data1', 'test2': 'data2'}
ESC

💡 검색 팁

  • #T1572 - 태그로 검색
  • persistence - 키워드로 검색