Monday, April 13, 2020

Insecurities Of WhatsApp's, Signal's, And Threema's Group Chats

Recently, the theoretical and practical analysis of secure instant messenger protocols received much attention, but the focus of prior evaluations mostly lay in one-to-one communication. In this blog post we want to presents the results of our work that focuses on group chat protocols of three major instant messenger applications; namely Signal, WhatsApp, and Threema.

In this blog post, we aim to focus on the practical impact and the found weaknesses identified by our analysis. The interested reader may also look into our paper for more details.


Our Aim and What We Were Looking For

End-to-end encryption protects the confidentiality of communication that is forwarded via central servers to the designated receivers. As a consequence, neither parties on the network route of the messages, nor the provider of the central server (e.g. the WhatsApp server) should be able to read any information out of the observation of the communication. In particular, no other user of the application should have access to the communication. Further it might be desirable to require that also the messages' integrity is end-to-end protected and that a sender is informed about the delivery state of sent messages.
Delivery state information in Signal (upper screenshot) and WhatsApp (lower screenshot)

In a two party scenario, this analysis is rather fixed to two components of the protocol: the key establishment between both parties and the communication channel protection using the established key (mostly consisting of an encryption algorithm and a scheme for providing integrity like MACs or signature schemes).

Regarded attackers


In a group setting, the same attackers apply (network, provider, other users). However the requirements for secure communication differ. It is further necessary that only group members can write to and read content from the group. Additionally, only administrators of the group are able to add new members.

In addition to these standard requirements, we also evaluated the protocols' security guarantees if the client's secrets were revealed (forward secrecy and future secrecy).

Our Approach

We analyzed the mentioned protocols by reading the source code and debugging the apps. We also used alternative open source implementations of Threema and WhatsApp as a help and we traced the network traffic. When using alternative implementations, we only took incoming traffic into account, which was generated by official applications. Thereby we extracted the protocol descriptions and evaluated them regarding the defined requirements.

Our Findings

In WhatsApp and Threema, the provider was able to manipulate the set of members. Threema only allowed the provider to rewind the set of members to a previous state. As a consequence previously removed members could have been added to the group again. The WhatsApp provider is able to arbitrarily manipulate the member set. Thereby further members and administrators can be added to the group. Since the authenticity of group manipulation is not protected, the WhatsApp provider can set the real group administrator as the source of manipulation even though this administrator was not active.

Since Signal's key exchange protocol provides future secrecy, we also evaluated the protocol's ability to recover into a secure group state after a member's state was compromised. The essential weakness here is that a sender only needs to know the static group ID to send a message to the group. If a group member receives a message with the correct group ID, no verification regarding the current member set takes place but the message is directly added to the group communication. Consequently it is sufficient to retrieve the group ID in order to send messages to the group. Since Signal treats content messages the same way as messages for the manipulation of the group set, an attacker who knows the group ID can add herself to the group and thereby read the subsequent group communication.

In addition to this, in all cases the delivery state of sent messages was not securely provided. Threema's group chats do not inform the sender about the delivery state while Signal and WhatsApp do not protect the delivery information on the end-to-end layer. Therefore the central provider can forge this information and drop messages without letting the communicating parties detect this.

Also the order of messages was manipulable for the providers of the applications such that the provider is able to deliver the messages in a different order than they were sent. Threema's weakness of rewinding a group state results from missing replay attack protection.

Impact of Weaknesses

Even though end-to-end encryption is implemented in all analyzed applications, the central providers can largely manipulate the communication in groups and partially also read it.
In all applications, the provider can undetectably drop and reorder messages during the delivery and thereby manipulate the view of the communication such that further attacks can be obfuscated.
The central servers of WhatsApp can be used to add arbitrary users to groups and thereby receive their communication.
To achieve the same result for Signal, it suffices to retrieve the group ID. An earlier member who left the group once still knows this ID since it is static. However, in contrast to WhatsApp, the origin of the manipulation is correctly displayed in the Signal application (which was not the fact when we started our analysis).

As a result, the end-to-end protection of WhatsApp is not sufficient to reach confidentiality in groups. For Signal no future secrecy is reached in groups and Threema was vulnerable to replay attacks which resulted in further weaknesses.

Responsible Disclosure

