일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
- VMware
- 리눅스
- NEXUS
- 드림핵
- 정보보안산업기사
- GitLab
- 유닉스
- 정보보안기사
- 기아
- 취약점진단
- dreamhack.io
- 모의해킹
- 보안기사실기
- 웹모의해킹
- AI
- 보안컨설팅
- 정보보안
- DreamHack
- Synology
- snort2.9
- docker
- Bigdata
- M1
- NQ5
- 리눅스보안
- gns3
- 스노트
- Snort
- Python
- 데이터모델링
- Today
- Total
Security_Analysis
[DreamHack.io]_CSRF_1 본문
DreamHack.io 의 웹해킹의 다섯번째 문제 "CSRF_1" 를 풀어보자.
CSRF란
"임의 이용자의 권한으로 임의 주소에 HTTP 요청을 보낼 수 있는 취약점으로, 공격자는 임의 이용자의 권한으로 서비스 기능을 사용하여 이득을 취할 수 있음"
app.py를 먼저 확인해보자
# app.py
# ========================================================
def check_csrf(param, cookie={"name": "name", "value": "value"}):
url = f"http://127.0.0.1:8000/vuln?param={urllib.parse.quote(param)}"
return read_url(url, cookie)
@app.route("/vuln")
def vuln():
param = request.args.get("param", "").lower()
xss_filter = ["frame", "script", "on"]
for _ in xss_filter:
param = param.replace(_, "*")
return param
@app.route("/flag", methods=["GET", "POST"])
def flag():
if request.method == "GET":
return render_template("flag.html")
elif request.method == "POST":
param = request.form.get("param", "")
if not check_csrf(param):
return '<script>alert("wrong??");history.go(-1);</script>'
return '<script>alert("good");history.go(-1);</script>'
memo_text = ""
@app.route("/memo")
def memo():
global memo_text
text = request.args.get("memo", None)
if text:
memo_text += text
return render_template("memo.html", memo=memo_text)
@app.route("/admin/notice_flag")
def admin_notice_flag():
global memo_text
if request.remote_addr != "127.0.0.1":
return "Access Denied"
if request.args.get("userid", "") != "admin":
return "Access Denied 2"
memo_text += f"[Notice] flag is {FLAG}\n"
return "Ok"
서버를 열어보면 이동할 수 있는 페이지가 4개 존재한다.
Vuln(csrf) Page
먼저 vuln(csrf) page 로 이동해보았다
URL에 GET방식으로 XSS 공격을 위한 예시구문이 실행되어 MessageBox(Alert) 창이 열린것을 확인했다.
Memo Page
두번째로 memo 페이지로 이동해보았다.
memo 페이지로 이동해보니 역시 이 페이지 또한 GET 방식으로 URL에 있는 값을 입력해주는 것으로 확인할 수 있다.
Notice Flag Page
세번째 페이지 notice flag로 이동해보았다.
Flag Page
마지막으로 네번째 페이지 flag로 이동해보았다.
힌트
코드를 통해서 몇가지 인트를 얻었다.
<1>. notice_flag 페이지는 접속한 IP가 "127.0.0.1" != Access Denied 출력
<2>. notice flag 페이지의 접속한 USERID가 admin이 아니면 != Access Denied 2 출력
<3>. flag 페이지에다가 값을 넣으면 check_csrf 함수를 통해서 parameter를 urlib.parse.quote(param) 을 통해 read_url에 넘긴다
풀이
1번째 힌트인 request.remote.addr 은 파라미터로 가져오는게 아니기 때문에 조작할 수가 없다고 판단해서 PASS
2번째 힌트는 request.args.get 으로 파라미터에서 인자를 가져오는 것이기 대문에 userid 값에 admin을 넣어서 /admin/notice_flag에 전달 하도록 작성해 보았다.
제출 버튼을 누르고 난후 memo 페이지로 접속해보면 아래와 같이 플래그가 확인된다.
플래그 찾기 성공!
다음 문제 : CSRf_2
※ 마지막 확인하는 부분에서 코드를 제대로 확인하지 않아 실수를 했었다.
파라미터로 /admin/notice_flag에다가 userid='admin' 을 넣어서 보냈기 때문에 제출 버튼 이후에 "/admin/notice_flag" 로 접속했던 것이다 . 그 결과는 역시나 "Access Denied"가 나왔다.
코드를 다시 한번 살펴보고 이해를 할 수 있었다.
1). 먼저 flag 페이지에다가 코드를 넣었으니 check_csrf(param) 을 통해서 check_csrf 함수를 실행시켰을 것이다.
2). check_csrf 함수에서 param= 뒤에는 공격자가 입력한 코드가 있을 것이다.
3). 이거를 url 변수로 하여 read_url로 넘겼다.
4). read_url 에서는 127.0.0.1:8000 으로 driver.get을 했고 url에도 127.0.01:8080 이 있는 상태이며 get으로 열었기 때문에 admin_notice_flag의 두가지 조건을 만족했다.
5). (request.remote.addr / request.args.get) 을 만족했기 때문에 get으로 url 불렀을 때 flag가 memo_text에 추가되었고,
6). 사용자가 memo 페이지를 눌렀을 때는 global 로 memo_text 값을 가져오기 때문에 flag가 보인 것이다.
def read_url(url, cookie={"name": "name", "value": "value"}):
# 생략 #
driver.get("http://127.0.0.1:8000/")
driver.get(url)
def check_csrf(param, cookie={"name": "name", "value": "value"}):
url = f"http://127.0.0.1:8000/vuln?param={urllib.parse.quote(param)}"
return read_url(url, cookie)
@app.route("/flag", methods=["GET", "POST"])
def flag():
# 생략 #
if not check_csrf(param):
return '<script>alert("wrong??");history.go(-1);</script>'
return '<script>alert("good");history.go(-1);</script>'
memo_text = ""
@app.route("/memo")
def memo():
global memo_text
text = request.args.get("memo", None)
if text:
memo_text += text
return render_template("memo.html", memo=memo_text)
@app.route("/admin/notice_flag")
def admin_notice_flag():
global memo_text
if request.remote_addr != "127.0.0.1":
return "Access Denied"
if request.args.get("userid", "") != "admin":
return "Access Denied 2"
memo_text += f"[Notice] flag is {FLAG}\n"
return "Ok"
app.run(host="0.0.0.0", port=8000)
P.S> 모의해킹 자체를 처음하다보니 제가 알고있는게 많이 적어서,,, 혹시나 제가 생각했던게 잘못되었을 경우 언제든 피드백 부탁드립니다.
'[Penetration] > _WEB' 카테고리의 다른 글
[DreamHack.io]_SqlInjection_1 (0) | 2023.12.03 |
---|---|
[DreamHack.io]_CSRF_2 (0) | 2023.12.02 |
[DreamHack.io]_(4)_XSS_2 (1) | 2023.11.30 |
[DreamHack.io]_(3)_XSS_1 (0) | 2023.11.29 |
[DreamHack.io]_(2)_Session (0) | 2023.11.28 |