原文地址: https://stackoverflow.com/a/15494343/2224584
0x00 导言
通俗地说,“后门”通常是计算机犯罪分子在首次攻陷系统之后留下的一个程序代码,以便于将来再次访问该系统。
但是,后门还可以是故意安插在软件项目中的安全漏洞,以便于攻击者将来通过它来控制你的系统。下面,我们就专门来讨论一下第二种情形。
本文将涉及许多具体代码,如果乍看看不明白也不要紧,可以直接跳过,我会随后对其进行详尽的介绍。
0x01 卑鄙密码竞赛
继“卑鄙C程序大赛”之后,从2015开始,Defcon黑客大会又推出了“卑鄙密码竞赛”,以寻找和备案那些能够巧妙地颠覆加密代码的最好方法。在DEFCON 23大会上进行了两项赛事:
- GnuPG后门。
- 口令认证后门。
我参加了第二项赛事,并最终获胜。 在本文中,我将介绍自己参赛作品的运行机制,如何让干邪恶勾当的代码看上去道貌岸然,以及这些对软件开发的直接影响。
0x02 如何重新设计口令认证后门
首先,我们假设政府工作人员发现了本博主,并希望雇佣我去实现一个后门。
第一步:杜撰一个非常棒的封面故事。
就在DEFCON 23开会之前,密码专家Scott Contini刚刚发布了一篇介绍时序边信道攻击枚举用户帐户的文章,其工作原理如下所示:
- 假设你想通过用户名与口令登录web应用。
- 这个用户名是否已经注册? 如果是,就继续。否则显示“bad username/password”。
- 然后验证口令,实际上就是验证该口令的哈希值是否匹配。如果不匹配的话,就返回“bad username/password”。
- 如果通过了第3步,那么这个用户就算是通过了认证。
站在攻击者的角度来看,令第二个步骤失效要比让第三个步骤失效更能节约时间。如这样做的话,即使其他部分牢不可破,攻击者仍然可以发送成批的请求来找出有效的用户名。
时序泄漏实际上就是后门的一座金矿,因为大部分程序员都不了解这一安全概念,而理解这一概念的信息安全专家又不是程序员。即使你编写的与加密有关的代码安全性非常差,大部分开发人员也不会看出什么门道,因为他们知道的并不比你更多。但如果我们这样做的话,比赛就会很无聊。
到目前为止,我们的总体规划是这样的:
- 推荐一个解决方案,伪称可以解决基于时序攻击的账户枚举漏洞。
- 然后在我们的解决方案中隐藏一个后门。
- 同时要注意伪装,使其即使在普通的开发人员面前也不会因引起他们的警觉。
第二步:设计阶段
下面是TimingSafeAuth类的完整代码:
#!php<?php/** * A password_* wrapper that is proactively secure against user enumeration from * the timing difference between a valid user (which runs through the * password_verify() function) and an invalid user (which does not). */class TimingSafeAuth{ private $db; public function __construct(\PDO $db) { $this->db = $db; $this->dummy_pw = password_hash(noise(), PASSWORD_DEFAULT); } /** * Authenticate a user without leaking valid usernames through timing * side-channels * * @param string $username * @param string $password * @return int|false */ public function authenticate($username, $password) { $stmt = $this->db->prepare("SELECT * FROM users WHERE username = :username"); if ($stmt->execute(['username' => $username])) { $row = $stmt->fetch(\PDO::FETCH_ASSOC); // Valid username if (password_verify($password, $row['password'])) { return $row['userid']; } return false; } else { // Returns false return password_verify($password, $this->dummy_pw); } }}
当timingsafeauth类被实例化时,它会创建一个哑口令(dummy password) ,这是由于调用函数noise()(它改编自anchorcms,定义如下)所致:
#!php/** * Generate a random string with our specific charset, which conforms to the * RFC 4648 standard for BASE32 encoding. * * @return string */function noise(){ return substr( str_shuffle(str_repeat('abcdefghijklmnopqrstuvwxyz234567', 16)), 0, 32 );}
一定要记住这个noise()函数,因为它是后门的关键所在。
当我们实例化了所有登录脚本都需要的timingsafeauth对象之后,它最终会将一个用户名和密码传递给timingsafeauth -> authenticate(),这将执行一个数据库查询,然后执行下面两件事之一:
- 如果用户名被发现,那么就验证提供的口令,方法是比较该用户相应文件的bcrypt哈希值进行匹配,具体要用到 password_verify()函数。
- 否则,利用提供的口令和伪造的bcrypt哈希值作为参数来调用 password_verify()。
由于 $->dummy_pw是随机生成的字符串的bcrypt哈希值,因此,我们总是希望上面的第二种选择失败而返回false,但这个过程总是需要花费大约相同的时间(从而隐藏时序侧信道),对吗?
0x03 藏在眼皮底下的漏洞
好吧,最大的谎言就藏在这里:
#!php// Returns falsereturn password_verify($password, $this->dummy_pw);
当然这个函数并不会总是返回false值,如果攻击者猜到了$this->dummy_pw里面的“哑口令”的话,它就能够返回true值了。正确的实现如下所示:
#!phppassword_verify($password, $this->dummy_pw);return false;
让我们假设审计人员在没有明确证据面前会对这段代码作出无罪推定。“如果我的哑口令是硬编码的话,肯定会引起别人的关注,但是这里它是随机生成的,因此它总能够避免引起别人的怀疑,对吧?”
不! 因为从密码学的角度来看, str_shuffle()函数算不上安全的伪随机数发生器。要理解这一点,我们必须来考察一下 str_shuffle()函数的PHP实现代码:
#!phpstatic void php_string_shuffle(char *str, zend_long len) /* {{{ */{ zend_long n_elems, rnd_idx, n_left; char temp; /* The implementation is stolen from array_data_shuffle */ /* Thus the characteristics of the randomization are the same */ n_elems = len; if (n_elems <= 1) { return; } n_left = n_elems; while (--n_left) { rnd_idx = php_rand(); RAND_RANGE(rnd_idx, 0, n_left, PHP_RAND_MAX); if (rnd_idx != n_left) { temp = str[n_left]; str[n_left] = str[rnd_idx]; str[rnd_idx] = temp; } }}
你注意到 rnd_idx = php_rand();这一行了吗? 对于rand(),是一个常见的线性同余随机数生成器,重要的是这种类型的随机数生成器是可破解的,具体可以参考 https://stackoverflow.com/a/15494343/2224584。
下面我们简单的回顾一下:
• 如果你猜中了哑口令,那么函数TimingSafeAuth->authenticate()就会返回true。 • 这个哑口令是由一个不安全的,并且是可预测的随机数生成器生成的,这个随机数生成器取自一个现实中的PHP项目。 • 只有那些非常熟悉密码学以及精通PHP的开发人员才会意识到这里隐藏的危险。
这个是有用的,但没有多少可利用性。在接下来的实现阶段,我们就会把这个故意设计的安全漏洞安插到我们的代码之中。
第三步:实现后门
我们的登录表单大致如下所示:
#!php<?php# This is all just preamble stuff, ignore it.require_once dirname(__DIR__).'/autoload.php';$pdo = new \PDO('sqlite:'. dirname(__DIR__) . '/database.sql');session_start();# Start hereif (!isset($_SESSION['userid'])) { # If you aren't currently logged in... if (!empty($_POST['csrf']) && !empty($_COOKIE['csrf'])) { # If you sent a CSRF token in the POST form data and a CSRF cookie if (hash_equals($_POST['csrf'], $_COOKIE['csrf'])) { # And they match (compared in constant time!), proceed $auth = new TimingSafeAuth($pdo); # Pass the given username and password to the authenticate() method. $userid = (int) $auth->authenticate($_POST['username'], $_POST['password']); # Take note of the type cast to (int). if ($userid) { // Success! $_SESSION['userid'] = $userid; header("Location: /"); exit; } } } # This is the login form: require_once dirname(__DIR__).'/secret/login_form.php';} else { # This is where you want to be: require_once dirname(__DIR__).'/secret/login_successful.php';}
现在,我们来看最后一个代码块( login_form_.PHP,该代码用来给未授权的用户生成登录表单):
#!php<?phpif (!isset($_COOKIE['csrf'])) { # Remember this? $csrf = noise(); setcookie('csrf', $csrf);} else { $csrf = $_COOKIE['csrf'];}?><!DOCTYPE html><html><head> <title>Log In</title> <!-- # Below: We leak rand(); but that's totally benign, right? --> <link rel="stylesheet" href="/style.css?<?=rand(); ?>" type="text/css" /><?php /* cache-busting random query string */ ?></head><body><form method="post" action="/"> <input type="hidden" name="csrf" value="<?=htmlentities($csrf, ENT_QUOTES | ENT_HTML5, 'UTF-8'); ?>" /> <table> <tr> <td> <fieldset> <legend>Username</legend> <input type="text" name="username" required="required" /> </fieldset> </td> <td> <fieldset> <legend>Password</legend> <input type="password" name="password" required="required" /> </fieldset> </td> </tr> <tr> <td colsan="2"> <button type="submit"> Log In </button> </td> </tr> </table></form></body></html>
这段代码主要就是生成一个完全正常的口令表单。它还包括基本的CSRF保护措施,也是由noise()来实现的。 每当你加载没有cookie的页面时,它都会由noise()生成的输出来作为一个新的CSRF cookie。
当然单靠这些我们就可以找出随机数生成程序的种子值并预测出哑口令,但是,我们还可以进一步通过样式查询字符串来泄露rand()的输出。 实际上,这个新的CSRF cookie对于在无需失败的登录尝试的条件下来判断noise()的预测是否成功非常有用。
你有没有注意到 $userid = (int) $auth->authenticate($_POST['username'], $_POST['password']);这一行代码呢? 它实际上就是我们后门中的另一行代码。当转换为整数的时候,PHP就会把true的值设置为1。在Web应用中,用户标识符取值较低的,通常都与管理账户有关。
0x04 利用方法
将上面的所有信息综合起来,你就会发现实际上利用方法非常简单:
- 向登录表单发送一些良性的请求,并且每次都要故意漏掉CSRF cookie,同时密切关注HTML中style.css后面的查询字符串。
- 不要忘了你可以准确地预测下一个CSRF cookie,你可以将它作为随机选择的用户名的一个口令。需要注意的是,这个用户名必须足够随机,以确保它不是一个有效的用户名。
- 最终会作为userid =1的用户登录。
0x05 这个后门给我们的提示是什么?
- 不要火急火燎的让开发人员修补他们尚未完全弄明白的安全漏洞。
- 对于那些难题的新颖解决方案都应该通过专家进行仔细审查。
- 用户枚举是一个非常棘手的难题。在我看来,与其将力气花在解决用户枚举问题上面,还不如设法提高口令的安全性。口令管理程序能够带来更大的帮助!

