LoRexxar's Blog

wctf2018 cyber mimic defence Writeup

2018/07/13

浠婂勾鏈夊垢浣滀负鏂颁汉璧涗腑鐨勪竴鍛樺弬鍔犱簡Wctf2018澶у笀璧涳紝姣旇緝闅捐繃鐨勬槸锛岀敱浜嶹ctf鏈韩浣跨敤鎴樹簤涓庡垎浜禌鍒讹紝鍗磋姹備簡姣忛槦蹇呴』鍑轰竴閬搘indows棰樼洰锛屽ぇ閮ㄥ垎浜洪兘閫夋嫨浜嗗唴鏍搁┍鍔ㄧ骇鍒殑re鍜宲wn锛屽彧鏈塋CBC鍑虹殑鈥滄嫙鎬侀槻寰♀濆拰鏅鸿兘鍚堢害瀹¤鍙互涓鍋氾紝鍏充簬鏅鸿兘鍚堢害鐨勯儴鍒嗘湁鏈轰細浼氬啀鍒嗕韩锛岃繖閲屽彧鐮旂┒涓涓媘imic杩欓銆

cyber mimic defence

浠g爜鎸虹畝鍗曠殑锛宖lask瀹屾垚锛屼富瑕佺殑鍔熻兘鍑犱箮鍙湁鐧婚檰娉ㄥ唽锛屽姛鑳芥牳蹇冨熀鏈兘鍦╱ser绫讳腑锛岃岃皟鐢ㄥ埌user绫荤殑view鍙湁鐧婚檰閮ㄥ垎锛屾墍浠ユ紡娲炰篃灏辨槸鍦ㄨ繖閲屻

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
views.py
# ~*~ coding: utf-8 ~*~
import flask_login as login
import flask_admin as admin
import json
import os
import time
from collections import defaultdict
from datetime import datetime
from flask_admin import helpers, expose
from flask import redirect, url_for, request, render_template
from flask import jsonify
from datetime import timedelta
from flask import make_response, request, current_app
from functools import update_wrapper
from loginform import LoginForm
import stub as stub
class AdminIndexView(admin.AdminIndexView):
def _stubs(self):
self.nav = {
"tasks" : stub.get_tasks(),
"messages" : stub.get_messages_summary(),
"alerts" : stub.get_alerts()
}
(cols, rows) = stub.get_adv_tables()
(scols, srows, context) = stub.get_tables()
self.tables = {
"advtables" : { "columns" : cols, "rows" : rows },
"table" : { "columns" : scols, "rows" : srows, "context" : context}
}
self.panelswells = {
"accordion" : stub.get_accordion_items(),
"tabitems" : stub.get_tab_items()
}
@expose('/')
def index(self):
# if not login.current_user.is_authenticated:
# return redirect(url_for('.login_view'))
self._stubs()
self.header = "Dashboard"
# login.current_user.query("EXEC sp_logEvent 'View at %s', 'dashboard', 'visit';" % time.time(), 'mssql')
print request.args.get('page', 'dashboard')
print os.path.basename(request.args.get('page', 'dashboard'))
page = os.path.basename(request.args.get('page', 'dashboard'))
return render_template('sb-admin/pages/%s.html' % page, admin_view=self)
@expose('/blank')
def blank(self):
# if not login.current_user.is_authenticated:
# return redirect(url_for('.login_view'))
self._stubs()
self.header = "Blank"
return render_template('sb-admin/pages/blank.html', admin_view=self)
@expose('/login/', methods=('GET', 'POST'))
def login_view(self):
form = LoginForm(request.form)
if helpers.validate_form_on_submit(form):
user = form.get_user()
login.login_user(user)
if login.current_user.is_authenticated:
return redirect(url_for('.index'))
self._template_args['form'] = form
return render_template('sb-admin/pages/login.html', form=form)
@expose('/logout/')
def logout_view(self):
login.logout_user()
return redirect(url_for('.index'))
class BlankView(admin.BaseView):
@expose('/')
def index(self):
return render_template('sb-admin/pages/blank.html', admin_view=self)

