strlcpy와 strlcat은 왜 안전하지 않다고 생각됩니까?
이해는 합니다.strlcpy
그리고.strlcat
안전한 대체품으로 설계되어 있습니다.strncpy
그리고.strncat
하지만, 어떤 사람들은 여전히 자신이 불안정하고 단지 다른 유형의 문제를 일으킬 뿐이라고 생각합니다.
누군가가 어떻게 사용하는지 예를 들어줄 수 있나요?strlcpy
또는strlcat
(즉, 항상 문자열을 종료하는 함수는) 보안 문제로 이어질 수 있습니까?
Ulrich Drepper와 James Antill은 이것이 사실이라고 주장하지만, 이 점을 설명하거나 명확히 하는 것은 결코 아니다.
일단은strlcpy
보안 버전으로 의도된 적은 없습니다.strncpy
(그리고strncpy
보안 버전으로 의도된 적은 없습니다.strcpy
). 이 두 함수는 전혀 관련이 없습니다. strncpy
는 C스트링(늘 종단 문자열)과는 전혀 관계가 없는 함수입니다.그 안에 있는 건str...
그 이름의 접두사는 단지 역사적 실수일 뿐이다.의 역사와 목적strncpy
잘 알려져 있고 잘 알려져 있다.이 함수는 Unix 파일시스템의 일부 이력 버전에서 사용되는 소위 "고정폭" 문자열(C 문자열이 아님)을 사용하기 위해 작성된 함수입니다.오늘날 몇몇 프로그래머들은 그것의 이름으로 인해 혼란스러워하고 다음과 같이 추측한다.strncpy
어떻게든 한정된 길이의 C스트링 복사 기능('안전한' 형제)으로 기능해야 합니다.strcpy
이는 사실상 완전히 말도 안 되는 것으로, 잘못된 프로그래밍 연습으로 이어집니다.현재 형식의 C 표준 라이브러리에는 제한된 길이의 C 스트링 복사 기능이 없습니다.여기가 바로 그 장소입니다strlcpy
들어맞습니다. strlcpy
는 C스트링을 사용하기 위해 만들어진 진정한 제한 길이 복사 기능입니다. strlcpy
제한된 길이의 복사 기능이 수행해야 하는 모든 작업을 올바르게 수행합니다.그것을 겨냥할 수 있는 유일한 비판은 유감스럽게도 표준이 아니라는 것이다.
둘째,strncat
반면에, 는 C-스트링과 함께 작동하며 제한된 길이의 연결을 수행하는 함수입니다(실제로 이것은 의 "안전한" 형제입니다).strcat
이 함수를 올바르게 사용하려면 프로그래머는 특별히 주의해야 합니다.이 함수는 결과를 수신하는 버퍼의 크기가 아니라 나머지 부분의 크기(터미네이터 문자도 암묵적으로 카운트됩니다)이기 때문입니다.이것은 혼란스러울 수 있다. 왜냐하면 그 크기를 버퍼의 크기에 연결하기 위해 프로그래머는 종종 비판에 사용되는 몇 가지 추가 계산을 수행해야 하기 때문이다.strncat
.strlcat
는 이러한 문제를 처리하고 인터페이스를 변경하여 추가 계산이 필요하지 않도록 합니다(최소한 발신자 코드에서는).다시 말하지만, 이것을 비판할 수 있는 유일한 근거는 기능이 표준적이지 않다는 것이다.또, 다음의 기능으로부터strcat
group은 재스캔 기반의 스트링 연결이라는 아이디어의 사용성이 제한되어 있기 때문에 프로페셔널 코드에서는 자주 볼 수 없는 것입니다.
이러한 기능이 보안 문제로 이어질 수 있습니다.그들은 도저히 할 수 없다.C 언어 자체가 보안 문제를 일으킬 수 있는 것보다 더 큰 보안 문제를 일으킬 수 없습니다.한동안은 C++ 언어가 자바의 이상한 맛으로 발전하는 방향으로 나아가야 한다는 생각이 강했습니다.이 감정은 때때로 C 언어의 영역에도 파급되어 C 언어의 특징과 C 표준 라이브러리의 특징에 대해 다소 무식하고 비판적인 결과를 초래한다.이 경우에도 그런 대응을 하고 있지 않을까 하는 생각이 듭니다만, 확실히 그렇게 나쁘지는 않길 바랍니다.
사람들이 "라고 말할 때strcpy()
위험합니다, 사용strncpy()
대신" (또는 에 대한 유사한 설명)strcat()
등입니다만, 사용하겠습니다.strcpy()
여기서 나의 초점으로서) 체크인은 무한하다는 것을 의미합니다.strcpy()
따라서 문자열이 지나치게 길면 버퍼 오버런이 발생합니다.정답입니다.사용.strncpy()
버퍼 오버런을 방지합니다.
나는 그것을 느낀다.strncpy()
버그를 수정하는 것은 아닙니다.좋은 프로그래머가 쉽게 회피할 수 있는 문제를 해결합니다.
C 프로그래머로서 문자열을 복사하기 전에 대상 크기를 알아야 합니다.그것이 에서의 가정이다.strncpy()
그리고.strlcpy()
의 마지막 파라미터도 그 사이즈를 지정합니다.문자열을 복사하기 전에 소스 크기를 알 수도 있습니다.대상 크기가 충분하지 않으면 호출하지 마십시오. 버퍼를 다시 할당하거나 다른 작업을 수행하십시오.
왜 싫어하지?strncpy()
?
strncpy()
대부분의 경우 잘못된 해결책입니다.문자열이 예고 없이 잘립니다.어떤 기능이 나에게 무엇을 해야 할지 결정하게 하기보다는 차라리 내가 이것을 알아내서 내가 하고 싶은 행동을 취할 수 있는 추가 코드를 쓰는 것이 낫다.strncpy()
매우 비효율적입니다.행선지 버퍼내의 모든 바이트에 기입합니다.넌 그 수천 개가 필요 없어'\0'
목적지가 끝날 때쯤에요.- 끝이라고는 쓰지 않는다.
'\0'
만약 목적지가 충분히 넓지 않다면.그러니, 어쨌든 네가 직접 해야 해 주세요.이 작업의 복잡성은 수고할 가치가 없습니다.
이제 우리는strlcpy()
에서의 변경점strncpy()
개선은 되지만, 구체적인 행동인지 아닌지는 잘 모르겠다strl*
그들의 존재를 보증합니다. 그들은 너무 구체적입니다.아직 목적지 크기를 알아야 합니다.보다 효율적입니다.strncpy()
수신처의 모든 바이트에 쓸 필요는 없기 때문입니다.그러나 다음과 같은 방법으로 해결할 수 있는 문제를 해결합니다.*((char *)mempcpy(dst, src, n)) = 0;
.
아무도 그렇게 말하지 않는 것 같아strlcpy()
또는strlcat()
는 보안 문제로 이어질 수 있습니다.예를 들어 문자열의 일부가 아닌 완전한 문자열이 작성될 것으로 예상되는 경우 등, 이러한 문제에 의해 버그가 발생할 가능성이 있습니다.
여기서 가장 중요한 문제는 복사할 바이트 수입니다.프로그래머는 이걸 알아야 하고 만약 그걸 모른다면strncpy()
또는strlcpy()
그를 구할 수 없어.
strlcpy()
그리고.strlcat()
ISO C도 POSIX도 표준이 아닙니다.그래서 휴대용 프로그램에서의 사용이 불가능하다.실은.strlcat()
에는 2개의 다른 종류가 있습니다.Solaris 실장은 길이0의 엣지 케이스의 다른 실장과는 다릅니다.그 때문에, 다른 방법보다 유용성이 떨어집니다.
울리치의 비판은 프로그램에서 감지되지 않는 문자열 절단이 잘못된 논리를 통해 보안 문제로 이어질 수 있다는 생각에 바탕을 두고 있다.따라서 보안을 유지하기 위해 잘라내기 여부를 확인해야 합니다.문자열 연결에 대해 이 작업을 수행하는 것은 다음과 같은 방법으로 검사를 수행하는 것을 의미합니다.
if (destlen + sourcelen > dest_maxlen)
{
/* Bug out */
}
지금이다,strlcat
프로그래머가 결과를 확인하는 것을 기억하고 있는 경우,는 이 체크를 효과적으로 실시합니다.그러면 안전하게 사용할 수 있습니다.
if (strlcat(dest, source, dest_bufferlen) >= dest_bufferlen)
{
/* Bug out */
}
울리치의 요점은 네가 이 모든 것들을destlen
그리고.sourcelen
주변(또는 재계산, 즉strlcat
효과적으로) 보다 효율적인 기능을 사용하는 것이 좋습니다.memcpy
어쨌든:
if (destlen + sourcelen > dest_maxlen)
{
goto error_out;
}
memcpy(dest + destlen, source, sourcelen + 1);
destlen += sourcelen;
(위 코드에서는,dest_maxlen
저장 가능한 문자열의 최대 길이입니다.dest
- 의 크기보다 1개 작음dest
버퍼링합니다. dest_bufferlen
의 풀사이즈입니다.dest buffer
).
난 그렇게 생각하지 않아.strlcpy
and strlcat
are consider insecure or it least it isn't the reason why they're not included in glibc - after all, glibc includes strncpy and even strcpy.
The criticism they got was that they are allegedly inefficient, not insecure.
According to the Secure Portability paper by Damien Miller:
The strlcpy and strlcat API properly check the target buffer’s bounds, nul-terminate in all cases and return the length of the source string, allowing detection of truncation. This API has been adopted by most modern operating systems and many standalone software packages, including OpenBSD (where it originated), Sun Solaris, FreeBSD, NetBSD, the Linux kernel, rsync and the GNOME project. The notable exception is the GNU standard C library, glibc [12], whose maintainer steadfastly refuses to include these improved APIs, labelling them “horribly inefficient BSD crap” [4], despite prior evidence that they are faster is most cases than the APIs they replace [13]. As a result, over 100 of the software packages present in the OpenBSD ports tree maintain their own strlcpy and/or strlcat replacements or equivalent APIs - not an ideal state of affairs.
That is why they are not available in glibc, but it is not true that they are not available on Linux. They are available on Linux in libbsd:
They're packaged in Debian and Ubuntu and other distros. You can also just grab a copy and use in your project - it's short and under a permissive license:
Security is not a boolean. C functions are not wholly "secure" or "insecure", "safe" or "unsafe". When used incorrectly, a simple assignment operation in C can be "insecure". strlcpy() and strlcat() may be used safely (securely) just as strcpy() and strcat() can be used safely when the programmer provides the necessary assurances of correct usage.
The main point with all of these C string functions, standard and not-so-standard, is the level to which they make safe/secure usage easy. strcpy() and strcat() are not trivial to use safely; this is proven by the number of times that C programmers have gotten it wrong over the years and nasty vulnerabilities and exploits have ensued. strlcpy() and strlcat() and for that matter, strncpy() and strncat(), strncpy_s() and strncat_s(), are a bit easier to use safely, but still, non-trivial. Are they unsafe/insecure? No more than memcpy() is, when used incorrectly.
Ulrich와 다른 사람들은 그것이 잘못된 안전감을 줄 것이라고 생각합니다.실수로 문자열이 잘리면 코드의 다른 부분에 보안이 영향을 미칠 수 있습니다(예를 들어 파일 시스템 경로가 잘린 경우 프로그램이 의도한 파일에 대해 작업을 수행하지 않을 수 있습니다).
strl 함수 사용과 관련된 두 가지 문제가 있습니다.
- 잘리지 않으려면 반환 값을 확인해야 합니다.
c1x 표준 드래프트 라이터와 Drepper는 프로그래머가 반환값을 확인하지 않을 것이라고 주장한다.Drepper는 우리가 어떻게든 길이를 알고 memcpy를 사용해야 하며 문자열 함수를 모두 피해야 한다고 말합니다. 표준 위원회는 안전한 strcpy가 특별히 명시되지 않은 한 0이 아닌 값을 반환해야 한다고 주장합니다._TRUNCATE
flag. 그 아이디어는 사람들이 if(strncpy_s(...))를 더 많이 사용한다는 것입니다.
- 문자열이 아닌 경우에는 사용할 수 없습니다.
어떤 사람들은 가짜 데이터를 보내도 문자열 함수가 고장나서는 안 된다고 생각한다.이는 strlen과 같은 표준 함수에 영향을 미치며 정상적인 상황에서는 세그먼트 장애가 발생합니다.새로운 표준에는 그러한 기능이 많이 포함될 것이다.수표는 물론 이행 위약금이 부과됩니다.
제안된 표준 함수보다 더 좋은 점은 strl 함수에서 놓친 데이터의 양을 알 수 있다는 것입니다.
strlcpy
트리거할 수 있다SIGSEGV
,한다면src
아니다NUL
-종료되었습니다.
/* Not enough room in dst, add NUL and traverse rest of src */
if (n == 0) {
if (siz != 0)
*d = '\0'; /* NUL-terminate dst */
while (*s++)
;
}
return(s - src - 1); /* count does not include NUL */
언급URL : https://stackoverflow.com/questions/2114896/why-are-strlcpy-and-strlcat-considered-insecure
'source' 카테고리의 다른 글
vuejs 템플릿 파일에 해시태그가 있는 템플릿 태그를 이해할 수 없습니다. (0) | 2022.08.30 |
---|---|
Java에서 Camel Case를 사람이 읽을 수 있는 이름으로 변환하려면 어떻게 해야 합니까? (0) | 2022.08.30 |
C 구조의 멤버로서의 함수 포인터 (0) | 2022.08.30 |
Vue.js에서 v-for를 사용하여 개체의 어레이에 있는 항목에 액세스합니다. (0) | 2022.08.30 |
파일 범위에서 가변적으로 변경된 어레이 (0) | 2022.08.30 |