วันอาทิตย์ที่ 15 สิงหาคม พ.ศ. 2553
วันศุกร์ที่ 13 สิงหาคม พ.ศ. 2553
Crack password Oracle database ตั้งแต่ 8i ถึง 11g
อันนี้ยกเครดิตให้ Blog Oracle and Java นะครับเห็นว่าน่าสนใจ
คงเป็นที่ทราบกันดีว่า password ที่เราเก็บไว้ในฐานข้อมูลเพื่อไว้ใช้ในการทำ authentication (ระบุตัวตน) นั้นในปกติการเก็บ password นั้นเราจะไม่เก็บกันตรง ๆ เช่นเราตั้ง password ว่า siam เวลาเก็บลงใน database จริงแล้วจะไม่เก็บคำว่า siam โดยคำว่า siam นั้นจะถูกแปลงเป็นคำอื่น ๆ โดยจะไม่เหลือเค้าโครงเดิมเลย โดยการแปลงนี้ก็มี algorithm (วิธีการ) ต่าง ๆ มากมายกันไปซึ่งเราจะเรียกวิธีการนี้ว่า การ hash password แต่ว่ามันอาจจะยังไม่เพียงพอ ทำให้บางคนนั้นก็ได้เพิ่ม keyword เข้าไปผสมลงใน password ก่อนจะผ่านกรรมวิธีการ hash password เพื่อให้แก้ไขได้ยากยิ่งขึ้นซึ่งเราเรียก keyword ที่เราไปผสม password นี้ว่า salt (ซึ่งเป็นตัวเดียวกันกับคำว่า เกลือ ครับ ก็เหมือนเวลาที่เรากินอาหารแล้วอยากให้อาหารอร่อยขึ้นเราก็เหยาะเกลือลงไป แต่ในที่นี้เพื่อที่จะทำให้การถอด password ยากขึ้น)
ซึ่งวิธีการนี้อาจะนำไปใช้ร่วมกับข้อมูลที่ป็นความลับ เพื่อทำการเข้ารหัส เพื่อไม่ให้คนอื่นที่สามารถทะลุทะลวงล้วงเข้ามาในฐานข้อมูลของเรา นั้นอ่านข้อมูลนี้ได้ ถึงได้ข้อมูลมาอาจจะต้องมานั่งเสียเวลาในการแก้ algorithm ตัวนี้มากขึ้น แต่ไม่น่าเชื่อว่าเจ้าแห่ง database อย่าง Oracle นั้น password ที่ถูกทำการ hash ไว้แล้วนั้นจะถูกแก้ออกมาได้อย่างง่ายดายและที่สำคัญไม่ใช่มีแค่ tool เดียวเท่านั้นที่สามารถแก้ได้ซึ่งแสดงออกมาดังตารางด้านล่างดังนี้ จะเห็นได้ว่าโปรแกรมที่ชื่อ worrauthbf version 0.2 นั้นใช้เวลาแค่ 3s วินาทีเท่านั้นเอง แต่ว่าที่เร็วกว่านั้นก็เพราะใช้ CPU ประมวลผลแบบ Dualcore แต่ถ้าเป็นแบบที่ไม่ใช่ CPU ที่เป็นแบบ Dualcore หละก็ orabf 0.7.6 จะเร็วกว่าครับ แต่ว่า password ที่ crack ได้เร็วนั้นขึ้นอยู่กับว่าจำนวน password นั้นยาวหรือสั้นมากแค่ไหนด้วยครับ ซึ่งถ้าใครอยากลองว่าจะ crack ได้จริงหรือเปล่าลองไปโหลดโปรแกรมที่เว็บนี้เลยครับ
เอาหละโม้มามากแล้วลงมือทำกันจริงๆ กันดีกว่าเดี๋ยวจะหาว่าผมมาโม้อีกโดน schema ที่ผมจะเอามาลองนั้นคือ schema HR โดยผมจะเปลี่ยน password เป็น “HRACLE” ตัวใหญ่หมดครับและ database ที่ลองคือ Oracle 11g R1 ครับโดยตอนแรกนั้นให้เราไปติดตั้งโปรแกรม worrauthbf version 0.2 ลงในเครื่องก่อนครับหลังจากนั้นก็ไปทำตามขึ้นตอนนี้ครับ
- เตรียมข้อมูลเพื่อที่จะทำการถอด password ที่ทำการ hash แล้วให้กลับมาเป็น password ปกติโดยให้เรา login เข้าไปใน database ก่อนโดยเราต้องมีสิทธิ์เป็น admin ด้วยนะครับไม่งั้นดึงข้อมูลไม่ได้ โดยเราต้องใช้ข้อมูลตามรูปแบบดังนี้ครับ
username:password hash:11g password hash:sid:server:
username :: นั้นเป็นชื่อของ username ที่เราต้องการจะแก้ hash password ครับ
password hash :: อันนี้คือ password ที่ถูกทำการ hash แล้วครับ
11g password hash :: ที่นี้ก็คือ salt ที่ผมบอกนั้นเองครับโดย salt ตัวนี้จะไม่ซ้ำกันตามแต่ที่ระบบจะสร้างขึ้นมา
sid :: คือชื่อของ Oracle database instance เช่น orcl
server :: นั้นเป็นชื่อของ server ที่ database นั้นอยู่ครับ
หมายเหตุ ในแต่ละ version ของ database นั้นอาจจะต้องการ parameter ที่แตกต่างกันเพื่อที่จะใช้เป็นข้อมูลที่จะทำการแก้ hash password ครับโดย salt นี้ Oracle เพิ่งจะมาเริ่มมีใน Oracle database 11g ครับ
แต่ ว่าโชคดีครับที่เราไม่ต้องไปหา parameter เหล่านี้เองให้เราใช้คำสั่ง sql นี้ครับแต่ต้องอย่าลืมว่าต้อง login เป็น username ที่มีสิทธิ์เป็น admin ครับ ดังนี้
select u.name||':'||u.password||':'||substr(u.spare4,3,63)||':'||d.name||':'||
sys_context('USERENV','SERVER_HOST')||':'
from sys.user$ u, sys.V_$DATABASE d
where u.type#=1;
ซึ่งเมื่อ run ใน database ที่ผมทดสอบผลที่ได้คือ
HR:E313D0596944C41D:6E7036A1EB587DCCE6D84DFF73E6F80207BB8F980B5643D01AE23F747FAC:ORCL:vista: - หลังจากนั้นก็จะใช้ command prompt run โปรแกรมเพื่อที่จะทำการ crack hash password ตามขั้นตอนนี้ครับ
- เข้าไปใน home directory ที่เราติดตั้ง worrauthbf version 0.2 ไว้
- run คำสั่ง woraauthbf แล้วตามด้วย parameter ต่างๆ ดังนี้
- -p :: คือชื่อ file ที่เก็บข้อมูลที่เราเตรียมไว้ข้างต้นซึ่งในที่นี้คือ 11gHash.txt
- -t :: ในที่นี้คือเป็นการระบุว่า hash password ที่เราต้องต้องการแก้นั้นเป็น version อะไรในที่นี้ให้ระบุว่า 11g10g
- -c :: เป็นการระบุว่า password ที่เราจะแก้ hash password นั้นมี character ชนิดใดบ้างซึ่งแบ่งได้เป็น สามชนิดคือ
- "alpha" คือ [A-Z]
- "alphanum" คือ [A-Z0-9]
"all" คือ [A-Z0-9!@#$%^&*()-_+=~`[]{}|\:;"'<>,.?/]
ซึ่งให้เราเลือกว่าทดลองตามความเหมาะสมครับถ้าสมมติเรารู้ว่า password เรามีแค่ตัวอักษรและตัวอักษรปนกันก็ให้เลือก alphanum ส่วนในที่นี้เรารู้อยู่แล้วว่า password ของเรามีตัวอักษรอย่างเดียวก็เลือก alpha ครับ- -d :: นั้นเป็นการระบุ dictionary file ครับซึ่งจะระบุหรือไม่ระบุก็ได้แต่ถ้าเราระบุมาก็จะทำให้แก้ hash password ได้เร็วขึ้นมากแต่ในที่นี้ผมไม่ใส่นะครับ
ที่จริง parameter นั้นมากกว่านี้อีกซึ่งถ้าใครสนใจก็ลองข้าไปดูที่เว็บนี้ครับ
หมายเหตุ คือผมลองแก้ hash password หลายตัวพร้อมกันครับผลที่ได้กว่าจะแก้ได้แต่ละตัวช้ามากครับ
สรุป
ถ้าไม่มี dictionary file ช้ามากถึงมากที่สุด
ใช้ กับ password ที่เป็นตัวใหญ่ได้อย่างเดียวนั้นก็คือถ้าเป็น 11g แล้วตั้ง password case sensitive หละก็จะแก้ไม่ได้ดังนั้นถึงจะบอกว่ารองรับ 11g แต่ก็ไม่เต็มร้อยครับต้องรอ version ใหม่ดีกว่า
ความยาวของ password รองรับแค่ 10 ตัวอักษรเท่านั้นถือว่าน้อยมากซึ่งตอนนี้มีตัว crack hash password ของ database Oracle ออก version ใหม่มาคือ checkpwd ซึ่งผมก็ยังไม่ได้ลองครับลองไปเล่นดูตามนี้เลยครับ http://www.red-database-security.com/software/checkpwd200a12.zip
อ้างอิง
http://www.petefinnigan.com/weblog/archives/00001103.htm
http://soonerorlater.hu/index.khtml?article_id=513
ปัญหาของการ Query Data กับ Index data type ที่เป็นรูปแบบวันที่
CONNECT BY คำสังขั้นเทพที่ไปเจอมา น่าจะมีประโยชน์กับการทำงานอยู่บ้าง
START WITH and CONNECT BY in Oracle SQL
select ... start with initial-condition connect by nocycle recurse-condition
select ... connect by recurse-condition
select ... start with initial-condition connect by nocycle recurse-condition
select ... connect by recurse-condition
recurse-condition
can make use of the keyword prior: connect by
prior foo = bar
A simple example
set feedback off
create table test_connect_by (
parent number,
child number,
constraint uq_tcb unique (child)
);
insert into test_connect_by values ( 5, 2);
insert into test_connect_by values ( 5, 3);
insert into test_connect_by values (18,11);
insert into test_connect_by values (18, 7);
insert into test_connect_by values (17, 9);
insert into test_connect_by values (17, 8);
insert into test_connect_by values (26,13);
insert into test_connect_by values (26, 1);
insert into test_connect_by values (26,12);
insert into test_connect_by values (15,10);
insert into test_connect_by values (15, 5);
insert into test_connect_by values (38,15);
insert into test_connect_by values (38,17);
insert into test_connect_by values (38, 6);
insert into test_connect_by values (null, 38);
insert into test_connect_by values (null, 26);
insert into test_connect_by values (null, 18);
select lpad(' ',2*(level-1)) || to_char(child) s
from test_connect_by
start with parent is null
connect by prior child = parent;
38
15
10
5
2
3
17
9
8
6
26
13
1
12
18
11
7
Interpreting connect by statements
start with ... connect by
select statement be read and interpreted? If Oracle encounters such an SQL statement, it proceeds as described in the following pseude code. for rec in (select * from some_table) loop
if FULLFILLS_START_WITH_CONDITION(rec) then
RECURSE(rec, rec.child);
end if;
end loop;
procedure RECURSE (rec in MATCHES_SELECT_STMT, parent_id IN field_type) is
begin
APPEND_RESULT_LIST(rec);
for rec_recurse in (select * from some_table) loop
if FULLFILLS_CONNECT_BY_CONDITION(rec_recurse.id, parent_id) then
RECURSE(rec_recurse,rec_recurse.id);
end if;
end loop;
end procedure RECURSE;
Pruning branches
create table prune_test (
parent number,
child number
);
insert into prune_test values (null, 1);
insert into prune_test values (null, 6);
insert into prune_test values (null, 7);
insert into prune_test values ( 1, 12);
insert into prune_test values ( 1, 14);
insert into prune_test values ( 1, 15);
insert into prune_test values ( 6, 61);
insert into prune_test values ( 6, 63);
insert into prune_test values ( 6, 65);
insert into prune_test values ( 6, 69);
insert into prune_test values ( 7, 71);
insert into prune_test values ( 7, 74);
insert into prune_test values ( 12, 120);
insert into prune_test values ( 12, 124);
insert into prune_test values ( 12, 127);
insert into prune_test values ( 65, 653);
insert into prune_test values ( 71, 712);
insert into prune_test values ( 71, 713);
insert into prune_test values ( 71, 715);
insert into prune_test values ( 74, 744);
insert into prune_test values ( 74, 746);
insert into prune_test values ( 74, 748);
insert into prune_test values ( 712,7122);
insert into prune_test values ( 712,7125);
insert into prune_test values ( 712,7127);
insert into prune_test values ( 748,7481);
insert into prune_test values ( 748,7483);
insert into prune_test values ( 748,7487);
select
lpad(' ', 2*level) || child
from
prune_test
start with
parent is null
connect by
prior child=parent
and parent not in (1, 71);
1
6
61
63
65
653
69
7
71
74
744
746
748
7481
7483
7487
Do two items stand in a ancestor descendant relationship
set feedback off
drop table parent_child;
create table parent_child(parent_ varchar2(20), child_ varchar2(20));
insert into parent_child values (null, 'a')
insert into parent_child values ( 'a', 'af');
insert into parent_child values ( 'a', 'ab');
insert into parent_child values ( 'a', 'ax');
insert into parent_child values ( 'ab', 'abc');
insert into parent_child values ( 'ab', 'abd');
insert into parent_child values ( 'ab', 'abe');
insert into parent_child values ('abe','abes');
insert into parent_child values ('abe','abet');
insert into parent_child values ( null, 'b');
insert into parent_child values ( 'b', 'bg');
insert into parent_child values ( 'b', 'bh');
insert into parent_child values ( 'b', 'bi');
insert into parent_child values ( 'bi', 'biq');
insert into parent_child values ( 'bi', 'biv');
insert into parent_child values ( 'bi', 'biw');
set verify off
select
case when count(*) > 0 then
'&&parent is an ancestor of &&child' else
'&&parent is no ancestor of &&child' end
"And here's the answer"
from
parent_child
where
child_ = '&&child'
start with
parent_ = '&&parent'
connect by
prior child_ = parent_;
undefine child
undefine parent