鎺ョ潃鎴戝啀璐翠笂user绫

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# ~*~ coding: utf-8 ~*~
from config import *
from collections import Counter
from random import choice
try:
from flask.ext.login import UserMixin
except:
from flask_login import UserMixin
class UserNotFoundError(Exception):
pass
class User(UserMixin):
id = None
password = None
def is_active(self):
return True
def query(self, query, driver):
try:
conn = self.DB_CONNECTIONS[driver]
c = conn.cursor()
c.execute(query)
r = tuple(c.fetchall())
return r
except Exception, e:
return ()
def find_user(self, username, driver):
TERMINAL_TOKENS = {
'psql': ["'", '$$'],
'mssql': ["'"],
'mysql': ["'", '"'],
'sqlite': ["'", '"']
}
quote = choice(TERMINAL_TOKENS.get(driver, ["'", '"']))
query = '''select * from users where username=%s%s%s;''' % (quote, username, quote)
# select * from users where username='1' and 1=0 union select '1','1','1234'
return self.query(query, driver)
def __init__(self, username):
self.DB_CONNECTIONS = {
'mssql': pymssql.connect('127.0.0.1', '', '', ''),
'mysql': MySQLdb.connect(host='localhost', user='', passwd='', db=''),
'psql': psycopg2.connect("dbname='' user='' host='localhost' password=''"),
'sqlite': sqlite3.connect(os.path.dirname(os.path.realpath(__file__)) + '/../X.sqlite3'),
}
result = [self.find_user(username, driver) for driver in self.DB_CONNECTIONS]
common = Counter(result).most_common()[0]
user = () if common[1] < len(result) - 1 else common[0]
if not user:
raise UserNotFoundError()
self._id = user[0][0]
self.username = user[0][1]
self.id = self.username
self.password = user[0][2]
@classmethod
def get(self_class, username):
try:
return self_class(username)
except UserNotFoundError:
return None

鎴戜滑寰堝鏄撶湅鍒帮紝鍦╱ser绫讳腑锛屽鏌ヨ璇彞鐩存帴鍋氫簡鎷兼帴

1
query = '''select * from users where username=%s%s%s;''' % (quote, username, quote)

寰堟槑鏄剧殑娉ㄥ叆锛屼絾闂鍦ㄤ簬锛岃繖閲孡CBC鍔犲叆浜嗘墍璋撶殑鎷熸侀槻寰★紝浠g爜濡備笅锛

1
2
3
4
5
6
7
8
9
10
11
12
def find_user(self, username, driver):
TERMINAL_TOKENS = {
'psql': ["'", '$$'],
'mssql': ["'"],
'mysql': ["'", '"'],
'sqlite': ["'", '"']
}
quote = choice(TERMINAL_TOKENS.get(driver, ["'", '"']))
query = '''select * from users where username=%s%s%s;''' % (quote, username, quote)

鍚庣浣跨敤浜4绉嶆暟鎹簱锛岀劧鍚庝笉鍚岀殑鏁版嵁搴撲細瀵瑰簲涓嶅悓鐨勯棴鍚堢鍙凤紝鍦ㄦ瘡娆℃煡璇㈡椂閮戒細鍚4涓暟鎹簱鍚屾椂鏌ヨ锛岀劧鍚庡姣旇繑鍥炵粨鏋滐紝鍙湁3绉嶄互涓婄浉鍚岀殑缁撴灉鎵嶄細琚繑鍥炪

1
2
3
4
5
6
7
8
9
result = [self.find_user(username, driver) for driver in self.DB_CONNECTIONS]
common = Counter(result).most_common()[0]
user = () if common[1] < len(result) - 1 else common[0]
if not user:
raise UserNotFoundError()
self._id = user[0][0]
self.username = user[0][3]
self.id = self.username
self.password = user[0][4]

鎴栬鎴戜滑寰堥毦鎵惧埌杩欑闃插尽鏂瑰紡鐨勫急鐐癸紝浣嗘槸鎴戜滑鎴栬闇瑕佹崲涓濊矾鏉ユ濊冭繖涓棶棰樸

鎴戜滑鏈変袱涓姙娉曡В鍐宠繖涓棶棰
1銆佹壘鍒拌嚦灏3绉嶆暟鎹簱閮芥敮鎸佺殑鏌ヨ鏂瑰紡
2銆佸彧鏀诲嚮鍏朵腑1绉嶆暟鎹簱

