1

파이썬에서 요청 라이브러리를 사용하여 http를 통해 많은 수의 이미지 파일을 다운로드합니다. 파이썬에서 BytesIO를 사용하여 수신 된 컨텐트를 raw 바이트로 변환 한 다음 Pillow()를 사용하여이 원시 컨텐트를 jpeg 파일로 저장합니다.이미지 다운로드 mime 형식 유효성 검사 파이썬 요청

from PIL import Image 
from io import BytesIO 

rsp = requests.get(imageurl) 
content_type_received = rsp.headers['Content-Type'] # mime type 
binarycontent = BytesIO(rsp.content) 
if content_type_received.startswith('image'): # image/jpeg, image/png etc 
    i = Image.open(binarycontent) 
    outfilename = os.path.join(outfolder,'myimg'+'.jpg') 
    with open(outfilename, 'wb') as f: 
     f.write(rsp.content) 
    rsp.close() 

이 코드의 잠재적 보안 위험 가능성은 무엇입니까? (나는 응답 헤더의 mime 형식이 실제로 서버가 말하고있는 것을 말하는 서버를 얼마나 신뢰할 수 있는지 잘 모르겠다.) 보안 다운로드 루틴을 작성하는 더 좋은 방법이 있습니까?

답변

1

코드의 잠재적 인 보안 위험은 사용자가 접촉하는 서버를 얼마나 신뢰하는지에 따라 다릅니다. 서버가 악성 콘텐츠로 사용자를 속일 수 없다면 해당 코드를 사용하는 것이 상대적으로 안전합니다. 그렇지 않으면 직접 콘텐츠 유형을 확인하십시오. 잠재적으로 가장 큰 위험은 이미지가 아닌 실행 파일을 모르는 채 저장할 수 있습니다. 크기가 작을수록 응용 프로그램에서 PIL 또는 다른 구성 요소가 손상 될 수있는 다른 종류의 콘텐츠를 저장할 수 있습니다.

서버는 content-type을 포함한 모든 응답 헤더에 원하는 값을 자유롭게 선택할 수 있습니다. 연락하는 서버가 정직하지 않을 수도 있다고 생각되는 경우 요청 헤더를 신뢰해서는 안됩니다.

받은 콘텐츠의 콘텐츠 형식을보다 안정적으로 확인하려면 libmagic의 래퍼 python-magic을 살펴 보시기 바랍니다. 이 라이브러리는 콘텐츠 유형을 스스로 결정하는 데 도움이되므로 다운로드하는 서버를 "신뢰"할 필요가 없습니다.

# ... 
content = BytesIO(rsp.content) 
mime = magic.from_buffer(content.read(1024), mime=True) 
if mime.startswith('image'): 
    content.seek(0) # Reset the bytes stream position because you read from it 
    # ... 

python-magic은 문서화가 잘되어 있으므로 사용자를 고려해 본다면 README를 살펴 보는 것이 좋습니다.

+0

좋은 답변입니다. 동의하기 전에 응답 내용에서 1024 바이트 만 읽는 이유는 무엇입니까? 이미지에서 MIME 형식을 추론하는 것으로 충분하기 때문에? 호기심에서 벗어나 요청 된 것이 다른 유형의 미디어 일 경우 어떻게 결정됩니까? 예를 들어 mp4라고 말하면 어떨까요? – hAcKnRoCk

+1

mimetype을 정확하게 평가하기 위해 읽어야하는 적절한 바이트 수는 당신이 읽는 파일 유형에 따라 다르므로 알아보기가 어렵습니다. 일부 파일 서명은이 정보를 오프셋과 함께 배치하기도합니다. 1024 바이트는 모든 종류의 이미지 유형에 충분히 적합해야하지만 그 가치는 오히려 "인터넷 지식"과 같습니다. –