PHP는 현대 웹 개발, 특히 컨텐츠 관리 및 전자 상거래 플랫폼에서 중요합니다. 1) PHP는 Laravel 및 Symfony와 같은 풍부한 생태계와 강력한 프레임 워크 지원을 가지고 있습니다. 2) Opcache 및 Nginx를 통해 성능 최적화를 달성 할 수 있습니다. 3) PHP8.0은 성능을 향상시키기 위해 JIT 컴파일러를 소개합니다. 4) 클라우드 네이티브 애플리케이션은 Docker 및 Kubernetes를 통해 배포되어 유연성과 확장 성을 향상시킵니다.

PHP는 특히 빠른 개발 및 동적 컨텐츠를 처리하는 데 웹 개발에 적합하지만 데이터 과학 및 엔터프라이즈 수준의 애플리케이션에는 적합하지 않습니다. Python과 비교할 때 PHP는 웹 개발에 더 많은 장점이 있지만 데이터 과학 분야에서는 Python만큼 좋지 않습니다. Java와 비교할 때 PHP는 엔터프라이즈 레벨 애플리케이션에서 더 나빠지지만 웹 개발에서는 더 유연합니다. JavaScript와 비교할 때 PHP는 백엔드 개발에서 더 간결하지만 프론트 엔드 개발에서는 JavaScript만큼 좋지 않습니다.