杩欓噷鎴戜滑寰堥毦鎵惧埌鏀寔绗竴绉嶅姙娉曠殑娉ㄥ叆鏂瑰紡锛屽洜涓哄湪涓嶅悓鐨勬暟鎹簱涓紝鍌ㄥ瓨琛ㄥ悕鍒楀悕瀛楁鐨勯兘鏄笉鍚屼綅缃紝鎴戜滑鏈澶氬彧鑳戒娇鐢ㄦ渶鏅氱殑union select璇硶鏉ョ櫥闄嗐

1
username=root' union select 0,'root','e10adc3949ba59abbe56e057f20f883e'--&password=123456

鐢ㄨ繖涓鍙ュ彲浠ョ洿鎺ョ櫥闄嗭紝寰堟樉鐒讹紝鍚庡彴浠涔堥兘娌℃湁銆

閭d箞鎴戜滑鏋滄柇鏄敱绗簩绉嶆柟寮忥紝鏃㈢劧鎴戜滑鐨勬瘡娆℃煡璇㈤兘浼氳繘鏁版嵁搴擄紝閭d箞鎴戜滑鐩存帴鏃堕棿鐩叉敞灏卞ソ浜嗭紝鏈変釜闂鍦ㄤ簬锛屾瘮濡俶ysql锛屾垜浠渶瑕佸鐞嗗崟鍙屽紩鍙烽棴鍚堟柟寮忎笉鍚岀殑闂锛屽綋闂悎鏂瑰紡涓嶅悓鏃讹紝鎴戜滑灏辨病鍔炴硶鑾峰緱鏁版嵁浜嗐

鏈変袱涓姙娉曪紝1鏄氳繃绮惧鐨勬瀯閫犳潵闂悎涓ょ寮曞彿锛屼篃涓嶆槸寰堥毦锛屽氨鏄湅鐫鎸洪毦鍙楃殑锛屼緥濡

1
username=1' or '"!="'!='' and sleep(2) and ''!='" or sleep(2)!="&password=123456

2灏辨槸閫氳繃if鐨勬纭拰閿欒鐢熸垚涓嶅悓鐨勫欢鏃舵潵鍒ゆ柇

1
1' or if(({}), sleep(3), sleep(1))#

閫氳繃鍙湁鏈夋晥璇彞鎵嶄細sleep

杩欎箞涓鏉ユ垜浠氨鑳芥敞浜嗭紝寰堟樉鐒剁殑鏄紝鏁版嵁搴撻噷涔熶粈涔堥兘娌℃湁锛侊紒锛

閭h鎴戜滑閲嶆柊鍥炲埌棰樼洰杩涜鎬濊

閭d箞鍦ㄦ敞鍏ヤ箣鍚庣殑绗簩姝

1銆佹敞鍏ユ嬁flag锛屾垨鑰呮敞鍏ヨ鏂囦欢鎷縡lag锛坣o锛
2銆侀渶瑕佹敞鍏ヨЕ鍙戠浜屼釜婕忔礊

闇瑕佺櫥闄嗘墠鑳借闂殑璺敱鍖呮嫭

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/blank
/
浠g爜濡備笅
@expose('/')
def index(self):
if not login.current_user.is_authenticated:
return redirect(url_for('.login_view'))
self._stubs()
self.header = "Dashboard"
login.current_user.query("EXEC sp_logEvent 'View at %s', 'dashboard', 'visit';" % time.time(), 'mssql')
page = os.path.basename(request.args.get('page', 'dashboard'))
return render_template('sb-admin/pages/%s.html' % page, admin_view=self)
@expose('/blank')
def blank(self):
if not login.current_user.is_authenticated:
return redirect(url_for('.login_view'))
self._stubs()
self.header = "Blank"
return render_template('sb-admin/pages/blank.html', admin_view=self)

page杩欓噷鍙橀噺缁忚繃浜哹asename鐨勫鐞嗭紝娌″姙娉曠粫杩囷紝鎵浠ユ垜浠彧鑳藉紩鍏sb-admin/pages/涓嬬殑
%.html锛屾寜鐓ц繖涓濊矾鎬濊冿紝鎴戜滑闇瑕佹壘鍒颁竴涓啓鍏ユ枃浠剁殑鐐癸紝鐒跺悗灏卞彲浠ラ氳繃鍐欏叆妯℃澘锛屾瀯閫犲懡浠ゆ墽琛実etshell锛

