MarioBoy

实验吧CTF-你真的会php吗
原题链接你真的会php吗?点击连接进去后直接显示have a fun!,一点提示也没有。打开网络控制台查看数据包如...
扫描右侧二维码阅读全文
09
2018/06

实验吧CTF-你真的会php吗

原题链接你真的会php吗?
点击连接进去后直接显示have a fun!,一点提示也没有。打开网络控制台查看数据包如下:

HTTP/1.1 200 OK
Date: Sat, 09 Jun 2018 08:38:41 GMT
Server: Apache/2.4.18 (Win32) OpenSSL/1.0.2e PHP/5.3.29
X-Powered-By: PHP/5.3.29
hint: 6c525af4059b4fe7d8c33a.txt
Content-Length: 12
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html

发现有一个hint,并且是一个32为的机器(这一点下面会用到)
所以访问: http://ctf5.shiyanbar.com/web/PHP/6c525af4059b4fe7d8c33a.txt
得到一个php文件,代码如下(注释是我自己写的):

'''php
<?php
$info = "";
$req = [];
$flag="xxxxxxxxxx";
ini_set("display_error", false);
error_reporting(0);
if(!isset($_POST['number'])){
    header("hint:6c525af4059b4fe7d8c33a.txt");
    die("have a fun!!");
}
foreach([$_POST] as $global_var) {
    //=>符号来分隔键和值,左侧表示键,右侧表示值
    foreach($global_var as $key => $value) {
        //trim()从字符串的开头去掉空格或其他字符
        $value = trim($value);
        //is_string 查找变量是否是数组  addskasges用C样式的斜线引用字符串
        is_string($value) && $req[$key] = addslashes($value);
    }
}
//判断是否是回文数
function is_palindrome_number($number) {
    //strvar获得一个变量的类型
    $number = strval($number);
    $i = 0;
    $j = strlen($number) - 1;
    while($i < $j) {
        //!==运算符:如果 x 不等于 y,或它们类型不相同,则返回 true
        if($number[$i] !== $number[$j]) {
            return false;
        }
        $i++;
        $j--;
    }
    return true;
}
//is——numric查找变量的类型是否是字符串(is_numeric函数对于空字符%00,无论是%00放在前后都可以判断为非数值,而%20空格字符只能放在数值后)
if(is_numeric($_REQUEST['number'])){

    $info="sorry, you cann't input a number!";
//intvar获取变量的浮点值
}elseif($req['number']!=strval(intval($req['number']))){
    $info = "number must be equal to it's integer!! ";
}else{
    $value1 = intval($req["number"]);
    $value2 = intval(strrev($req["number"]));
    if($value1!=$value2){
        $info="no, this is not a palindrome number!";
    }else{
        if(is_palindrome_number($req["number"])){
            $info = "nice! {$value1} is a palindrome number!";
        }else{
            $info=$flag;
        }
    }
}
echo $info;
'''

阅读代码可以发现,我们可以post提交一个number.
且这个number满足下面这三个条件

  1. 不为空,且不能是一个数值型数字,包括小数。(由is_numeric函数判断)
  2. 不能是一个回文数。(is_palindrome_number判断)
  3. 该数的反转的整数值应该和它本身的整数值相等。

接下来就是如何绕过并且获得flag了。

  1. 首先要绕过is_numberic函数
    实验了一波发现is_numeric函数对于空字符%00,无论是%00放在前后都可以判断为非数值,而%20空格字符只能放在数值后
  2. 如何绕过条件2和3呢,这里可以利用intval函数溢出绕过
    Intval最大的值取决于操作系统。 32 位系统最大带符号的 integer 范围是 -2147483648 到 2147483647。举例,在这样的系统上, intval(‘1000000000000’) 会返回 2147483647。64 位系统上,最大带符号的 integer 值是 9223372036854775807。

3.所以我们可以构造2147483647%00来绕过这3个条件

python3代码获取flag

# -*- coding:utf-8 -*-
import requests
#2147483647后面有空格
data={"number":"2147483647 "}
html=requests.post("http://ctf5.shiyanbar.com/web/PHP/index.php",data=data)
print(html.text)

控制台打印:

FLAG{2dd8711082fe24c19ae8}

通过上面我们知道服务器的操作系统是32位的,所以我们构造2147483647就可以同时满足2,3条件

Last modification:June 11th, 2018 at 09:31 pm
If you think my article is useful to you, please feel free to appreciate

Leave a Comment