We disclosed our findings to the developers and received varying response. Threema updated their protocol in version 3.14 such that our attacks are not feasible anymore. Moxie Marlinspike responded that Signal is "working on an entirely new group mechanism that we should be deploying soon". WhatsApp did not hold out the prospect of fixing the described vulnerabilities (Update 01/18: According to Facebook's Security Head, the invite links make a fix more difficult [1]; we proposed a way to solve this issue [2]).

[1] https://twitter.com/alexstamos/status/951169036947107840
[2] https://web-in-security.blogspot.de/2018/01/group-instant-messaging-why-baming.htmlRelated posts

Wirelurker For OSX, iOS (Part I) And Windows (Part II) Samples


PART II

Wirelurker for Windows (WinLurker)

Research: Palo Alto Claud Xiao: Wirelurker for Windows

Sample credit: Claud Xiao



PART I


Research: Palo Alto Claud Xiao WIRELURKER: A New Era in iOS and OS X Malware

Palo Alto |Claud Xiao - blog post Wirelurker

Wirelurker Detector https://github.com/PaloAltoNetworks-BD/WireLurkerDetector


Sample credit: Claud Xiao


Download

Download Part I
Download Part II

Email me if you need the password




List of files
List of hashes 

Part II

s+«sìÜ 3.4.1.dmg 925cc497f207ec4dbcf8198a1b785dbd
apps.ipa 54d27da968c05d463ad3168285ec6097
WhatsAppMessenger 2.11.7.exe eca91fa7e7350a4d2880d341866adf35
使用说明.txt 3506a0c0199ed747b699ade765c0d0f8
libxml2.dll c86bebc3d50d7964378c15b27b1c2caa
libiconv-2_.dll 9c8170dc4a33631881120a467dc3e8f7
msvcr100.dll bf38660a9125935658cfa3e53fdc7d65
libz_.dll bd3d1f0a3eff8c4dd1e993f57185be75
mfc100u.dll f841f32ad816dbf130f10d86fab99b1a

zlib1.dll c7d4d685a0af2a09cbc21cb474358595


│   apps.ipa
│   σ╛«σìÜ 3.4.1.dmg

└───WhatsAppMessenger 2.11.7
            libiconv-2_.dll
            libxml2.dll
            libz_.dll
            mfc100u.dll
            msvcr100.dll
            WhatsAppMessenger 2.11.7.exe
            zlib1.dll
            使用说明.txt


Part I

BikeBaron 15e8728b410bfffde8d54651a6efd162
CleanApp c9841e34da270d94b35ae3f724160d5e
com.apple.MailServiceAgentHelper dca13b4ff64bcd6876c13bbb4a22f450
com.apple.appstore.PluginHelper c4264b9607a68de8b9bbbe30436f5f28
com.apple.appstore.plughelper.plist 94a933c449948514a3ce634663f9ccf8
com.apple.globalupdate.plist f92640bed6078075b508c9ffaa7f0a78
com.apple.globalupdate.plist f92640bed6078075b508c9ffaa7f0a78
com.apple.itunesupdate.plist 83317c311caa225b17ac14d3d504387d
com.apple.machook_damon.plist 6507f0c41663f6d08f497ab41893d8d9
com.apple.machook_damon.plist 6507f0c41663f6d08f497ab41893d8d9
com.apple.MailServiceAgentHelper.plist e6e6a7845b4e00806da7d5e264eed72b
com.apple.periodic-dd-mm-yy.plist bda470f4568dae8cb12344a346a181d9
com.apple.systemkeychain-helper.plist fd7b1215f03ed1221065ee4508d41de3
com.apple.watchproc.plist af772d9cca45a13ca323f90e7d874c2c
FontMap1.cfg 204b4836a9944d0f19d6df8af3c009d5
foundation 0ff51cd5fe0f88f02213d6612b007a45
globalupdate 9037cf29ed485dae11e22955724a00e7
globalupdate 9037cf29ed485dae11e22955724a00e7
itunesupdate a8dfbd54da805d3c52afc521ab7b354b
libcrypto.1.0.0.dylib 4c5384d667215098badb4e850890127b
libcrypto.1.0.0.dylib 3b533eeb80ee14191893e9a73c017445
libiconv.2.dylib 94f9882f5db1883e7295b44c440eb44c
libiconv.2.dylib fac8ef9dabdb92806ea9b1fde43ad746
libimobiledevice.4.dylib c596adb32c143430240abbf5aff02bc0
libimobiledevice.4.dylib 5b0412e19ec0af5ce375b8ab5a0bc5db
libiodb.dylib bc3aa0142fb15ea65de7833d65a70e36
liblzma.5.dylib 5bdfd2a20123e0893ef59bd813b24105
liblzma.5.dylib 9ebf9c0d25e418c8d0bed2a335aac8bf
libplist.2.dylib 903cbde833c91b197283698b2400fc9b
libplist.2.dylib 109a09389abef9a9388de08f7021b4cf
libssl.1.0.0.dylib 49b937c9ff30a68a0f663828be7ea704
libssl.1.0.0.dylib ab09435c0358b102a5d08f34aae3c244
libusbmuxd.2.dylib e8e0663c7c9d843e0030b15e59eb6f52
libusbmuxd.2.dylib 9efb552097cf4a408ea3bab4aa2bc957
libxml2.2.dylib 34f14463f28d11bd0299f0d7a3985718
libxml2.2.dylib 95506f9240efb416443fcd6d82a024b9
libz.1.dylib 28ef588ba7919f751ae40719cf5cffc6
libz.1.dylib f2b19c7a58e303f0a159a44d08c6df63
libzip.2.dylib 2a42736c8eae3a4915bced2c6df50397
machook 5b43df4fac4cac52412126a6c604853c
machook ecb429951985837513fdf854e49d0682
periodicdate aa6fe189baa355a65e6aafac1e765f41
pphelper 2b79534f22a89f73d4bb45848659b59b
sfbase.dylib bc3aa0142fb15ea65de7833d65a70e36
sfbase.dylib bc3aa0142fb15ea65de7833d65a70e36
sfbase_v4000.dylib 582fcd682f0f520e95af1d0713639864
sfbase_v4001.dylib e40de392c613cd2f9e1e93c6ffd05246
start e3a61139735301b866d8d109d715f102
start e3a61139735301b866d8d109d715f102
start.sh 3fa4e5fec53dfc9fc88ced651aa858c6
stty5.11.pl dea26a823839b1b3a810d5e731d76aa2
stty5.11.pl dea26a823839b1b3a810d5e731d76aa2
systemkeychain-helper e03402006332a6e17c36e569178d2097
watch.sh 358c48414219fdbbbbcff90c97295dff
WatchProc a72fdbacfd5be14631437d0ab21ff960
7b9e685e89b8c7e11f554b05cdd6819a 7b9e685e89b8c7e11f554b05cdd6819a
update 93658b52b0f538c4f3e17fdf3860778c
start.sh 9adfd4344092826ca39bbc441a9eb96f

File listing

├───databases
│       foundation
├───dropped
│   ├───version_A
│   │   │   com.apple.globalupdate.plist
│   │   │   com.apple.machook_damon.plist
│   │   │   globalupdate
│   │   │   machook
│   │   │   sfbase.dylib
│   │   │   watch.sh
│   │   │
│   │   ├───dylib
│   │   │       libcrypto.1.0.0.dylib
│   │   │       libiconv.2.dylib
│   │   │       libimobiledevice.4.dylib
│   │   │       liblzma.5.dylib
│   │   │       libplist.2.dylib
│   │   │       libssl.1.0.0.dylib
│   │   │       libusbmuxd.2.dylib
│   │   │       libxml2.2.dylib
│   │   │       libz.1.dylib
│   │   │
│   │   ├───log
│   │   └───update
│   ├───version_B
│   │       com.apple.globalupdate.plist
│   │       com.apple.itunesupdate.plist
│   │       com.apple.machook_damon.plist
│   │       com.apple.watchproc.plist
│   │       globalupdate
│   │       itunesupdate
│   │       machook
│   │       start
│   │       WatchProc
│   │
│   └───version_C
│       │   com.apple.appstore.plughelper.plist
│       │   com.apple.appstore.PluginHelper
│       │   com.apple.MailServiceAgentHelper
│       │   com.apple.MailServiceAgentHelper.plist
│       │   com.apple.periodic-dd-mm-yy.plist
│       │   com.apple.systemkeychain-helper.plist
│       │   periodicdate
│       │   stty5.11.pl
│       │   systemkeychain-helper
│       │
│       └───manpath.d
│               libcrypto.1.0.0.dylib
│               libiconv.2.dylib
│               libimobiledevice.4.dylib
│               libiodb.dylib
│               liblzma.5.dylib
│               libplist.2.dylib
│               libssl.1.0.0.dylib
│               libusbmuxd.2.dylib
│               libxml2.2.dylib
│               libz.1.dylib
│               libzip.2.dylib
├───iOS
│       sfbase.dylib
│       sfbase_v4000.dylib
│       sfbase_v4001.dylib
│       start
│       stty5.11.pl
├───IPAs
│       7b9e685e89b8c7e11f554b05cdd6819a
│       pphelper
├───original
│       BikeBaron
│       CleanApp
│       FontMap1.cfg
│       start.sh
└───update
        start.sh
        update

Related articles


  1. Top Pentest Tools
  2. Pentest Tools Kali Linux
  3. Pentest Tools Alternative
  4. Tools 4 Hack
  5. Hack Tools
  6. Hacker Tools For Mac
  7. Pentest Tools Open Source
  8. Blackhat Hacker Tools
  9. Hacker
  10. Hacker Techniques Tools And Incident Handling
  11. Hacking Tools 2020
  12. Hacker Search Tools
  13. Hacker Tools Linux
  14. Nsa Hack Tools
  15. Hacking Tools Usb
  16. Hackrf Tools

Parrot Security OS 4.7 Released With New Linux Kernel, Menu Structure, Tools Improvements And Many Changes


In Sep 18 2019, Parrot Security OS 4.7 has released, with many new following changes below.

Latest Linux 5.2.x series
   The new ISO files of Parrot 4.7 are being released only now, but we were the first Debian derivative distribution to introduce Linux 5.1 and 5.2 to all our users, and now ParrotSec team is ready to offer it also with our ISO files rebild cycle to support more devices and integrate all the latest linux features from the beginning.

New sandbox behavior (opt-in rather than opt-out)
   Sandboxing is a great thing, and ParrotSec team was in the first line when they introduced our custom Firejail and AppArmor solution for the first time many years ago. We still want to improve such feature and ParrotSec team has a whole team dedicated to improve sandboxing and hardening of the Parrot Security OS system, but ParrotSec team had to face the many users with issues caused by the restrictions of our sandbox.

   In Parrot Security OS 4.7 the sandbox is disabled by default, and users can decide wether to start an application sandboxed or not. You can easily start the sandboxed version of an installed program from the /sandbox/ folder or from a dedicated menu that ParrotSec team plans to improve in the future (meanwhile the search feature of the bottom menu will fit all your needs), or you can re-enable it by default by using the firecfg tool.

New menu structure and tools improvements
   The pentesting menu structure was refactored and re-designed to make tools easier to access in a more logical hierarchical structure. New tools were also added to the project, and ParrotSec team plans to add even more in the future. Not all of them are going to be pre-installed, but a good set of tools in our repository enables pentesters to build up the perfect pentest system for their specific needs, regardless the default package selection picked by ParrotSec team.

Domain changes
   To reflect the neutrality of a distro that started as a pentest-only system and became more general purpose later with Parro Home, the community voted through a democratic process to switch to parrotlinux.org as the new default domain of the project.

   ParrotSec team will still use ParrotSec.org for other things (included the old email addresses), and they introduced other project domains to handle specific parts of the infrastructure.

Repository changes
   ParrotSec team is preparing to integrate a future LTS branch, so they decided to rename the current repository from stable to rolling. Nothing changes for the end user, and the current Parrot Security OS branch will continue to behave the same as before, but now with a different name to better reflect the rolling release nature of the system, waiting for the LTS edition to join the Parrot Security OS family along side the rolling branch in a similar way OpenSUSE does.

New MATE 1.22 release: Parrot Security OS 4.7 ships with the latest MATE 1.22 desktop environment.

Miscellaneous: New Firefox Browser 69, the latest Radare2 and cutter versions and many other important upgrades are all aboard as expected in a properly developed rolling release distro.

How to upgrade to the lastest Parrot Security OS version
   You can update your existing Parrot Security OS system with this command:
sudo parrot-upgrade

   Or use the raw apt command
sudo apt update
sudo apt full-upgrade


   Don't forget to use this command regularly (at least once a week) to receive the latest security updates and bugfixes from the Parrot Security OS repository.

   Or you can download the latest release from official download page.

More articles


  1. Black Hat Hacker Tools
  2. Hacker Tools Hardware
  3. Hacking Tools
  4. Hacker Tools Online
  5. Pentest Tools Subdomain
  6. Hacking App
  7. Hacker Tools Online
  8. Pentest Tools Alternative
  9. Hacking Tools Windows 10
  10. Physical Pentest Tools
  11. Hack Tools Download
  12. Hack Tools Github
  13. Tools Used For Hacking
  14. Tools Used For Hacking
  15. Easy Hack Tools
  16. How To Install Pentest Tools In Ubuntu
  17. Pentest Tools Open Source
  18. Hacking App
  19. Nsa Hack Tools Download

Saturday, April 11, 2020

Let's Go To The Ring!

Just a quick note here to alert anyone to a new project I've been working on: "Let's Go to the Ring!"

"Let's Go to the Ring!" is a podcast about World Championship Wrestling (and its predecessor, Jim Crockett Promotions). Together, John, Alec, and I are going through WCW's big shows, series by series, starting with all the Starrcades, to explore what makes each series unique and what themes come out across the shows, along with the high and low points of each series. It's been an interesting journey so far and I'd like to invite you to come along with us as we discover what made WCW such a fascinating company and why its legacy endures so many years later.

If you're interested, new episodes can be found on iTunes, Google Play Podcasts, or Spotify, or at http://lets-go-2-the-ring.cast.rocks/

A website, which will also provide episode links, is available at: https://blog.lg2tr.com/

You can follow us on Twitter at https://twitter.com/LetsGo2theRing or on Facebook at https://www.facebook.com/LetsGo2theRing/

We hope you enjoy the show.

Wednesday, April 08, 2020

Beach Fallacy

This month we celebrate our store's 15th anniversary. I am happy to report in year 15 I learned from failure. Failure means I'm still trying to innovate and change things up. This particular failure was one I recently realized while speaking with a friend who just sold his business. It comes down to this: The idea you can remotely manage your business with an installed manager is temporary at best. The 4-Hour Work Week may work for a turn key business, but most businesses are not even remotely turn key.

You may have a great manager, but they won't be there forever, and the process of getting a new one trained up, will be time consuming and not conducive to lying on a beach. So even if you have the skills to train them, how fast can they reasonably achieve mastery? In general, the concept of remote management for me has gone from something I might be able to do full time to something that may be possible half the time, that half determined by chaos in my business.

So I may be able to live in Mexico, for example, six months out of the year, a random six months at that, but I better have a place to stay when it all falls apart and I have to retrain staff for six months back home. The idea you can do this all remotely, living elsewhere, is a myth.

Here are the three areas that I see, that if I were a better owner or had magic powers, I would be able to solve to extend my six month theory. If you think you have skills in how to quickly train up candidates in these areas, this is where I would pay for a consultant:

  • Gross versus Net. A bad manager will spend your business into the ground with no apparent benefit. An alright manager will spend your money on long term investments that pay off later, but still leave you in the poor house right now, as they usually don't understand cash flow. A great manager will always spend cautiously and be conscious of the bottom line and the cash needs of the business.
I was not a "great manager" of cash until I had distributions from the net profit. I became incentivized to focus on net. Unless you can incentivize someone with bonuses for producing net profit, you'll always be watching your back (which you will always do regardless). Or you may train someone to be so overly cautious with your money, they take no chances at all.
  • Tight Employee Management. A good manager sets employee expectations via an accurate job description and solid training. The manager manages those expectations through the employees tenure by means of additional training and corrective action. Then they reward or penalize employee performance based on how those results are achieved. 
Most managers, most people, can't do this. They simply can't without some very good training, and even then it's not within most peoples personality range. I can tell you from the corporate world that most managers are untrained and awful. Training a manager to master this process will ensure you always have good people, but good luck finding someone skilled at this for what you can afford and good luck developing the skills in yourself when you've probably only had bad managers.
  • Inventory Accuracy. Does anyone other than you really care if your POS system is only 90% accurate? Inventory accuracy results in better buying practices, higher sales, lower taxes, and happier customers. Yet, it is very difficult to have a manager who cares about this accuracy as much as you. It is very much tied to net profit. If you find someone outraged at inaccuracy, and they have skill in the other two areas, find a way to groom that employee for manager. 

So those are the three areas that require an owner to be involved in a store on a near daily basis. This does not mean your store sucks if this is the case. In fact, there's no reason this should harm the value of your business if, say, you wanted to sell it. Someone with these three concerns will always need to have their hand on the wheel, but it's unlikely to be an employee for very long.

Saturday, March 28, 2020

Gaslands And Kill Team

Those are the two projects I am spending my time on right now.

Oh, and I am doing fine, just incredibly busy. Dealing with a lot of things, but its improving, if you are worried about me. And if you are, well... thanks. I appreciate it.

Monthly Progress Report For My Twitch Channel, FuzzyJCats, Nov 25 Through Dec 24

Twitch Channel FuzzyJCats

During this month of streaming, I continued to work on improving the usual chatting and gaming at the same time, and not using filler words, though I noticed I constantly slip into using a lot of filler words as they help to fill dead air.

I was also trying to find out how we can tell if we're entertaining. Certainly watching your VoDs help you notice if you're articulate or not, if you move around too much such that you're off the facecam, but I still can't tell if my streams are entertaining.

However, I started having an inkling as to what's entertaining to viewers this month. Since the entertainment is in real-time, and people are chatting, like with everything, people find you very interesting if you ask about them and talk about their issues. This is try-hard but cbenni.com can let you review your logs so you can remember what your viewers say, so when they show up the next time, you can ask them about that specific thing. 

For instance, if they mention that they're starting a new job, you can ask them how work is coming along, if they like their new boss, coworkers, and so on and so forth.

So another try-hard method is after each stream, I have been more or less writing these topics to talk about when the viewer shows up next.

Again, this is very try-hard, but it can help not only make your chat more entertaining for specific viewers, but with these topics on hand, it will help reduce dead air.


Aside from the usual goal of chat and gaming ratio, working on dead air, and removing filler words while streaming, improvements to be made is to be more aware of my viewers so I can ask them about issues next stream. 

The How of Happiness Review

XCOM - The Long War Files

I recently became obsessed with XCOM: Enemy Unknown and decided to try out the player made overhaul known as "Long War" which expands the base game to be exceptionally difficult and in most regards more like an actual war. I decided to blog the exploits of my team in a yet unnamed project. I'd like each post in the series to be a stand-alone short story about the experiences of those involved - with some scattered pictures of the mission highlights. One of the greatest parts of the XCOM series is the stories it generates about these characters and their ordeals. I hope to capture some of that and share it here in this writing project.



Table of Contents

Friday, March 20, 2020

SuperTuxKart 1.0 Release


It's been a long and winding road for mascot racer SuperTuxKart, but after more than ten years of continuous and dedicated progress, the team has finally announced the release of build 1.0, marking an important development milestone for the project.

 As quoted from the official release post:

Yes, if you have followed our development a bit, that might be a bit of a surprise. But we have been asked why we don't call this release 1.0, and the majority of us developers discussed this and decided that indeed this release is a major milestone that deserves the big 1.0 number.

Indeed a nice surprise and definitely a big step forward with the inclusion of online multiplayer!

See more new features in the official release video:



As usual you can download the game here. Also don't forget to head over to our forums to provide some feedback to the developers.


Code License: GPLv3
Assets License:
CC BY-NC-SA 3.0

Thursday, March 19, 2020

Tech Book Face Off: Rails AntiPatterns Vs. The Rails 5 Way

It's been a while since I've cracked open a Ruby on Rails book, and there were still a couple of these books that I've been meaning to read. So far the Rails books I've read have been beginner's books and tutorials. With this latest pair of books, I wanted to go deeper into Rails and learn how to program fluently in the framework. The first book, Rails AntiPatterns: Best Practice Ruby on Rails Refactoring by Chad Pytel and Tammer Saleh, was published way back in 2010 when Rails 2.3 was cutting edge. I took a chance that the book would focus more on timeless advice than version-specific tips and tricks. The opposing book, The Rails 5 Way by Obie Fernandez, was published much more recently at the end of 2017 and should be at less risk of being out-of-date. Although, it looks like Rails 6 will be out soon. One thing's for sure: technology doesn't stand still, but that shouldn't matter too much if the books take that into account. Let's see how they fare.

Rails AntiPatterns front coverVS.The Rails 5 Way front cover

Rails AntiPatterns


Most programming books will tell you the right way to do things and give examples of how to implement that advice. This book takes a different tack and instead shows you what not to do, with examples of how to refactor those mistakes into clean Rails code. This change in approach is refreshing for the intermediate to advanced programmer because over time we develop certain habits as we try to discover how to do things in a language or a framework, and they're not always the best (or even very good) ways of doing those things. Having a book to help identify where our code has gone astray and how to fix it is a helpful tool indeed.

I was a bit worried about reading a book specifically about Rails that was written so many versions ago, being that Rails 2.3 was out at the time and we're now heading into Rails 6.0. I normally don't mind reading older books about programming in general, since those books have been filtered by time and tend to contain plenty of wisdom that has survived current fads. However, this is a book about a specific web framework, so if it is over eight years old, how could it possibly still be relevant? I needn't have worried. Most of the book focuses on general good programming practices within the context of the Rails environment. Such advice is still as valid in Rails 6.0 as it was in Rails 2.3, even if some of the implementation details have changed.

The structure of the book works well, with ten chapters each focusing on a different topic of the Rails framework. These topics range from the obvious models, views, and controllers on which the Rails architecture is based, to the related services, testing, and databases that are all a part of web application programming. Each topic covers a few antipatterns with descriptions of a common programming mistake and why it's wrong, followed by one or more solutions that fix up the antipattern into beautiful, DRY code. The obvious solutions—like that views should contain strictly display logic, controllers should be thin, and models should contain all of the business logic, but broken out into helpers and plain Ruby objects—are covered along with a number of less obvious antipatterns. Some of the more extended solutions are quite satisfying to follow as the refactorings morph an ugly hack into a pretty Rails implementation.

Throughout these refactored antipatterns the authors relate clear reasons for why things should be done a certain way and sound advice on how to choose between competing options. For example, when discussing whether or not to use scopes to create chainable filters on models, they say:
There are downsides to this approach, including problems with readability and simplicity, as well as abuse of the Law of Demeter. Whether you use this approach is a judgment call on your part. Will you use the added flexibility? Is it better than defining a handful of separate finders? Like many advanced refactorings, this one has no easy answer and depends greatly on your tastes.
I appreciate the honesty of this advice. In programming, as in most things in life, not all rules are hard and fast. Multiple good options can and do exist, and in these cases it comes down to a judgement call from the programmer, given the context of the specific situation. Experience and taste will develop into a programmer's style, and as long as they're not making a poor choice for the wrong reason, it's okay to prefer one viable option over another.

The authors aren't always so amenable to choice in correcting antipatterns. They do discourage attempts at divining the future, as in this example:
Developers new to the template pattern tend to want to err on the side of flexibility. This is a form of future-proofing, and it's a mistake—especially when working in a language as geared toward agile development and the refactoring cycle as Ruby.
It's almost always better to spend time fixing real problems in the here and now instead of trying to predict and head off future problems that may never happen.

The whole book was full of insights like these, and it was all packaged in easy-to-read prose and concise, relevant examples of how not to write Rails code, followed by how to fix it. I found it to be a quite enjoyable way to learn better Rails programming practices, and it reminded me of an old chess book that had followed a similar format: How Not to Play Chess. Seeing the mistakes that can be made and their consequences clearly laid out can prove quite helpful in identifying our own mistakes and seeing the path to correcting them. This teaching method was expertly executed in Rails AntiPatterns, and I highly recommend giving it a read if you do any programming in Rails.

The Rails 5 Way


This was definitely the longest book on a programming language or framework that I've read in a while. Weighing in at over a thousand pages, it definitely achieves tome status, and strives to be a comprehensive map of the Rails 5 framework. The forwards and introduction recommend reading it straight through at least once to get the lay of the land and see everything that's available in Rails before using it as a reference.

I would agree that knowing what tools are available in any given language or framework is half the battle when attempting to develop solutions as efficiently as possible. If you know that something you want to do is possible and you know where to look to research how to do it, then you're already ahead of the game in reaching an optimal solution. However, I was not going to read all the way through this book, considering the last third of it is a pure reference listing of the Active Model and Active Support APIs. That's skim-worthy material at best.

At least another third of the non-appendix part of the book is also reference listings of various APIs in the Rails framework. The trouble with this reference material is that it is interspersed with actual guidance on how to use the different parts of Rails. That makes it much harder to skim through the boring, tedious method descriptions without missing tidbits of more useful information, so most of the book was kind of a slog.

Obie Fernandez took a slightly unconventional approach to covering Rails, and instead of starting with Active Record, he started at a high level by covering the Rails configuration and environments, then followed the flow of a request by going into routes, REST, resources, and controllers before getting to Active Record. After five chapters of the various aspects of Active Record, he continued with Action View, helpers, and Haml, followed up by an assortment of short chapters on session management, security, Action Mailer, caching, background processing, Ajax, Turbolinks, Action Cable, and testing with RSpec. Whew. Like I said, comprehensive, and even if some things couldn't be included in depth, they were at least mentioned so that the reader could be aware of them and do more research on their own.

Some chapters were quite useful and informative, like the main chapters on the MVC architecture of Rails. These chapters contained a fair amount of good advice and recommendations that can save developers a lot of trouble, such as:
Rails' schema definition provides the authoritative record of truth for the latest version of your database schema. If you need to recreate your database on another server, you should be using db:schema:load, not running all the migrations from scratch.
Anyone who's tried to run a long chain of migrations while setting up an application on a new machine can attest to the futile debugging situation you end up in when one of the migrations inevitably fails halfway through. Using the schema is definitely the way to go. I also found the chapters on security, caching, and Turbolinks to be quite helpful, and I learned a bunch of great things that will help me build better Rails applications.

On the other hand, there were large swaths of the book that were pure drudgery. Most of the helpers chapter was like this with page after page of very similar method descriptions:
11.3.1 asset_path(source, options = {})
Computes the path to asset in public directory. If :type options is set, a file extension will be appended and scoped to the corresponding public directory. All other asset *_path helpers delegate through this method.

<...code example...>

11.3.2 asset_url(source, options = {})
Computes the full URL to an asset in the public directory. This will use asset_path internally, so they behave the same way. If the :host option is set, it overrides the global config.action_controller.asset_host setting normally set in config/environments/production.rb.

asset_url "application.js", host: "http://cdn.example.com" # => http://cdn.example.com/assets/application.js

Also aliased as url_to_asset.
Ugh. This kind of stuff is much easier to search for in the online Rails documentation when you need to look it up, not by paging through a giant book. I was also surprised at how much of these method descriptions ended with comments about how useless they were. Maybe 20% of the methods would have a description of what they did with a code example, and then Fernandez would end it with saying he had never found a use for this method or you would never want to do things this way because some other method was much better. That got more than a little frustrating as the book dragged on.

It may sound a bit strange to criticize this book for including ways not to do things in Rails, having just praised a book whose entire structure was showing how not to do things and then showing the right way, but this is different. In Rails AntiPatterns, the author was showing common mistakes when programming in Rails and how to fix those mistakes by using Rails the right way. My complaint with The Rails 5 Way is that time is spent describing irrelevant methods that may have been included in the framework for completeness or for a specific, uncommon use case, but are hardly ever used in practice. When those things are included in a book whose title asserts that this is how things should be done, it muddies the waters.

Between the appendices, the long lists of method descriptions, and the inclusion of dozens of methods that are rarely used, this book is probably three to four times longer than it needs to be, all for the sake of being comprehensive. It was light enough on actual recommendations for how to use Rails, focusing more on every single thing that's available, that a more appropriate title would simple be The Rails 5 Documentation.


I much prefer reading programming books that directly address the 'how' and 'why' of programming, like these books I previously reviewed on how to use Rails. The Ruby on Rails Tutorial is especially good and the latest version is also up-to-date with Rails 5.  Even Rails AntiPatterns is still relevant nearly a decade later because it addresses the fundamentals of developing in Rails. I would rather leave the 'what' of programming to the online documentation where it is easily searchable and stays updated to the latest version of the tools. In that respect The Rails 5 Way falls flat. It would have been a much more compelling book if it had stripped out all of the drab documentation and focused on showing the right way to program in Rails and explaining why that was the best way to do it. As it is, reading through Rails AntiPatterns and referring to the online documentation is the more productive path.