鎬濇潵鎯冲幓涔熷彧鏈夋敞鍏ユ湁鍙兘鍙互鍐欏叆鏂囦欢锛屾墍浠ユ垜浠妸鐩厜鏀惧埌鍏朵粬鏁版嵁搴撲腑锛屼絾鏃犱竴渚嬪鍦版槸鏉冮檺涓嶅锛屽洖椤炬簮鐮佺殑鏃跺欙紝鍙戠幇浜

1
login.current_user.query("EXEC sp_logEvent 'View at %s', 'dashboard', 'visit';" % time.time(), 'mssql')

鍏跺疄褰撴椂鍦ㄦ瘮璧涚殑鏃跺欎篃鍙戠幇杩欎釜浜嗭紝鎵浠ヤ竴鐩村湪鐮旂┒mssql鐨凟XEC鑳戒笉鑳藉啓鍏ユ枃浠讹紝鍥犱负鏃犳硶鑾峰彇杩斿洖锛屾墍浠ヤ竴鐩存壘涓嶅埌鑳介獙璇佹槸鍚︽垚鍔熷啓鍏ユ枃浠剁殑鏂规硶锛屼粠鏉冮檺鍒ゆ柇锛屽垯鏄病鏈夊啓鏂囦欢鐨勬潈闄愶紝褰撴椂娌℃兂鍒扮殑鏄紝mssql鍙互鏌ヨ瀛樺偍杩囩▼鐨勯厤缃

1
2
3
sp_helptext 'ListBandGenresInternational' # 鏌ョ湅瀛樺偍杩囩▼瀹氫箟
sp_help band_genres # 鏌ョ湅琛ㄧ粨鏋勶紝涔熷彲浠ユ煡鐪嬪瓨鍌ㄨ繃绋嬬殑绠鍗曚俊鎭

鍊煎緱娉ㄦ剰鐨勬槸锛屽洜涓哄悗绔湁澶氱鏁版嵁搴擄紝鎵浠ュ嵆浣挎垜浠紑鐫sqlmap鎵仛鍚勭闄愬埗锛宻qlmap涔熷緢闅炬寜鐓ф垜浠渶瑕佺殑鏂瑰紡甯垜浠畬鎴愯繖閲岀殑鏃堕棿鐩叉敞锛堣嚦灏戞垜浠病鎴愬姛锛夛紝鎵浠ワ紝濡備綍鍦ㄦ湁闄愮殑鏃堕棿瀹屾垚涓嶇啛鎮夌殑mssql娉ㄥ叆鑴氭湰骞惰幏寰楅偅涔堝ぇ鐨勬暟鎹紝灏辨垚浜嗘牳蹇冮棶棰橈紝杩欎篃鏄繖涓鐩渶澶х殑闂锛

鍏充簬mssql鏃堕棿鐩叉敞鍙互鐪嬭繖绡囨枃绔

http://drops.xmd5.com/static/drops/tips-8242.html

image.png-9469.8kB

杩欐槸鐜板満鍒嗕韩浼氬叕甯冪殑鍌ㄥ瓨杩囩▼锛屽湪鍏朵腑锛屾垜浠緢鏄庢樉鍙互鐪嬪埌鍐欏叆log鐨勭洰褰曞拰鍌ㄥ瓨缁撴瀯锛屽敮涓鐨勯棶棰樻槸锛屾垜浠渶瑕佹兂鍔炴硶缁曡繃鍚庣紑闄愬埗锛屽叾瀹炰篃寰堝ソ鍔烇紝鍥犱负鍦ㄦ暟鎹簱涓檺鍒朵簡name鍜宼ype鐨勪綅鏁帮紝鍒嗗埆閮芥槸40浣嶃

image.png-1129.1kB

鎴戜滑閫氳繃杩欑鏂瑰紡娉ㄥ叆璇彞鍒皊pWriteupStringToFile涓紝鏋勯犳埅鏂氨鍙互鍐欏叆鏂囦欢浜嗐

鍚庨潰鐨勬濊矾寰堟竻妤氫簡锛屽啓鍏lask妯℃澘锛岀劧鍚庣敤鍚庡彴鐨勫姛鑳藉紩鍏ワ紝鎵ц鍛戒护

image.png-958.5kB

1
2
page = os.path.basename(request.args.get('page', 'dashboard'))
return render_template('sb-admin/pages/%s.html' % page, admin_view=self)

鏈鍚庤姹?page=x鍗冲彲瑙﹀彂

CATALOG
  1. 1. cyber mimic defence