이것은 아마도 실제 세계에서는 아직 발생하지 않았으며 결코 일어날 수는 없지만 이것을 고려해 봅시다 .git 저장소가 있고 커밋하고 매우 운이 좋지 않다고 가정하십시오. 이미 저장소에있는 다른 것으로. 질문은 Git이 이것을 어떻게 처리 할 것인가이다. 단순히 실패? 두 얼룩을 연결하고 상황에 따라 어느 얼룩이 필요한지 확인하는 방법을 찾으십니까?
실제 문제보다 뇌 맛이 더 좋지만 문제가 흥미로 웠습니다.
이것은 아마도 실제 세계에서는 아직 발생하지 않았으며 결코 일어날 수는 없지만 이것을 고려해 봅시다 .git 저장소가 있고 커밋하고 매우 운이 좋지 않다고 가정하십시오. 이미 저장소에있는 다른 것으로. 질문은 Git이 이것을 어떻게 처리 할 것인가이다. 단순히 실패? 두 얼룩을 연결하고 상황에 따라 어느 얼룩이 필요한지 확인하는 방법을 찾으십니까?
실제 문제보다 뇌 맛이 더 좋지만 문제가 흥미로 웠습니다.
답변:
이 경우 Git이 어떻게 동작하는지 정확히 알아 내기 위해 실험을했습니다. 버전 2.7.9 ~ rc0 + next.20151210 (데비안 버전)입니다. 기본적으로 다음 diff를 적용하고 git을 다시 작성하여 해시 크기를 160 비트에서 4 비트로 줄였습니다.
--- git-2.7.0~rc0+next.20151210.orig/block-sha1/sha1.c
+++ git-2.7.0~rc0+next.20151210/block-sha1/sha1.c
@@ -246,6 +246,8 @@ void blk_SHA1_Final(unsigned char hashou
blk_SHA1_Update(ctx, padlen, 8);
/* Output hash */
- for (i = 0; i < 5; i++)
- put_be32(hashout + i * 4, ctx->H[i]);
+ for (i = 0; i < 1; i++)
+ put_be32(hashout + i * 4, (ctx->H[i] & 0xf000000));
+ for (i = 1; i < 5; i++)
+ put_be32(hashout + i * 4, 0);
}
그런 다음 몇 가지 커밋을 수행하고 다음을 알았습니다.
# 2의 경우 "git push"를 실행할 때 일반적으로 다음과 같은 오류가 발생합니다.
error: object 0400000000000000000000000000000000000000 is a tree, not a blob
fatal: bad blob object
error: failed to push some refs to origin
또는:
error: unable to read sha1 file of file.txt (0400000000000000000000000000000000000000)
파일을 삭제 한 다음 "git checkout file.txt"를 실행하십시오.
# 4와 # 6의 경우 일반적으로 다음과 같은 오류가 발생합니다.
error: Trying to write non-commit object
f000000000000000000000000000000000000000 to branch refs/heads/master
fatal: cannot update HEAD ref
"git commit"을 실행할 때. 이 경우 일반적으로 "git commit"을 다시 입력하면 새로운 해시가 생성되므로 (변경된 타임 스탬프 때문에)
# 5와 # 9의 경우 일반적으로 다음과 같은 오류가 발생합니다.
fatal: 1000000000000000000000000000000000000000 is not a valid 'tree' object
"git commit"을 실행할 때
누군가가 손상된 저장소를 복제하려고하면 일반적으로 다음과 같은 것을 보게됩니다.
git clone (one repo with collided blob,
d000000000000000000000000000000000000000 is commit,
f000000000000000000000000000000000000000 is tree)
Cloning into 'clonedversion'...
done.
error: unable to read sha1 file of s (d000000000000000000000000000000000000000)
error: unable to read sha1 file of tullebukk
(f000000000000000000000000000000000000000)
fatal: unable to checkout working tree
warning: Clone succeeded, but checkout failed.
You can inspect what was checked out with 'git status'
and retry the checkout with 'git checkout -f HEAD'
"걱정"하는 것은 두 가지 경우 (2,3)에서 저장소가 경고없이 손상되고 세 가지 경우 (1,7,8)에서 모든 것이 정상으로 보이지만 저장소 내용이 예상 한 것과 다릅니다 되려고. 사람들이 복제하거나 당기는 것은 당신이 가진 것과 다른 내용을 가질 것입니다. 4, 5, 6 및 9의 경우는 오류와 함께 중지되므로 괜찮습니다. 적어도 모든 경우에 오류로 실패하면 더 좋을 것이라고 생각합니다.
원래 답변 (2012) (아래 shattered.io
2017 SHA1 충돌 참조)
그건 리누스 세 (2006 년) 대답은 여전히 관련이있을 수 :
아니. SHA1이 같으면 다른 쪽 끝에서 개체를받을 때 이미 가지고있는 개체를 덮어 쓰지 않습니다 .
따라서 충돌이 발생하면 특정 리포지토리의 "이전"개체가 항상 재정의됩니다. 그러나 git 객체 네트워크가 완전히 정렬되지 않은 DAG를 생성한다는 점에서 "이전"은 분명히 저장소마다입니다. 따라서 다른 저장소는 직계 조상의 경우 "이전"에 대해 동의하지만 개체는 별도의 분기가 아닌 별도의 분기를 통해 이루어 졌으므로 두 개의 다른 저장소가 두 개체를 다른 순서로 얻었을 수 있습니다.
그러나 "이전의 재정의"는 보안 관점에서 원하는 것입니다. git 모델은 주로 자신의 저장소 만 신뢰해야한다는 점을 기억하십시오 .
따라서 "git pull
" 를 수행 하면 새 수신 오브젝트는 이미 보유한 오브젝트보다 신뢰도가 떨어 지므로 새 오브젝트를 기존 오브젝트로 바꾸는 것이 잘못됩니다.따라서 두 가지 충돌 사례가 있습니다.
부주의 종류 어떻게 든 아주 아주 재수, 두 개의 파일은 동일한 SHA1을 가진 끝.
이때 파일을 커밋 할 때 (또는 "git-update-index
"를 사용 하여 파일을 인덱스로 이동했지만 아직 커밋하지 않은 경우) 새 내용의 SHA1이 계산되지만 이전 개체와 일치하므로 새로운 객체는 생성되지 않으며 commit-or-index는 이전 객체를 가리키게됩니다 .
인덱스가 이전 개체 SHA1과 일치하기 때문에 즉시 알 수 없으며 "git diff
" 와 같은 항목 이 체크 아웃 된 복사본을 사용 한다는 것을 의미합니다 . 그러나 트리 수준 차이를 수행하거나 복제본을 수행하는 경우 또는 잡아 당기거나 강제로 결제) 파일이 무언가로 변경되었음을 갑자기 알 수 있습니다.예상했던 것과 완전히 다릅니다.
따라서 일반적으로 이러한 종류의 충돌은 상당히 빨리 나타납니다.
관련 뉴스에서, 문제는 실수로 충돌에 대해 무엇을 할 수 있는가의 문제입니다 ..
우선은, 충돌의 부주의 종류가 정말 정말 저 사람을 생각 나게하자 정말 빌어 먹을 가능성이 우리가 매우 가능성이 결코 이제까지 전체 역사를 볼 수 있도록, 우주의.
그러나 경우에 그런 일이, 그것은 세상의 종말이 아니다 : 당신은 가능성이 가장 높은 단지 약간 충돌하는 파일을 변경, 단지 새로운 변경된 내용으로 커밋 힘해야 할 것입니다 무엇을 (코멘트 "는 말을 추가/* This line added to avoid collision */
")와 그런 다음 위험한 것으로 표시된 마법 SHA1에 대해 git을 가르치십시오.
따라서 몇 백만 년 동안 아마도 하나 또는 두 개의 "중독"SHA1 값을 git에 추가해야 할 것입니다. 유지 관리 문제가 될 가능성은 거의 없습니다.)충돌 공격자 종류의 사람 (또는 짐승 - 강제) SHA1을 위반하기 때문이다.
이 사람은 분명하다 많은 가능성이 부주의 종류 이상의하지만 정의는 항상 "원격"저장소입니다. 침입자가 로컬 리포지토리에 액세스 할 수 있다면 훨씬 더 쉬운 방법입니다.
따라서이 경우 충돌은 전적으로 문제가되지 않습니다. 공격자가 의도 한 것과 다른 "나쁜"저장소를 얻게되지만 실제로 충돌하는 객체를 사용 하지 않으므로 문자 그대로 와 다릅니다. 공격자가 충돌을 전혀 발견하지 못했습니다.하지만 이미 가지고있는 객체를 사용하면됩니다 (즉, 동일한 SHA1을 생성하는 동일한 파일의 "사소한"충돌과 100 % 동일합니다).
SHA-256을 사용하는 문제는 정기적으로 언급,하지만 지금은 (2012)에 대한에 따라 행동하지 않습니다.
참고 : 2018 및 Git 2.19부터 SHA-256을 사용하도록 코드를 리팩토링하고 있습니다.
주 (유머) : 당신은 특정 SHA1의 저지 강제 할 수 접두사 프로젝트로, gitbrute 에서 (브래드 피츠 패트릭 bradfitz
) .
gitbrute brute는 결과 git commit이 원하는 접두사를 갖도록 한 쌍의 author + committer 타임 스탬프를 강제합니다.
예 : https://github.com/bradfitz/deadbeef
다니엘 디니 에스 지적 코멘트에 에 7.1 망할 놈의 도구 - 수정 선택 포함 :
프로그래밍 팀의 모든 구성원이 같은 날 밤 관련없는 사건에서 늑대에 의해 공격 당하고 살해 당할 가능성이 더 높습니다.
가장 최근 (2017 년 2 월)조차도 shattered.io
SHA1 충돌을 일으킬 가능성을 보여주었습니다.
(내에서 더 많이 볼 별도의 대답 리누스 토발즈 (Linus Torvalds) 'Google+ 소식을 포함)
자세한 내용 은 Valerie Anita Aurora의 " 암호화 해시 함수 수명 "을 참조하십시오 .
그 페이지에서 그녀는 다음과 같이 지적합니다.
Google은 보안이 중요한 애플리케이션에 SHA-1 사용을 중단해야하는 모든 사람을 설득하기 위해 6500 CPU 년과 110 GPU 년을 보냈습니다.
또한 시원했기 때문에
아래의 별도 답변 에서 자세한 내용을 참조하십시오 .
/* This line added to avoid collision */
: D 당신은 복권을 두 번 이길 수 있습니다 : P
/* This line added to avoid collision of the avoid collision line */
에 따르면 프로 힘내 :
저장소의 이전 객체와 동일한 SHA-1 값으로 해시되는 객체를 커밋하면 Git은 이미 Git 데이터베이스에있는 이전 객체를보고 이미 작성된 것으로 간주합니다. 어떤 시점에서 해당 객체를 다시 체크 아웃하려고하면 항상 첫 번째 객체의 데이터를 얻게됩니다.
따라서 실패하지는 않지만 새 객체를 저장하지는 않습니다.
나는 그것이 커맨드 라인에서 어떻게 보일지 모르겠지만 확실히 혼란 스러울 것입니다.
조금 더 아래로, 동일한 참조는 그러한 충돌의 가능성을 설명하려고 시도합니다.
다음은 SHA-1 충돌 발생에 대한 아이디어를 제공하는 예입니다. 지구상의 65 억 명의 사람들이 프로그래밍을하고 매초마다 전체 리눅스 커널 역사 (1 백만 개의 Git 객체)와 동등한 코드를 생성하여 하나의 거대한 Git 저장소로 밀어 넣는다면 5 년이 걸릴 것입니다. 이 저장소에는 단일 SHA-1 오브젝트 충돌의 50 % 확률을 갖기에 충분한 오브젝트가 포함되어 있습니다. 프로그래밍 팀의 모든 구성원이 같은 날 밤 관련없는 사건에서 늑대에 의해 공격 당하고 살해 당할 가능성이 더 높습니다.
2012 년의 이전 답변에 추가하기 위해 shattered.io 와의 실제 SHA-1 충돌의 예 인 2017 년 2 월 2017 이 있습니다. 이곳에서 두 개의 충돌하는 PDF 파일을 만들 수 있습니다. 첫 번째 PDF 파일의 디지털 서명 1 개. 두 번째 PDF 파일의 유효한 서명으로 남용 될 수도 있습니다.
" 몇 년 동안 사망했을 때 널리 사용되는 SHA1 기능이 이제 사망했습니다 "를 참조하십시오. .
2 월 26 일 업데이트 : Linus 는 Google+ 게시물에서 다음 사항 을 확인했습니다 .
(1) 우선 하늘이 떨어지지 않습니다. 보안 서명과 같은 일에 암호 해시를 사용하는 것과 git과 같은 내용 주소 지정 가능한 시스템에 대한 "콘텐츠 식별자"를 생성하는 것에는 큰 차이가 있습니다.
(2) 둘째,이 특정 SHA1 공격의 본질은 실제로 완화하기가 매우 쉽고 해당 완화를 위해 이미 두 가지 패치 세트가 게시되어 있음을 의미합니다.
(3) 마지막으로, 세계를 파괴하지 않는 다른 해시 또는 심지어 오래된 자식 저장소로 합리적으로 간단하게 전환합니다.
이러한 전환에 대해서는 2018 년 1 분기 Git 2.16을 참조하십시오. 하여 해시 알고리즘을 나타내는 구조를 추가 한 . 해당 전환 구현이 시작되었습니다.
Git 2.19 (Q3 2018) 부터 Git은 SHA-256을 NewHash로 선택했으며 이를 코드에 통합하는 중입니다 (SHA1이 여전히 기본값 (Q2 2019, Git 2.21)이지만 SHA2가 후속 임).
원래 답변 (2 월 25 일) 그러나 :
git-svn
git fsck
git fsck
NUL
NUL
transfer.fsck
있습니다.전체 지점 SCM의는 일회성 이벤트에 대한 것이 아니라 지속적인 역사이다. 또한 근본적으로 성공적인 공격은 시간이 지남에 따라 작동해야하며 탐지 할 수 없다는 것을 의미합니다.
SCM을 한 번만 속이고 코드를 삽입하면 다음 주에 감지되면 실제로 유용한 작업은 수행되지 않았습니다. 너는 너 자신을 태웠다.
Joey Hess 는 Git 리포지토리 에서 해당 PDF를 시도 하고 발견했습니다 .
여기에는 SHA와 크기가 동일한 두 개의 파일이 포함되어 있는데, git이 헤더를 내용에 추가하는 방식 덕분에 서로 다른 얼룩이 생깁니다.
joey@darkstar:~/tmp/supercollider>sha1sum bad.pdf good.pdf
d00bbe65d80f6d53d5c15da7c6b4f0a655c5a86a bad.pdf
d00bbe65d80f6d53d5c15da7c6b4f0a655c5a86a good.pdf
joey@darkstar:~/tmp/supercollider>git ls-tree HEAD
100644 blob ca44e9913faf08d625346205e228e2265dd12b65 bad.pdf
100644 blob 5f90b67523865ad5b1391cb4a1c010d541c816c1 good.pdf
이러한 충돌 파일에 동일한 데이터를 추가해도 다른 충돌이 발생하지만 선행 데이터는 그렇지 않습니다.
따라서 주요 공격 벡터 (커밋 단조)는 다음과 같습니다.
- 일반 커밋 객체를 생성합니다.
- 전체 커밋 객체 + NUL을 선택한 접두어로 사용하십시오.
- 충돌이 좋은 / 나쁜 개체를 생성하려면 동일한 접두사 충돌 공격을 사용하십시오.
- ... 좋은 커밋 객체와 나쁜 커밋 객체가 여전히 같은 트리를 가리 키기 때문에 이것은 쓸모가 없습니다!
또한 각 파일에 존재하는 SHA-1에 대한 암호화 분석 충돌 공격을 이미 탐지하고 탐지 할 수 있습니다. cr-marcstevens/sha1collisiondetection
Git 자체에 비슷한 검사를 추가하면 계산 비용이 발생합니다. 합니다.
해시 변경시 Linux는 다음과 같이 말합니다 .
해시의 크기와 해시 알고리즘의 선택은 독립적 인 문제입니다.
아마도 256 비트 해시로 전환하고 내부 및 네이티브 git 데이터베이스에서 사용하고 기본적으로 해시를 40 자 16 진수 문자열로 표시 하는 것입니다. 많은 상황).
그런 식으로 git 주변의 툴은 특별한 "--full-hash
"인수 (또는 "--abbrev=64
"또는 기본적으로 40으로 축약되는 기본값)를 .
여전히 SHA1에서 다른 해시 함수로 의 전환 계획은 여전히 복잡 하지만 적극적으로 연구되고 있습니다. 캠페인 이다
convert-to-object_id
진행 :
3 월 20 일 업데이트 : GitHub에 가능한 공격 및 보호 세부 사항 .
SHA-1 이름은 다양한 메커니즘을 통해 신뢰를 할당 할 수 있습니다. 예를 들어, Git을 사용하면 커밋 또는 태그를 암호화하여 서명 할 수 있습니다. 그렇게하면 커밋 또는 태그 객체 자체에만 서명되며, SHA-1 이름을 사용하여 실제 파일 데이터를 포함하는 다른 객체를 가리 킵니다. 이러한 객체가 충돌하면 서명이 생성 될 수 있지만 서명은 의도 한 것과 다른 데이터를 나타냅니다. 이러한 공격에서 서명자는 충돌의 절반 만 보게되고 피해자는 다른 절반 만 보게됩니다.
보호:
최근의 공격은 특별한 기술을 사용하여 훨씬 적은 시간 내에 충돌을 발견하는 SHA-1 알고리즘의 취약점을 악용합니다. 이러한 기술들은 충돌 쌍의 절반의 SHA-1을 계산할 때 검출 될 수있는 바이트 단위의 패턴을 남긴다.
이제 GitHub.com은 계산하는 각 SHA-1에 대해이 탐지를 수행하고 객체가 충돌 쌍의 절반이라는 증거가있는 경우 작업을 중단합니다. 이는 공격자가 GitHub를 사용하여 프로젝트가 충돌의 "무고한"절반을 수락하고 악의적 인 절반을 호스팅하지 못하도록 유도하는 것을 방지합니다.
Marc Stevens의 " sha1collisiondetection
" 참조
다시 함께 Q1 2,018 힘내 2.16 해시 알고리즘을 나타내는 구조를 추가하는 새로운 해시 전이의 구현을 개시했다.
위에서 언급했듯이 새로운 지원되는 해시는 SHA-256 입니다.
git-svn
비록 비록 약간의 문제가 있습니다"뒤에 링크 는 간접적이지만)
나는 암호 전문가들이 축하 할 것이라고 생각합니다.
2005 년 2 월 Xiaoyun Wang, Yiqun Lisa Yin 및 Hongbo Yu의 공격이 발표되었습니다. 이 공격은 정식 버전의 SHA-1에서 충돌을 발견하여 2 ^ 69 미만의 작업이 필요합니다. 무차별 검색에는 2 ^ 80 작업이 필요합니다.
y
되는 h(x) ==
h (y)`를 찾을 수 는 있지만 Git에는 영향을 미치지 않으므로 두 번째 사전 이미지 공격에 취약합니다. 메시지를 가진 x
당신은 메시지를 수정할 수 있습니다 x'
그 h(x) == h(x')
. 따라서이 공격은 힘내를 약화시키지 않습니다. 또한 Git은 보안상의 이유로 SHA-1을 선택하지 않았습니다.
SHA-1과 같은 해시에 대한 여러 가지 공격 모델이 있지만 일반적으로 논의되는 것은 Marc Stevens의 HashClash 도구를 포함한 충돌 검색 입니다.
사람들이 지적했듯이 git과 해시 충돌을 일으킬 수는 있지만 다른 저장소의 기존 객체를 덮어 쓰지는 않습니다. 나는 심지어 상상할 것이다git push -f --no-thin
기존 개체를 덮어 쓰지 않습니다,하지만 확실하지 않은 100 %.
즉, 원격 저장소를 해킹하면 잘못된 객체를 오래된 객체로 만들 수 있습니다 가능 GitHub의 또는 유사한에서 오픈 소스 프로젝트에 해킹 코드를 삽입. 조심한다면 새 사용자가 다운로드 한 해킹 된 버전을 소개 할 수 있습니다.
그러나 프로젝트 개발자가 할 수있는 많은 일이 수백만 달러의 핵을 노출 시키거나 실수로 파괴 할 수 있다고 생각합니다. 특히, 해킹을하지 않은 일부 개발자 git push --no-thin
가 영향을받는 파일을 수정 한 후 때로는 --no-thin
의존 하지 않고 앞서 언급 한 내용 을 실행하면 많은 비용이 발생합니다 .