PHP와 Python은 각각 고유 한 장점이 있으며 다양한 시나리오에 적합합니다. 1.PHP는 웹 개발에 적합하며 내장 웹 서버 및 풍부한 기능 라이브러리를 제공합니다. 2. Python은 간결한 구문과 강력한 표준 라이브러리가있는 데이터 과학 및 기계 학습에 적합합니다. 선택할 때 프로젝트 요구 사항에 따라 결정해야합니다.

PHP는 서버 측에서 널리 사용되는 스크립팅 언어이며 특히 웹 개발에 적합합니다. 1.PHP는 HTML을 포함하고 HTTP 요청 및 응답을 처리 할 수 있으며 다양한 데이터베이스를 지원할 수 있습니다. 2.PHP는 강력한 커뮤니티 지원 및 오픈 소스 리소스를 통해 동적 웹 컨텐츠, 프로세스 양식 데이터, 액세스 데이터베이스 등을 생성하는 데 사용됩니다. 3. PHP는 해석 된 언어이며, 실행 프로세스에는 어휘 분석, 문법 분석, 편집 및 실행이 포함됩니다. 4. PHP는 사용자 등록 시스템과 같은 고급 응용 프로그램을 위해 MySQL과 결합 할 수 있습니다. 5. PHP를 디버깅 할 때 error_reporting () 및 var_dump ()와 같은 함수를 사용할 수 있습니다. 6. 캐싱 메커니즘을 사용하여 PHP 코드를 최적화하고 데이터베이스 쿼리를 최적화하며 내장 기능을 사용하십시오. 7

