Подписване на Java аплет и някои тънкости на сигурността на Java
Формулиране на проблема:
Статията не претендира за научна точност и точност, допускам някои неточности в определенията. Не съм отварял Уикипедия, пиша, така да се каже, от сърце, но коментарите се приемат.
Как работи аплетът за пръсти
Когато браузър открие таг в HTML страница, той прехвърля контрола върху зареждането на аплета към съответния java плъгин, който от своя страна прехвърля контрола към JRE, инсталиран на клиентската машина. Има два начина за зареждане на аплет (аплетът е вид java приложение, което е набор от буркани, където има основен буркан с клас Main, който имплементира класа Applet):
- Тагът на аплет изброява файловете на аплет jar, които трябва да бъдат заредени и откъде да ги заредите (кодова база)
- с jnlp файл, който определя тази информация, както и много други опции и аргументи
И така, зареждането на аплета започва със зареждане на файла jnlp, който освен списъка с необходимите jar файлове и тяхната кодова база, също така определя аргументите на java (това е много важен момент, по-долу ще научите защо), с които тази java трябва да стартира на клиентската машина. Java започва да изтегля буркани и да ги проверява за безопасност. Тук влиза в действие механизмът за защита на Java, който започва да проверява заредения roast преди да се заредят класове от него. Този механизъм е доста сложен и многостранен: настройка на общото ниво на сигурност при зареждане на аплети и политика за сигурност на Java на клиента (предоставяне на разрешения), настройки за сигурност в манифестите на самите буркани, проверка на цифровия подпис на буркана и т.н. Не искам да се задълбочавам и ще засегна само онези аспекти, които са важни в описаната задача.
За справка: подписването на аплет предполага подписване на jar файлове. Подписването на буркан е изпълнението на java-командата signjar, в резултат на което в буркана се появява информация за ключа, който е подписан в криптирана форма, и всеки ресурс, опакован от буркана, се свързва с определен код, криптиран с този ключ, съдържащ информация за съдържанието на този ресурс. По този начин, ако се опитате да промените подписаното пържене, например като хвърлите някакъв клас там или промените стария, тогава такова пържене ще стане невалидно и няма да премине проверката за сигурност и няма да бъде заредено.
Така че аплетът може да бъде неподписан, самоподписан или подписан с доверен сертификат. В зависимост от версията на клиентската Java, на която е зареден аплетът, нивото на подписване на аплета влияе върху това дали аплетът ще бъде зареден изобщо или ще бъде блокиран, зареден, но с куп предупреждения и съобщения като "Ако се съгласите да стартирате този аплет, тогава ще дойде глобален катаклизъм и всичко ще бъде загубено, така че стартирайте на свой риск и риск",
или зареден с едно красиво и не плашещо съобщение, което не можете да повторите в бъдеще, като щракнете върху съответното квадратче за отметка. Тук стигаме до същинския проблем. По време на решаването на описания проблем нашият аплет Oxygen беше самоподписан. Тоест подписът беше, но фалшив - те сами измислиха публичен ключ и сами генерираха частен ключ за него. Разбира се, при зареждане на такъв аплет, java хвърли фекалии във вентилатора и ругаеше, въпреки че накрая зареди аплета. Но трябваше да се отървем от тези съобщения, така че се нуждаехме от сертификат от доверен сертифициращ орган (Trusted Certifictae Authority).
Така че имаме нужда от сертификат от доверен орган. Как да го получите? Лесно, но забавлението не е евтино. Сертификат за една година ще струва около 500 щатски долара.Използвахме услугите на център www.verisign.com. Трябва да създадете хранилище за ключове със собствен псевдоним и друга информация за издателя (с помощната програма keytool) и да формирате специална заявка (и, разбира се, да платите). В отговор CA изпраща ключовете. Нашите изпратиха цели 3 броя: Code Signing сертификат, междинен CA сертификат и сертификат във формат pkcs7. За типа сертификат JKS се нуждаем от междинен сертификат и сертификат за подписване на код. Първо се добавя междинен сертификат към предварително създаденото хранилище за ключове, а след това основният сертификат за подписване на код. Полученото хранилище за ключове ще се използва за подписване на буркана.
Ако вашите печени преди това са били подписани (и в моя случай те са били подписани или по-скоро самоподписани), тогава преди да ги подпишете отново, първо трябва да премахнете старите подписи. Ако не направите това, тогава, когато заредите аплета, Java ще се задави при първото изпържване и ще ви изпрати по дяволите. Можете да премахнете подписа, например, на ръка - изтрийте .RSA (или .DSA) и .SF файловете от папката META-INF и също така премахнете всички подписи на ресурси Digest от файла на манифеста. За малко да забравя: преди да подпишете буркана, трябва да добавите атрибути за сигурност към манифеста:
Започвайки с актуализация 51 на Java 7, всички буркани, които не съдържат атрибути за защита, автоматично ще бъдат блокирани. И ето скрипта на мравка за това:
Важно: ще ви трябва antcontrib, за да можете да използвате foreach в този скрипт.
И така, почистваме картофите, добавяме необходимите атрибути към манифестите, подписваме, стартираме и ... Отново виждаме предупреждението!
Бащите ще го разберат веднага, но аз все пак ще обясня за всеки случай какво се случва в мишената на тази мравка. В първата част всичко е ясно - създаваме директорията с класове и компилираме кода на нашия аплет там. Моля, имайте предвид, че при компилирането се добавя пътят на класаdaddy lib, който съдържа куп буркани, от които се нуждае аплетът и всички те трябва да бъдат подписани. След това папката JNLP-INF се създава там и нашият оригинален author-component-dita.jnlp се копира там. След това опаковаме всичко това в буркан (това е нашият основен буркан) и го хвърляме в същата папка lib до останалите буркани. Оказва се, че сега имаме 2 jnlp файла: оригиналния author-component-dita.jnlp и APPLICATION.JNLP, пакетирани в jar. Малко ме обърква, добре. Пускам аплета - грешка!
И така, това ли е всичко и когато заредя аплета, най-накрая ще видя дългоочакваното удобно за потребителя съобщение със син щит, че аплетът е доверен, надежден и не буди подозрение? Не вярвайки на щастието си, с треперещи ръце стартирам приложението, зареждам аплета и ...
Ура! Готово е! Най-накрая видях това съобщение със син щит! И като се лигавя от радост, кликвам върху квадратчето „Винаги вярвай на този издател“, то се затваря, аплетът започва да се зарежда и ... тогава се появява това:
Какво . Бързо побелявайки, започвам трескаво да се вкопчвам в кода - какво е толкова несигурно? Като цяло убих още 2 дни, за да намеря този ред във файла jnlp:
Това са java аргументите, с които се стартира аплетът. Така чеаргументите за отстраняване на грешки не са защитени. И ако вашият аплет е подписан и с доверен сертификат, тези аргументи са забранени. Интересното е, че ако вашият аплет е самоподписан, тогава стартирайте аплета дори и с дявола, защото клиентът е предупреден, че изпълнимото приложение е неизвестно, което означава, че е опасно по своята същност.
Ето пълния списък на забранените аргументи: