MisConfig HTTP Proxy Scanner是一个web漏洞扫描器,用于扫描发现配置不当的HTTP正反代理:
- 错误配置的外网反向代理,内网系统被意外暴露到外网
- 错误配置的外网正向代理,攻击者可以暴力枚举内网域名,访问内网的生产运维系统、办公系统
本项目地址:https://github.com/lijiejie/MisConfig_HTTP_Proxy_Scanner
MisConfig HTTP Proxy Scanner是一个web漏洞扫描器,用于扫描发现配置不当的HTTP正反代理:
本项目地址:https://github.com/lijiejie/MisConfig_HTTP_Proxy_Scanner
在一个多年前的历史项目中,我们发现,django cron job出现了卡死现象。 应用逻辑没有被完整执行直到结束,程序已经僵死了。
调试分析卡死的Python进程,请参考: https://wiki.python.org/moin/DebuggingWithGdb
通过调试进程,我们发现应用卡死在了
Domain.objects.bulk_update(update_domain_list, [‘ips_from_fuxi’])
如下图所示:
回到源代码中,在上下文找到了原因,原来,需要bulk update的列表,没有在循环体内部正确被初始为空。 需要update的列表出现了持续增长,最终导致bulk update 超大的列表,卡死应用程序。
正确初始化列表,即可解决bulk update hung死的问题。
Python父进程通过logging.basicConfig,设定日志文件的路径,子进程再次通过basicConfig设定另一个新的路径。这个操作,在Windows系统和Linux下表现不一致。
区别在于,Windows下将打开不同的文件句柄,写入2个不同的文件 。而在Linux下,则config看起来无效,子进程和父进程使用同一个文件描述符,第二次config无效。(解决的方法文末补充)
import logging
import os
import multiprocessing
import threading
cwd = os.getcwd()
def set_log(log_file_path):
logging.basicConfig(filename=log_file_path,
filemode='a+',
format='%(message)s',
level=logging.INFO)
logging.info('%s: %s' % (logging.root, log_file_path) )
def test_func():
set_log(os.path.join(cwd, 'test2.log'))
class TestThread(threading.Thread):
def __init__(self):
p = multiprocessing.Process(target=test_func)
p.start()
if __name__ == '__main__':
set_log(os.path.join(cwd, 'test.log'))
TestThread()
这个程序在Windows的执行结果是
logging.RootLogger object at 0x0000000002610C18>: C:\test\test.log
logging.RootLogger object at 0x000000000276C7B8>: C:\test\test2.log
可以看到,日志写入了两个不同的文件。并且Logger ID不一样
在Linux下的执行结果是
[root@cyberivy-web-dev002-whdx test]# ls *.log
test.log
[root@cyberivy-web-dev002-whdx test]# cat test.log
: /root/test/test.log
: /root/test/test2.log
两个进程的日志都写到了test.log中。 并且 Logger ID 和 fd是一样的
子进程在set_log之前,先 reload(logging), test_func变成
def test_func():
reload(logging)
set_log(os.path.join(cwd, 'test2.log'))
修改之后,在Linux执行,日志同样会写入不同的文件
[root@cyberivy-web-dev002-whdx test]# ls *.log
test2.log test.log
[root@cyberivy-web-dev002-whdx test]# cat *.log
logging.RootLogger object at 0x1df28d0>: /root/test/test2.log
logging.RootLogger object at 0x1d80bd0>: /root/test/test.log
昨天群里,大家聊到了一个面试题,关于 浅复制 (shallow copy )的。 相信很多人都写过类似的错误代码。
items = list(range(1, 11)) while items: tmp_items = items # tmp_items referred to items for i in tmp_items: items.remove(i) print items
通过一个for loop遍历删除列表中的元素(这里示例1到10)。最终执行的结果是
[2, 4, 6, 8, 10] [4, 8] [8] []
可以看到,每次循环,只有奇数位的数字被从列表移除了,偶数位的数字被保留下来。
这跟列表是一个链表结构有关系。
第二,这里的 tmp_items = items 是浅复制, tmp_items只是items的引用
迭代器在遍历列表的时候,从head开始
head -> pointer1 -> 1 pointer2 -> 2 ... pointer10 -> 10
循环开始,首先删除第一个元素(1),此时,对应的head指针移动到指针2
head -> pointer2 -> 2 ... pointer10 -> 10
继续遍历时, head->next 指向的是已经是元素3。 于是,最终只有奇数位置的元素被移除了。
这两天优化端口扫描脚本,在获取HTTP页面内容时,发现requests.get hang住了(之前httplib不会)。
requests.get 提供了超时参数timeout,但在实际使用过程中,仍发现get请求可能被hang住。
原因在于非HTTP Server,response中一直没有出现换行符\n,导致_read_status()在获取状态码的时候就hang住了。
一个简单的解决方法,可以创建新的线程,示例代码参考如下,这部分代码是无法直接工作的:
def do_get_thread(url, ret): try: headers = { 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 ' '(KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25', 'Range': 'bytes=0-10240', 'Connection': 'Close'} ret.append(requests.get(url, headers=headers, timeout=(4, 30))) except: pass def get_http_title(ip, port, service, log_queue): if service.lower().find('https') >= 0 or service.lower().find('ssl') >= 0: service = 'https' else: service = 'http' url = '%s://%s:%s' % (service, ip, port) msg = 'Get http title %s' % url log_queue.put(msg) try: start_time = time.time() ret = [] t = threading.Thread(target=do_get_thread, args=(url, ret)) t.daemon = True t.start() while t.isAlive(): if time.time() - start_time > 31: log_queue.put('[get_http_title timed out] %s' % url) return {}, '' else: time.sleep(1.0) if not ret: return {}, '' resp = ret[0] headers = resp.headers m = re.search('<title>(.*?)</title>', resp.text, re.IGNORECASE) http_title = m.group(1).strip() if m else '' if http_title: http_title = decode_response_text(http_title) else: http_title = resp.text.replace('\n', ' ').strip()[0:200] return headers, http_title except requests.exceptions.RequestException, e: pass except Exception, e: log_queue.put('[get_http_title.exception] %s' % str(e)) return {}, ''
.DS_Store是Mac下Finder用来保存如何展示 文件/文件夹 的数据文件,每个文件夹下对应一个。
如果开发/设计人员将.DS_Store上传部署到线上环境,可能造成文件目录结构泄漏,特别是备份文件、源代码文件。
ds_store_exp 是一个.DS_Store 文件泄漏利用脚本,它解析.DS_Store文件并递归地下载文件到本地: https://github.com/lijiejie/ds_store_exp
DS_Store parser is based on ds_store 1.1.0 。
python ds_store_exp.py http://hd.zj.qq.com/themes/galaxyw/.DS_Store hd.zj.qq.com/ └── themes └── galaxyw ├── app │ └── css │ └── style.min.css ├── cityData.min.js ├── images │ └── img │ ├── bg-hd.png │ ├── bg-item-activity.png │ ├── bg-masker-pop.png │ ├── btn-bm.png │ ├── btn-login-qq.png │ ├── btn-login-wx.png │ ├── ico-add-pic.png │ ├── ico-address.png │ ├── ico-bm.png │ ├── ico-duration-time.png │ ├── ico-pop-close.png │ ├── ico-right-top-delete.png │ ├── page-login-hd.png │ ├── pic-masker.png │ └── ticket-selected.png └── member ├── assets │ ├── css │ │ ├── ace-reset.css │ │ └── antd.css │ └── lib │ ├── cityData.min.js │ └── ueditor │ ├── index.html │ ├── lang │ │ └── zh-cn │ │ ├── images │ │ │ ├── copy.png │ │ │ ├── localimage.png │ │ │ ├── music.png │ │ │ └── upload.png │ │ └── zh-cn.js │ ├── php │ │ ├── action_crawler.php │ │ ├── action_list.php │ │ ├── action_upload.php │ │ ├── config.json │ │ ├── controller.php │ │ └── Uploader.class.php │ ├── ueditor.all.js │ ├── ueditor.all.min.js │ ├── ueditor.config.js │ ├── ueditor.parse.js │ └── ueditor.parse.min.js └── static ├── css │ └── page.css ├── img │ ├── bg-table-title.png │ ├── bg-tab-say.png │ ├── ico-black-disabled.png │ ├── ico-black-enabled.png │ ├── ico-coorption-person.png │ ├── ico-miss-person.png │ ├── ico-mr-person.png │ ├── ico-white-disabled.png │ └── ico-white-enabled.png └── scripts ├── js └── lib └── jquery.min.js 21 directories, 48 files