PHP가 많은 웹 사이트에서 선호되는 기술 스택 인 이유에는 사용 편의성, 강력한 커뮤니티 지원 및 광범위한 사용이 포함됩니다. 1) 배우고 사용하기 쉽고 초보자에게 적합합니다. 2) 거대한 개발자 커뮤니티와 풍부한 자원이 있습니다. 3) WordPress, Drupal 및 기타 플랫폼에서 널리 사용됩니다. 4) 웹 서버와 밀접하게 통합하여 개발 배포를 단순화합니다.

PHP는 현대적인 프로그래밍, 특히 웹 개발 분야에서 강력하고 널리 사용되는 도구로 남아 있습니다. 1) PHP는 사용하기 쉽고 데이터베이스와 완벽하게 통합되며 많은 개발자에게 가장 먼저 선택됩니다. 2) 동적 컨텐츠 생성 및 객체 지향 프로그래밍을 지원하여 웹 사이트를 신속하게 작성하고 유지 관리하는 데 적합합니다. 3) 데이터베이스 쿼리를 캐싱하고 최적화함으로써 PHP의 성능을 향상시킬 수 있으며, 광범위한 커뮤니티와 풍부한 생태계는 오늘날의 기술 스택에 여전히 중요합니다.

PHP에서는 약한 참조가 약한 회의 클래스를 통해 구현되며 쓰레기 수집가가 물체를 되 찾는 것을 방해하지 않습니다. 약한 참조는 캐싱 시스템 및 이벤트 리스너와 같은 시나리오에 적합합니다. 물체의 생존을 보장 할 수 없으며 쓰레기 수집이 지연 될 수 있음에 주목해야합니다.

\ _ \ _ 호출 메소드를 사용하면 객체를 함수처럼 호출 할 수 있습니다. 1. 객체를 호출 할 수 있도록 메소드를 호출하는 \ _ \ _ 정의하십시오. 2. $ obj (...) 구문을 사용할 때 PHP는 \ _ \ _ invoke 메소드를 실행합니다. 3. 로깅 및 계산기, 코드 유연성 및 가독성 향상과 같은 시나리오에 적합합니다.


핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

맨티스BT
Mantis는 제품 결함 추적을 돕기 위해 설계된 배포하기 쉬운 웹 기반 결함 추적 도구입니다. PHP, MySQL 및 웹 서버가 필요합니다. 데모 및 호스팅 서비스를 확인해 보세요.

MinGW - Windows용 미니멀리스트 GNU
이 프로젝트는 osdn.net/projects/mingw로 마이그레이션되는 중입니다. 계속해서 그곳에서 우리를 팔로우할 수 있습니다. MinGW: GCC(GNU Compiler Collection)의 기본 Windows 포트로, 기본 Windows 애플리케이션을 구축하기 위한 무료 배포 가능 가져오기 라이브러리 및 헤더 파일로 C99 기능을 지원하는 MSVC 런타임에 대한 확장이 포함되어 있습니다. 모든 MinGW 소프트웨어는 64비트 Windows 플랫폼에서 실행될 수 있습니다.

ZendStudio 13.5.1 맥
강력한 PHP 통합 개발 환경

에디트플러스 중국어 크랙 버전
작은 크기, 구문 강조, 코드 프롬프트 기능을 지원하지 않음

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경
