Closed xiaozhu1337 closed 4 years ago
感谢你的问题提交,的确存在该问题,看了一天初步判断是更新后7.3版本在$_SESSION处出问题,目前还未想到解决方案,待后续更新解决
@xiaozhu1337 不好意思,没来得及看,fork
好像删除了,如果解决了,不妨发一个Pull requests
给我,感谢~
php7.2.24里tunnl.php也有一样的问题。
`
72 session_write_close();
73
74 while ($_SESSION["run"])
75 {
76 $readBuff = "";
77 @session_start();
78 $writeBuff = $_SESSION["writebuf"];//这里一直获取不到内容,上面的session_start去掉忽略报错也会一直报错
79 $_SESSION["writebuf"] = "";
80 session_write_close();
81 if ($writeBuff != "")
`
@sureiam 感谢你的测试反馈!v2.0版本正在开发测试,架构会大改应该会连同解决该问题的
不好意思忘记回你了。我基于原版的已经改好了,方便加个好友吗?这是我邮箱 NTM5OTEzMzhAMTYzLmNvbQo= 我改的几个地方
reGeorgSocksProxy.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import logging
import urllib3
from threading import Thread
import socket
import struct
# import os
from time import sleep
from urllib3.contrib.socks import SOCKSProxyManager
from socketserver import StreamRequestHandler, ThreadingTCPServer
from libs.loggings import log, transferLog, LEVEL
from libs.exception import SocksCmdNotImplemented
from libs.exception import SocksProtocolNotImplemented
from libs.exception import RemoteConnectionFailed
from libs.exception import DomainNameResolveFailed
from libs.utils import choose_useragent
from libs.utils import parse_args
from libs.utils import HeaderObfuscator
from libs.socks5server import ReuseServer
# Constants
SOCKTIMEOUT = 5
VER = b"\x05"
METHOD = b"\x00"
SUCCESS = b"\x00"
REFUSED = b"\x05"
# SOCKFAIL = b"\x01"
# NETWORKFAIL = b"\x02"
# HOSTFAIL = b"\x04"
# TTLEXPIRED = b"\x06"
# UNSUPPORTCMD = b"\x07"
# ADDRTYPEUNSPPORT = b"\x08"
# UNASSIGNED = b"\x09"
BASICCHECKSTRING = "the page not found"
# Globals
READBUFSIZE = 1024
USERAGENT = choose_useragent()
class reGeorgSession(StreamRequestHandler):
def handle(self):
self.cookie = None
# self.connection
self.url = args.url
self.dns_cache = {}
try:
if self.handle_socks():
log.debug("Staring reader")
r = Thread(target=self.reader, args=())
r.start()
log.debug("Staring writer")
w = Thread(target=self.writer, args=())
w.start()
r.join()
w.join()
except SocksCmdNotImplemented as scni:
log.error('SocksCmdNotImplemented: ' + scni)
return
except SocksProtocolNotImplemented:
log.error('SocksProtocolNotImplemented')
return
except DomainNameResolveFailed as dnf:
log.error("DNS Query Error: [%s]" % (dnf, ))
return
except Exception as e:
logging.exception(e)
self.closeRemoteSession()
return
def handle_socks(self):
# This is where we setup the socks connection
ver = self.connection.recv(1)
if ver == b"\x05":
log.debug('socks5 protocal version: ')
# hexdump(ver)
return self.parse_socks5()
else:
log.error('wrong socks5 protocal version: ')
# hexdump(ver)
return False
def gethostbyname(self, host):
host = host.decode()
if host in self.dns_cache:
return self.dns_cache[host]
ipaddr = None
headers = {"X-CMD": "DNS", 'User-Agent': USERAGENT}
headers = HeaderObfuscator(headers)
response = request_pool.request(
'POST', self.url, headers=headers, body=host)
if response.status == 200 and response.data.decode() != host:
log.info("DNS Query OK: [%s] <---> [%s]" % (host, response.data.decode()))
ipaddr = response.data.decode()
else:
raise DomainNameResolveFailed(host)
self.dns_cache[host] = ipaddr
return ipaddr
def parse_socks5(self):
sock = self.connection
log.debug("SocksVersion5 detected")
nmethods, methods = (sock.recv(1), sock.recv(1))
sock.sendall(VER + METHOD)
ver = sock.recv(1)
if ver == b"\x02": # this is a hack for proxychains
ver, cmd, rsv, atyp = (sock.recv(1), sock.recv(1), sock.recv(1), sock.recv(1))
else:
cmd, rsv, atyp = (sock.recv(1), sock.recv(1), sock.recv(1))
target = None
targetPort = None
log.debug('begin deal socks5 - 2 - Connection')
if atyp == b"\x01": # IPv4
# Reading 6 bytes for the IP and Port
target = sock.recv(4)
targetPort = sock.recv(2)
target = socket.inet_ntoa(target)
elif atyp == b"\x03": # Hostname
targetLen = ord(sock.recv(1)) # hostname length (1 byte)
target = sock.recv(targetLen)
targetPort = sock.recv(2)
target = self.gethostbyname(target) # 放到web端去解析
elif atyp == b"\x04": # IPv6
target = sock.recv(16)
targetPort = sock.recv(2)
target = socket.inet_ntop(socket.AF_INET6, target)
# targetPort = ord(targetPort[0]) * 256 + ord(targetPort[1])
self.port = struct.unpack('>H', targetPort)[0]
self.target = target
if cmd == b"\x02": # BIND
raise SocksCmdNotImplemented("Socks5 - BIND not implemented")
elif cmd == b"\x03": # UDP
raise SocksCmdNotImplemented("Socks5 - UDP not implemented")
elif cmd == b"\x01": # CONNECT
serverIp = socket.inet_aton(target)
self.cookie = self.init_session()
if self.cookie:
self.setupRemoteSession()
sock.sendall(VER + SUCCESS + b"\x00" + b"\x01" + serverIp + targetPort)
return True
else:
sock.sendall(VER + REFUSED + b"\x00" + b"\x01" + serverIp + targetPort)
raise RemoteConnectionFailed(
"[%s:%d] Remote failed" % (self.target, self.port))
else:
raise SocksCmdNotImplemented("Socks5 - Unknown CMD")
def init_session(self):
log.debug('begin init session')
headers = {"X-CMD": "INIT", 'User-Agent': USERAGENT, "X-TARGET": self.target,
"X-PORT": self.port,}
headers = HeaderObfuscator(headers)
cookie = None
response = request_pool.request(
'POST', args.url, headers=headers, body="")
if response.status == 200:
status = response.getheader("x-status")
if status == "OK":
cookie = response.getheader("set-cookie")
log.info("[%s:%d] HTTP [200]: cookie [%s]" %
(self.target, self.port, cookie))
else:
if response.getheader("X-ERROR") is not None:
log.error(response.getheader("X-ERROR"))
else:
log.error("[%s:%d] HTTP [%d]: [%s]" % (
self.target, self.port, response.status,
response.getheader("X-ERROR")))
log.error("[%s:%d] RemoteError: %s" %
(self.target, self.port, response.data.decode()))
return cookie
def setupRemoteSession(self):
try:
log.debug('run setupRemoteSession')
headers = {"X-CMD": "CONNECT", "X-TARGET": self.target,
"X-PORT": self.port, 'User-Agent': USERAGENT, "Cookie": self.cookie}
headers = HeaderObfuscator(headers)
response = request_pool.request(
'POST', args.url, headers=headers, body="", timeout=0.1)
except:
pass
def closeRemoteSession(self):
headers = {"X-CMD": "DISCONNECT", "Cookie": self.cookie,
"User-Agent": USERAGENT}
headers = HeaderObfuscator(headers)
params = ""
response = request_pool.request("POST", args.url, params, headers)
if response.status == 200:
log.info("[%s:%d] Connection Terminated" %
(self.target, self.port))
def reader(self):
while True:
try:
if not self.connection:
break
headers = {"X-CMD": "READ", "Cookie": self.cookie,
"Connection": "Keep-Alive", 'User-Agent': USERAGENT}
headers = HeaderObfuscator(headers)
# url_cmd_args = "?cmd=read"
# if(withoutUrlParams):
# url_cmd_args = ""
response = request_pool.request(
'POST', self.url, headers=headers, body="")
data = None
if response.status == 200:
status = response.getheader("x-status")
if status == "OK":
data = response.data
# Yes I know this is horrible, but its a quick fix to
# issues with tomcat 5.x bugs that have been reported,
# will find a propper fix laters
try:
if response.getheader("server").find(
"Apache-Coyote/1.1") > 0:
data = data[:len(data) - 1]
except Exception:
pass
if data is None:
data = ""
else:
data = None
log.info(("[%s:%d] HTTP [%d]: Status: [%s]: "
"Message [%s] reader Shutting down") % (
self.target, self.port, response.status, status,
response.getheader("X-ERROR")))
log.info("read complete")
else:
log.error("[%s:%d] HTTP [%d]: reader Shutting down" %
(self.target, self.port, response.status))
if data is None:
# Remote socket closed
break
if len(data) == 0:
sleep(0.1)
continue
transferLog.info("[%s:%d] <<<< [%d]" %
(self.target, self.port, len(data)))
self.connection.send(data)
except Exception as ex:
raise ex
self.closeRemoteSession()
log.debug("[%s:%d] Closing localsocket" % (self.target, self.port))
try:
self.connection.close()
except Exception:
log.debug("[%s:%d] Localsocket already closed" %
(self.target, self.port))
def writer(self):
while True:
try:
self.connection.settimeout(1)
data = self.connection.recv(READBUFSIZE)
if not data:
break
headers = {"X-CMD": "FORWARD", "Cookie": self.cookie,
"Content-Type": "application/octet-stream",
"Connection": "Keep-Alive",
'User-Agent': USERAGENT}
headers = HeaderObfuscator(headers)
response = request_pool.request(
'POST', self.url, headers=headers, body=data)
if response.status == 200:
status = response.getheader("x-status")
if status == "OK":
if response.getheader("set-cookie") is not None:
self.cookie = response.getheader("set-cookie")
else:
log.error(("[%s:%d] HTTP [%d]: Status: [%s]: "
"Message [%s] writer Shutting down") % (
self.target, self.port, response.status, status,
response.getheader("x-error")))
break
else:
log.error("[%s:%d] HTTP [%d]: writer Shutting down" %
(self.target, self.port, response.status))
break
transferLog.info("[%s:%d] >>>> [%d]" %
(self.target, self.port, len(data)))
except socket.timeout:
continue
except Exception:
break
self.closeRemoteSession()
log.debug("[%s:%d] Closing localsocket" % (self.target, self.port))
try:
self.connection.close()
except Exception:
log.debug("Localsocket already closed")
def askGeorg():
headers = {'User-Agent': USERAGENT}
r = request_pool.request('GET', args.url, headers=headers)
if r.status == 200:
if BASICCHECKSTRING == r.data.decode():
log.info("Georg says, 'All seems fine'")
return True
return False
if __name__ == '__main__':
log.setLevel(logging.DEBUG)
args = parse_args()
READBUFSIZE = args.read_buff_size
if args.proxy:
log.info("Use proxy to connect to target: " + args.proxy)
if args.proxy.startswith('http'):
request_pool = urllib3.ProxyManager(args.proxy)
elif args.proxy.startswith('socks5'):
request_pool = SOCKSProxyManager(args.proxy)
else:
request_pool = urllib3.PoolManager()
if args.verbose in LEVEL:
log.setLevel(LEVEL[args.verbose])
log.info("Log Level set to [%s]" % args.verbose)
if args.insecure:
log.info("Skip SSL certificate validation")
urllib3.disable_warnings()
log.info("Checking if Georg is ready")
if not askGeorg():
log.info("Georg is not ready, please check url")
exit()
log.info("Starting socks server [%s:%d], tunnel at [%s]" % (
args.listen_on, args.listen_port, args.url))
try:
with ReuseServer((args.listen_on, args.listen_port), reGeorgSession) as server:
server.serve_forever()
except KeyboardInterrupt:
log.info('user interrupt')
tunnel.nosocket.php
<?php
ini_set("allow_url_include", true);
ini_set("allow_url_fopen", true);
error_reporting(E_ERROR | E_PARSE);
function getHeader()
{
$headers = array();
foreach ($_SERVER as $key => $value) {
if ('HTTP_' == substr($key, 0, 5)) {
$headers[str_replace('_', '-', substr($key, 5))] = $value;
}
if (isset($_SERVER['PHP_AUTH_DIGEST'])) {
$header['AUTHORIZATION'] = $_SERVER['PHP_AUTH_DIGEST'];
} elseif (isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])) {
$header['AUTHORIZATION'] = base64_encode($_SERVER['PHP_AUTH_USER'] . ':' . $_SERVER['PHP_AUTH_PW']);
}
if (isset($_SERVER['CONTENT_LENGTH'])) {
$header['CONTENT-LENGTH'] = $_SERVER['CONTENT_LENGTH'];
}
if (isset($_SERVER['CONTENT_TYPE'])) {
$header['CONTENT-TYPE'] = $_SERVER['CONTENT_TYPE'];
}
}
return $headers;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
set_time_limit(0);
$headers = getHeader();
switch ($headers['X-SECURE']) {
case "INIT":
{
list($target, $port) = explode(":", $headers['X-AUTH']);
$target = base64_decode($target);
$port = (int) base64_decode($port);
$res = fsockopen($target, $port);
if ($res === false) {
header('X-STATUS: FAIL');
header('X-ERROR: Failed connecting to target');
return;
}
fclose($res);
@session_start();
$_SESSION["run"] = true;
$_SESSION["writebuf"] = "";
$_SESSION["readbuf"] = "";
session_write_close();
header('X-STATUS: OK');
header("Connection: close");
}
break;
case "CONNECT":
{
list($target, $port) = explode(":", $headers['X-AUTH']);
$target = base64_decode($target);
$port = (int) base64_decode($port);
$res = fsockopen($target, $port);
if ($res === false) {
header('X-STATUS: FAIL');
header('X-ERROR: Failed connecting to target');
return;
}
stream_set_blocking($res, false);
ignore_user_abort(true);
@session_start();
session_write_close();
while ($_SESSION["run"]) {
if (empty($SESSION["writebuf"])) {
usleep(50000);
}
$readBuff = "";
@session_start();
$writeBuff = $_SESSION["writebuf"];
$_SESSION["writebuf"] = "";
session_write_close();
if ($writeBuff != "") {
stream_set_blocking($res, false);
$i = fwrite($res, $writeBuff);
if ($i === false) {
@session_start();
$_SESSION["run"] = false;
session_write_close();
header('X-STATUS: FAIL');
header('X-ERROR: Failed writing socket');
}
}
stream_set_blocking($res, false);
while ($o = fgets($res, 10)) {
if ($o === false) {
@session_start();
$_SESSION["run"] = false;
session_write_close();
header('X-STATUS: FAIL');
header('X-ERROR: Failed reading from socket');
}
$readBuff .= $o;
}
if ($readBuff != "") {
@session_start();
$_SESSION["readbuf"] .= $readBuff;
session_write_close();
}
}
fclose($res);
}
break;
case "DISCONNECT":
{
@session_start();
$_SESSION["run"] = false;
session_write_close();
return;
}
break;
case "READ":
{
@session_start();
$readBuffer = $_SESSION["readbuf"];
$_SESSION["readbuf"] = "";
session_write_close();
if ($_SESSION["run"]) {
header('X-STATUS: OK');
header("Connection: Keep-Alive");
echo $readBuffer;
return;
} else {
header('X-STATUS: FAIL');
header('X-ERROR: RemoteSocket read failed');
return;
}
}
break;
case "FORWARD":
{
@session_start();
session_write_close();
if (!$_SESSION["run"]) {
header('X-STATUS: FAIL');
header('X-ERROR: No more running, close now');
return;
}
header('Content-Type: application/octet-stream');
$rawPostData = file_get_contents("php://input");
if ($rawPostData) {
@session_start();
$_SESSION["writebuf"] .= $rawPostData;
session_write_close();
header('X-STATUS: OK');
header("Connection: Keep-Alive");
return;
} else {
header('X-STATUS: FAIL');
header('X-ERROR: POST request read failed');
}
}
break;
case "DNS":
{
$rawPostData = file_get_contents("php://input");
$dns = gethostbyname($rawPostData);
echo $dns;
}
}
} else {
exit("the page not found");
}
@junmoxiao 方便
PHP >= 7.1 环境的BUG 已经修复,获取最新的 v1.5.0 版本使用~
php7.0及以下可以正常使用,但是php7.3会卡住 burp抓包的话会看到READ指令一直读不到返回