Ну, «количество сложности», накопленной внутри обычного персонального компьютера, с установленным на нем обычным набором программного обеспечения, больше, я полагаю, и по числу деталей и связей между ними, и по объему вложенных туда человеческих усилий.
Просто этот самый персональный компьютер, однажды разработав, можно почти бесплатно тиражировать. Поэтому это и не заметно.
По-моему, разумнее всего не считать WiFi локальной сетью (сетью, заслуживающей доверия). Тогда взломают и взломают, риск на самом деле не велик. Тарифы то, поди, у всех давно безлимитные.
Метод раскрытия пароля заключается, грубо говоря, в том, что WPA/PSK (PSK — pre-shared key, т.е. пароль) гоняет по сети в открытом виде криптохеш от пароля. Не какой-нибудь там стандартный SHA-256, а специфическую для WiFi функцию, но это и не важно, поскольку функция не секретна.
Поскольку пароль у большинства пользователей представляет собой что-нибудь вроде «kvartira356», то простым перебором он берется. При этом, что характерно, к точке доступа в процессе взлома никто не лезет, поэтому защититься она никак не может.
WPA/Radius этой уязвимостью не страдает, но настроить его заметно сложнее, и обычно никто не заморачивается.
Вообще, это требует инфраструктуры. В меру гибкой, в меру жесткой, чтобы было удобно делать хорошо и неудобно — плохо :-)
Я не знаю пока ни одной среды программирования, в которой такая инфраструктура была бы предусмотрена, хотя потребность явно назрела. Вероятно это то, что человечеству еще предстоит изобрести.
Жалко, что это не изобрели вовремя авторы языка Go, у них это хорошо получается. А сейчас уже поздно, они обещали не ломать обратную совместимость.
Как маленькая часть этой инфраструктуры, в языке должно быть запрещено передавать немодифицированную ошибку вверх по стеку, без явного указания, что именно это и имеется ввиду.
Предлагаю таких ошибок пользователю не вываливать. Ошибка должна выглядеть, как «проверь сетевое соединение», «кончилось место на диске», «не хватает прав доступа», «сначала надо авторизоваться» и т.п., независимо от того, какой уровень абстракции наткнулся на эту ситуацию.
Какая польза верхнему уровню, вплоть до живого человека, знать, что где-то там глубоко внизу случился DNS lookup failure по причине того, что timeout? Что этот самый верхний уровень должен с этой информацией делать?
Верхнему уровню, по большому счету, надо знать:
1) можно ли сделать что-то, в терминах API, который вернул ошибку, чтобы ошибка рассосалась? Ну, например, подождать (сколько?) и попробовать еще раз, предоставить дополнительную информацию (какую?), и т.п.
2) не вызвана ли ошибка неверными параметрами?
3) что сказать человеку, если нужно его вмешательство?
4) что записать в лог для разработчика?
Важность достижимости скорости исполнения, близкой к аппаратной, сильно переоценена.
За редким исключением, узким местом является не кодогенерация, а способность человека понимать исходный (не машинный) код и адекватным образом с ним управляться. Это приводит ко многим негативным последствиям, одним из которых (не самым важным) является написание медленного кода. Т.е., каждый конкретный маленький кусочек исполняется быстро, но все вместе работает медленно, потому, что человек, погрязший в общей сложности проекта, выбирает неоптимальную архитектуру, неопримальные структуры данных и неоптимальные алгоритмы.
Разница между overhead'ом в 1% и 5% вообще малосущественна, потому что это разница между скоростью 99% и 95% — под микроскопом не различишь.
С другой стороны, исключения, как способ работать с ошибками, имеет существенные недостатки, именно с точки зрения организации исходного кода. Один из них — разрыв «сюжетной линии» программы между кодом, который что-то делает, и кодом, который разгребает последствия. Получается, что при ошибке программа вылетает неведомо куда, и это место находится по тексту далеко от того места, где возникла ошибка. Другая проблема — исключения с легкостью пролетают между уровнями абстракции, и что, простите, высокоуровневый код, работающий с базой данных, должен делать с исключениями, прилетевшими из низкоуровнего кода, работающего с сетевым стеком, если он ничего про сеть не знает (ну, по крайней мере, не должен знать)? Третья проблема — обработка «внешних» ошибок (файл не открылся, данные испорчены, блок на диск не записался) должна кардинально отличаться от обработки ошибок во внутренней логике программы (это ошибки программиста, а не условий, в которых оказался исполняемый код), систематическое использование исключений помогает с легкостью смешивать эти совершенно разные вещи между собой.
Обработка ошибок — вообще очень сложная тема, и многие программы с ней не справляются даже на уровне «написать осмысленное сообщение в лог и завершиться, по возможности ничего не сломав». Поэтому говорить о механизме обработки ошибок гораздо интереснее с точки зрения, как этот механизм помогает сделать обработку корректной, не переусложная чрезмерно логику программы, а не с точки зрения, как он позволяет ускорить ее исполнение на 4%.
Это тот самый случай, про который сказано, premature optimization is the root of all evil.
Не очень понятно, что такое время, уделенное вопросам безопасности.
Например, если я прилагаю изрядные усилия для обеспечения общей корректности кода, включая, но не ограничиваясь, усилиями по корректной работе с памятью, это время уделено вопросам безопасности или не им?
Или надо специально напрячь нужную морщину на лбу, и сказать всем, «сейчас я работаю с вопросами безопасности», и именно это время засчитывается?
У Go есть 2 компилятора, «родной» и на основе gcc. Тот, который на основе gcc представляет пока что лишь академический интерес. Мало того, что он очень медленный, он еще и код во многих случаях генерирует хуже, хоть у него и gcc внутри.
И еще добавлю пару-тройку малоизвестных вещей про встроенный фаирвол. Правда, я довольно давно проверял, где-то на уровне семерки. Возможно, с тех пор что-то изменилось.
Первое. Когда программа открывает порт для входящих соединений, и на экране появляется диалог с вопросом, разрешать или нет, все то время, пока этот диалог висит не отвеченный, порт реально открыт. Закрывается он в тот момент, когда пользователь говорит, «порт не открывать». Вероятно это сделано из соображений, что за то время, пока пользователь думает, злобный хакер много вреда нанести не успеет, а вот если сразу сделать порт закрытым, наивная программа может и сломаться.
Второе. Если программа является сервисом, никакого диалога не появится, система сама примет решение «порт не открывать». Но вот только на обдумывание этого решения у нее уйдет несколько секунд. Выглядит это так: создали слушающий сокет, к нему кто-то приконнектился, данные полетели, а через несколько секунд вдруг неожиданно перестали. Когда с этим сталкиваешься первый раз, отладка занимает некоторое время.
Третье. Если программа говорит bind(), указав нулевой номер порта (т.е., пускай система сама назначит порт автоматически), никакого диалога от фаирвола не появляется, и порт по умолчанию будет открыт. Видимо считается, что поскольку номер порта выделяется более-менее случайно, злобный хакер ни в жизнь его не угадает.
Это не корректный подсчет. На самом деле, надо бы как-то оценить энергию импульса, приходящуюся именно на свариваемую зону, а для этого не хватает понимания о величине падения напряжения на ней
Просто этот самый персональный компьютер, однажды разработав, можно почти бесплатно тиражировать. Поэтому это и не заметно.
Поскольку пароль у большинства пользователей представляет собой что-нибудь вроде «kvartira356», то простым перебором он берется. При этом, что характерно, к точке доступа в процессе взлома никто не лезет, поэтому защититься она никак не может.
WPA/Radius этой уязвимостью не страдает, но настроить его заметно сложнее, и обычно никто не заморачивается.
Я не знаю пока ни одной среды программирования, в которой такая инфраструктура была бы предусмотрена, хотя потребность явно назрела. Вероятно это то, что человечеству еще предстоит изобрести.
Жалко, что это не изобрели вовремя авторы языка Go, у них это хорошо получается. А сейчас уже поздно, они обещали не ломать обратную совместимость.
Как маленькая часть этой инфраструктуры, в языке должно быть запрещено передавать немодифицированную ошибку вверх по стеку, без явного указания, что именно это и имеется ввиду.
Верхнему уровню, по большому счету, надо знать:
1) можно ли сделать что-то, в терминах API, который вернул ошибку, чтобы ошибка рассосалась? Ну, например, подождать (сколько?) и попробовать еще раз, предоставить дополнительную информацию (какую?), и т.п.
2) не вызвана ли ошибка неверными параметрами?
3) что сказать человеку, если нужно его вмешательство?
4) что записать в лог для разработчика?
За редким исключением, узким местом является не кодогенерация, а способность человека понимать исходный (не машинный) код и адекватным образом с ним управляться. Это приводит ко многим негативным последствиям, одним из которых (не самым важным) является написание медленного кода. Т.е., каждый конкретный маленький кусочек исполняется быстро, но все вместе работает медленно, потому, что человек, погрязший в общей сложности проекта, выбирает неоптимальную архитектуру, неопримальные структуры данных и неоптимальные алгоритмы.
Разница между overhead'ом в 1% и 5% вообще малосущественна, потому что это разница между скоростью 99% и 95% — под микроскопом не различишь.
С другой стороны, исключения, как способ работать с ошибками, имеет существенные недостатки, именно с точки зрения организации исходного кода. Один из них — разрыв «сюжетной линии» программы между кодом, который что-то делает, и кодом, который разгребает последствия. Получается, что при ошибке программа вылетает неведомо куда, и это место находится по тексту далеко от того места, где возникла ошибка. Другая проблема — исключения с легкостью пролетают между уровнями абстракции, и что, простите, высокоуровневый код, работающий с базой данных, должен делать с исключениями, прилетевшими из низкоуровнего кода, работающего с сетевым стеком, если он ничего про сеть не знает (ну, по крайней мере, не должен знать)? Третья проблема — обработка «внешних» ошибок (файл не открылся, данные испорчены, блок на диск не записался) должна кардинально отличаться от обработки ошибок во внутренней логике программы (это ошибки программиста, а не условий, в которых оказался исполняемый код), систематическое использование исключений помогает с легкостью смешивать эти совершенно разные вещи между собой.
Обработка ошибок — вообще очень сложная тема, и многие программы с ней не справляются даже на уровне «написать осмысленное сообщение в лог и завершиться, по возможности ничего не сломав». Поэтому говорить о механизме обработки ошибок гораздо интереснее с точки зрения, как этот механизм помогает сделать обработку корректной, не переусложная чрезмерно логику программы, а не с точки зрения, как он позволяет ускорить ее исполнение на 4%.
Это тот самый случай, про который сказано, premature optimization is the root of all evil.
Например, если я прилагаю изрядные усилия для обеспечения общей корректности кода, включая, но не ограничиваясь, усилиями по корректной работе с памятью, это время уделено вопросам безопасности или не им?
Или надо специально напрячь нужную морщину на лбу, и сказать всем, «сейчас я работаю с вопросами безопасности», и именно это время засчитывается?
У Go есть 2 компилятора, «родной» и на основе gcc. Тот, который на основе gcc представляет пока что лишь академический интерес. Мало того, что он очень медленный, он еще и код во многих случаях генерирует хуже, хоть у него и gcc внутри.
Такой вот у нас в C isalnum. Понять это нельзя, это можно только запомнить.
> Уходим на ребут и все! Вы невероятны и с собственным почтовым сервером!
И удивляемся, почему все отправленные нами письма ложатся у получателей в spam
В общем. тема DKIM, SPF, DMARC не раскрыта
www.dmarcanalyzer.com/dkim
www.dmarcanalyzer.com/spf
Первое. Когда программа открывает порт для входящих соединений, и на экране появляется диалог с вопросом, разрешать или нет, все то время, пока этот диалог висит не отвеченный, порт реально открыт. Закрывается он в тот момент, когда пользователь говорит, «порт не открывать». Вероятно это сделано из соображений, что за то время, пока пользователь думает, злобный хакер много вреда нанести не успеет, а вот если сразу сделать порт закрытым, наивная программа может и сломаться.
Второе. Если программа является сервисом, никакого диалога не появится, система сама примет решение «порт не открывать». Но вот только на обдумывание этого решения у нее уйдет несколько секунд. Выглядит это так: создали слушающий сокет, к нему кто-то приконнектился, данные полетели, а через несколько секунд вдруг неожиданно перестали. Когда с этим сталкиваешься первый раз, отладка занимает некоторое время.
Третье. Если программа говорит bind(), указав нулевой номер порта (т.е., пускай система сама назначит порт автоматически), никакого диалога от фаирвола не появляется, и порт по умолчанию будет открыт. Видимо считается, что поскольку номер порта выделяется более-менее случайно, злобный хакер ни в жизнь его не угадает.
Я бы подключил конденсатор через силовой тиристор, прижимал бы руками с усилием, а потом уже отпирал тиристор (вероятно, ногой, руки-то заняты).