Ctfshow web入门 PHP特性篇 web89-web151 全(二)

本文涉及的产品
图片翻译,图片翻译 100张
文档翻译,文档翻译 1千页
语种识别,语种识别 100万字符
简介: Ctfshow web入门 PHP特性篇 web89-web151 全(二)

·Ctfshow web入门 PHP特性篇 web89-web151 全(一):https://developer.aliyun.com/article/1585247

CTFshow PHP web113

这次限制了filter伪协议

压缩流payload可以继续用

?file=compress.zlib://flag.php

新知识点:目录溢出导致is_file认为这不是一个文件。

?file=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/var/www/html/flag.php

引用一下佬的博客:


linux里/proc/self/root是指向根目录的,也就是如果在命令行中输入ls /proc/self/root,其实显示的内容是根目录下的内容


/proc/self:不同的进程访问该目录时获得的信息是不同的,内容等价于/proc/本进程pid/。/proc/self/root/是指向/的符号链接,就是根目录。

CTFshow PHP web114

加了对compress 、root、 zip的过滤,之前的payload都用不了了。

但是,对filter的过滤却不见了。

payload:

?file=php://filter/resource=flag.php

CTFshow PHP web115

让我们GET传参一个num,满足is_numeric(num)andnum) and num!=='36' and trim(num)!==36andfilter(num)!=='36' and filter(num)=='36') 与$num=='36',注意,这里是字符串’36’。


trim():去除字符串首尾处的空白字符(或者其他字符)

自定义函数filter():把num中0x、0、e、.、+字符都换成数字1。

网上有一个FUZZ脚本:

<?php
for($i = 0; $i<129; $i++){
  $num=chr($i).'36';
  if(trim($num)!=='36' && is_numeric($num) && $num!=='36'){
    echo urlencode(chr($i))."\n";
  }
}
?>

一共有五个条件,脚本fuzz了三个,跑出来的字符是:

%0C、%2B、-、.、0、1、2、3、4、5、6、7、8、9

还剩两个条件是filter(num)==36num)=='36' 和num=='36'

跑出来的字符中,-、0、1、2、3、4、5、6、7、8、9直接就导致了num不满足$num==‘36’

跑出来的字符中,%2B(+的url编码)和 . 会被filter函数识别换成1,num变成136,不满足$num==‘36’

payload:

?num=%0C36

正常思路是去找函数绕过。


is_numeric():

php中is_numeric函数的绕过_is_numeric绕过_T0mrvvi1b3t的博客-CSDN博客

利用数组+十六进制来进行绕过;在前后加%00或在后加%20(空格);类型转换绕过:is_numeric(999a)是false。

所以我们可以选择在前面加%20,is_numeric()不会被绕过,任然判断为true。

trim()不会移除%0c

加上%0c换页符,是%0c36,这个东西类型转换时会被转换为数值36。%0c36在==进行类型转换,结果true;在!==不进行类型转换,所以字符串和数值比较,类型不同,结果true。

payload:

?num=%0C36

CTFshow PHP web123

考点:在php中变量名字是由数字字母和下划线组成的,所以不论用post还是get传入变量名的时候都将空格、+、点、[转换为下划线,但是用一个特性是可以绕过的,就是当[提前出现后,后面的点就不会再被转义了。


这里CTF[SHOW.COM=>CTF_SHOW.COM


要求CTF_SHOW、CTF_SHOW.COM必须传参,fl0g不能传参。所以$fl0g==="flag_give_me"条件不能满足,可以利用上面的eval。

payload:

CTF_SHOW=1&CTF[SHOW.COM=1&fun=echo $flag

问题来了,题中有一段代码是a=a=_SERVER['argv'];,这个argv是个什么呢?

第一次遇到它的时候是pear文件包含,argv这个东西涉及到了pear文件包含的原理。

argv是数组,argc是数字。
可通过var_dump($_SERVER);和var_dump($argv);语句查看

argv有独立GET之外获取参数的作用。比如传入?aaa+bbb   argv(数组)两个元素

是aaa和bbb。argc是数组的长度。

php中有些文件(pearcmd.php)是通过argv和argc来获取参数的。

这个argv还分两种模式,web和cli

web网页模式下

在web页模式下必须在php.ini开启register_argc_argv配置项

设置register_argc_argv = On(默认是Off),重启服务,$_SERVER[‘argv’]才会有效果,题目中应该是On

这时候的$_SERVER[‘argv’][0] = $_SERVER[‘QUERY_STRING’]
//$_SERVER[‘argv’][0]就是a[0]

$argv,$argc在web模式下不适用
cli模式(命令行)下

第一个参数总是当前【脚本】的文件名,因此 $argv[0] 就是脚本文件名。

当把php作为脚本,使用这个命令执行:php script.php arg1 arg2 arg3

以上示例的输出类似于:
array(4) {
  [0]=>
  string(10) "script.php"
  [1]=>
  string(4) "arg1"
  [2]=>
  string(4) "arg2"
  [3]=>
  string(4) "arg3"
}

我们是在网页模式下的,注意重点:

SERVER[argv][0]=_SERVER[‘argv’][0] = _SERVER[‘QUERY_STRING’]

而 $_SERVER[‘QUERY_STRING’] 是获取查询语句,也就是?后面的语句

举个例子:

如果    ?$fl0g=flag_give_me

$_SERVER['argv'][0]=$a[0]
=$_SERVER[‘QUERY_STRING’]就是$fl0g=flag_give_me

利用SERVER[argv][0]isset(_SERVER['argv'][0] 就可以绕过对isset(fl0g)的判断。用+代表空格。

payload:

get:
?$fl0g=flag_give_me;
post:
CTF_SHOW=1&CTF[SHOW.COM=1&fun=eval($a[0])

//从而满足之后的判断语句
//if($fl0g==="flag_give_me"){
//    echo $flag;
//}

get:
?a=1=1+fl0g=flag_give_me
post:
CTF_SHOW=&CTF[SHOW.COM=&fun=parse_str($a[1]) 

//需要用burp发包

CTFshow PHP web125

这次过滤了echo,长度限制也变短了

之前的payload满足条件的还剩

get:
?$fl0g=flag_give_me;
post:
CTF_SHOW=1&CTF[SHOW.COM=1&fun=eval($a[0])

get:
?a=1+fl0g=flag_give_me
post:
CTF_SHOW=&CTF[SHOW.COM=&fun=parse_str($a[1])      
//需要用burp发包

我们还可以用highlight_file构造一个新的payload:

get:
?1=flag.php
post:
CTF_SHOW=&CTF[SHOW.COM=&fun=highlight_file($_GET[1])
//不懂c怎么小于16的

CTFshow PHP web126

多过滤了字母g i f c o d

那么highlight_file不能用了,各种输出函数不能使用了,所以不能直接通过eval("c".";");flagfl0gechoc".";");来实现输出flag了,需要考虑用满足fl0g的条件来echo flag。

之前的payload还剩下能用的:

?a=1+fl0g=flag_give_me          //GET

CTF_SHOW=&CTF[SHOW.COM=&fun=parse_str($a[1])     //POST 
//需要用burp发包
?$fl0g=flag_give_me;      //GET

CTF_SHOW=1&CTF[SHOW.COM=1&fun=eval($a[0])    //POST

当然,eval也能用assert代替。

(突然回忆到蚁剑的转接头,有时候eval用不了也是能用assert的)

assert的语法要求没eval那么严格,相比上一个payload,$fl0g=flag_give_me少一个分号也没啥事。

?$fl0g=flag_give_me     //GET

CTF_SHOW=&CTF[SHOW.COM=&fun=assert($a[0])   //POST

别的师傅对assert的详细解释:

assert() 断言:

PHP 5
bool assert ( mixed $assertion [, string $description ] )

PHP 7
bool assert ( mixed $assertion [, Throwable $exception ] )

如果 assertion 是字符串,它将会被 assert() 当做 PHP 代码来执行
可见,eval和assert都可以将字符当作代码执行。

CTFshow PHP web127

注释都告诉我们了有waf。

SERVER[QUERYSTRING];"web123_SERVER['QUERY_STRING'];":web123提到过_SERVER[‘argv’][0] = $_SERVER[‘QUERY_STRING’],在题目,就是web模式下,这个和GET传参有关

extract:从数组中将变量导入到当前的符号表

回归题目

浏览所有代码,我们能获取flag的路径只有

if($ctf_show==='ilove36d'){
    echo $flag;
}

所以我们的目标是使$ctf_show==='ilove36d' 。

很容易想到GET传参?ctf_show=ilove36d 。

然后 extract()函数把我们的传参导入到当前的符号表使$ctf_show==='ilove36d'

但是有一个问题,自定义函数waf()会对urlurl也就是_SERVER['QUERY_STRING']也就是我们的GET传参进行正则匹配过滤,ctf_show中_会被过滤使程序直接die出。

回归web123,可以自动转成下划线又不在waf里面的,就只有空格。

我们GET传参?ctf show=ilove36d就行了

CTFshow PHP web128

让我来看看你有多骚~

直接给了源码。

题目的正则要求f1不存在字母数字,v2无限制。


call_user_func:第一个参数是被调用的回调函数,其余参数是回调函数的参数。

var_dump:打印变量的相关信息


扩展

gettext():_()是gettext()的拓展函数 在开启相关设定后,_("666")等价于gettext("666"),且就返回其中的参数


get_defined_vars:返回由所有已定义变量所组成的数组,因为包含了flag.php,所以flag.php里面肯定有$flag储存了flag。


所以可构造playload:

?f1=_&f2=get_defined_vars 
var_dump(call_user_func(call_user_func($f1,$f2)));
=> var_dump(call_user_func(call_user_func(_,'get_defined_vars')));
=> var_dump(call_user_func(get_defined_vars));

确实够骚的。

CTFshow PHP web129

stripos:查找字符串首次出现的位置

readfile: 输出文件

考点:目录穿越

题目要求我们构造的f中有ctfshow,且不在最开头。则执行readfile函数,同时还要不影响flag.php的读取

GET传参:

//查看源码
?f=php://filter/|ctfshow/resource=flag.php
?f=/ctfshow/../../../../../../../var/www/html/flag.php
?f=./ctfshow/../flag.php

//直接回显base64
?f=php://filter/read=convert.base64-encode|ctfshow/resource=flag.php

CTFshow PHP web130

题目描述:very very very(省略25万个very)ctfshow

分析代码:

if(preg_match('/.+?ctfshow/is', $f)){
     die('bye!');
}

要求我们传入的字符串不包含"ctfshow" (preg_match判断)

if(stripos($f, 'ctfshow') === FALSE){
    die('bye!!');
}

要求我们传入的字符串包含"ctfshow" (stripos判断)

方法一:

preg_match不识别数组,否则返回false

采用数组绕过的方法,stripos()遇到数组会返回null,null!=false,所以可以绕过stripos函数

f[]=1

方法二:

.表示任意单个字符,+表示必须匹配1次或多次,+?表示 重复1次或更多次,但尽可能少重复。

所以在ctfshow前面必须有至少一个字符,才会返回true

所以直接构造playload:f=ctfshow,即可绕过preg_match函数

同时,if(0 === flase)返回值为false0不是强等于false的,所以也不满足if(stripos($f, 'ctfshow') === FALSE)

f=ctfshow

方法三:

溢出回溯限制,这个知识点在2023年安洵杯第一题刚刚遇到过。

PHP利用PCRE回溯次数限制绕过某些安全限制

引用一下小元砸师傅的博客

PHP中,为了防止一次正则匹配调用的匹配过程过大从而造成过多的资源消耗,限定了一次正则匹配中调用匹配函数的次数。 回溯主要有两种

贪婪模式下,pattern部分被匹配,但是后半部分没匹配(匹配“用力过猛”,把后面的部分也匹配过了)时匹配式回退的操作,在出现*、+时容易产生。

非贪婪模式下,字符串部分被匹配,但后半部分没匹配完全(匹配“用力不够”,需要通配符再匹配一定的长度),在出现*?、+?时容易产生。

利用脚本:

import requests
url="xxxxxxxxxxxxxxx"
data={
    'f':'very'*250000+'ctfshow'
}
r=requests.post(url,data=data)
print(r.text)

执行后,因为超出了preg_match的回溯次数,报错返回false,达到绕过的效果,

同时因为POST传入的f中有ctfshow,第二个判断也被绕过,输出flag。

方法四:

f=ctfshow[]

【原理存疑】

CTFshow PHP web131

和web130差不多,但是由于改了stripos()的匹配内容,之前的方法二用不了了

因为f=(String)f = (String)_POST['f'];对$F进行了强制类型转换,所以之前的方法一、四也用不了了。只剩下方法三——溢出回溯限制

跑一下利用脚本

CTFshow PHP web132

题目描述:为什么会这样?

话不多说,直接开始信息搜集

先dirsearch扫一下。

访问/admin/index.php路由得到源码

分析一下代码:


mt_rand():使用 Mersenne Twister 算法生成随机整数。相比较于rand()函数其速度更快


&&和||优先级问题||优先级低于&&。if(code === mt_rand(1,0x36D) &&code === mt_rand(1,0x36D) && password === flag||flag || username ==="admin")可看作if((code === mt_rand(1,0x36D) &&code === mt_rand(1,0x36D) && password === flag)||flag )|| username ==="admin")


所以只需要满足后者就行:$username ==="admin"

同时满足下一个if:$code == 'admin'

payload:

?username=admin&code=admin&password=6666666

其实第一个$code === mt_rand(1,0x36D)为false,之后就执行||后面的内容,跳过了对password的判断,这叫做"短路"


Ctfshow web入门 PHP特性篇 web89-web151 全(三):https://developer.aliyun.com/article/1585328

目录
相关文章
|
9月前
|
PHP
PHP中的面向对象编程入门
在PHP的海洋里,面向对象编程(OOP)是一艘承载着代码复用与组织之美的巨轮。本文将带你启航,从基础概念到实际应用,领略类与对象的风采,掌握封装、继承、多态三大奥义。准备好你的航海图,让我们揭开PHP OOP的神秘面纱,驶向高效编程的彼岸。
|
7月前
|
监控 Linux PHP
【02】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-2月12日优雅草简化Centos stream8安装zabbix7教程-本搭建教程非docker搭建教程-优雅草solution
【02】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-2月12日优雅草简化Centos stream8安装zabbix7教程-本搭建教程非docker搭建教程-优雅草solution
186 20
|
8月前
|
SQL 关系型数据库 MySQL
php入门
PHP入门是循序渐进的过程,涵盖基本概念、语法、数据类型、运算符、控制结构及常用函数。PHP是一种开源服务器端脚本语言,特别适用于Web开发。代码在服务器执行,返回HTML给浏览器。基础语法包括变量、注释和标记;掌握数据类型(整数、浮点数、字符串等)和运算符(算术、比较、逻辑)。实践编写简单程序,如if语句、循环和自定义函数。学习内置函数处理字符串、数组、文件和数据库操作。结合实践加深理解,建议多编写小程序巩固知识。
|
8月前
|
存储 缓存 安全
网安入门之PHP后端基础
PHP 是一种服务器端脚本语言,广泛用于动态网站和Web应用程序开发。其文件扩展名为`.php`,支持嵌入HTML、CSS和JavaScript。PHP代码由Web服务器解析后返回给浏览器。PHP是弱类型语言,变量以`$`开头,支持字符串、整数、浮点数、布尔值、数组、对象等类型。PHP具有跨平台、开源、丰富的扩展库等特点。常用超全局变量如`$_GET`、`$_POST`、`$_SESSION`等处理用户输入和会话数据。HTTP请求方法GET和POST在数据传输方式、长度限制、安全性等方面有显著差异。
网安入门之PHP后端基础
|
9月前
|
Java 开发者 微服务
Spring Boot 入门:简化 Java Web 开发的强大工具
Spring Boot 是一个开源的 Java 基础框架,用于创建独立、生产级别的基于Spring框架的应用程序。它旨在简化Spring应用的初始搭建以及开发过程。
304 7
Spring Boot 入门:简化 Java Web 开发的强大工具
|
7月前
|
监控 关系型数据库 MySQL
【01】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-硬件设备实时监控系统运营版发布-本产品基于企业级开源项目Zabbix深度二开-分步骤实现预计10篇合集-自营版
【01】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-硬件设备实时监控系统运营版发布-本产品基于企业级开源项目Zabbix深度二开-分步骤实现预计10篇合集-自营版
155 0
|
10月前
|
Java 程序员 PHP
01 入门PHP就来我这-安装phpstudy
路老师的PHP入门教程,带你从零开始学习PHP。首先下载并安装phpStudy,接着配置域名和端口,最后创建并运行第一个PHP文件。内容详实,适合初学者。
193 3
01 入门PHP就来我这-安装phpstudy
|
10月前
|
XML 前端开发 JavaScript
PHP与Ajax在Web开发中的交互技术。PHP作为服务器端脚本语言,处理数据和业务逻辑
本文深入探讨了PHP与Ajax在Web开发中的交互技术。PHP作为服务器端脚本语言,处理数据和业务逻辑;Ajax则通过异步请求实现页面无刷新更新。文中详细介绍了两者的工作原理、数据传输格式选择、具体实现方法及实际应用案例,如实时数据更新、表单验证与提交、动态加载内容等。同时,针对跨域问题、数据安全与性能优化提出了建议。总结指出,PHP与Ajax的结合能显著提升Web应用的效率和用户体验。
220 3
|
10月前
|
安全 关系型数据库 PHP
探索PHP:从入门到精通
【10月更文挑战第38天】在这篇文章中,我们将一起踏上PHP的探索之旅。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的信息和技巧。我们将从PHP的基础开始,逐步深入到更复杂的主题,包括面向对象编程、数据库操作、安全性问题等。最后,我们将通过一些实用的代码示例,来展示PHP的强大功能和灵活性。让我们一起开始这段旅程吧!
57 2
|
10月前
|
存储 Serverless PHP
PHP编程入门:从基础到实战
【10月更文挑战第35天】本文将带你走进PHP的世界,从最基本的语法开始,逐步深入到实际应用。我们将通过简单易懂的语言和实际代码示例,让你快速掌握PHP编程的基础知识。无论你是初学者还是有一定经验的开发者,都能在这篇文章中找到你需要的内容。让我们一起探索PHP的魅力吧!

热门文章

最新文章