time warner cable – different person, different problem?

I haven’t a problem that was maddening when dealing with Time Warner since 2010. It’s that time again.

Background

My cable/DVR box has been slowing getting worsening problems for a while:

  1. freezing periodically for a few seconds
  2. saying there was 0% recorded (a reboot solved that, but it happened about once a month)
  3. turning off and not recording with a reboot. then after the reboot would start recording the middle of a show as if it were a long standing agreement

As I had shows I wanted to watch on the DVR, I chose to live with the first two problems. The third one is core functionality of a DVR so had to deal with it and get a different DVR.

Saturday

I went to the Time Warner store. I returned the Scientific American box and was given a “new” Samsung box. And by “new” I mean a box that someone else returned, they presumably tested and then gave to me. Here’s what happened:

  1. I plugged in the box and it told me to call Time Warner to activate. I haven’t had to do that when trading boxes in the past, but ok. That’s reasonable. They activated the box and had me restart the box. I appeared to have TV.
  2. I went to “Free Primetime On Demand” and got a message to call Time Warner. The rep says she needs to check if it is on my plan. It is FREE primetime on demand. I’m pretty sure it is on everyone’s plan. (This is the station for network tv after it airs. Which I wanted to watch because my DVR wasn’t working last week when I tried to record them.) She eventually gets back to me and agrees I should have it. Guess what the solution was? Reboot the box. I imagine she did something at her end as well.
  3. A little later in the day, I found that cable stations would freeze after a few seconds of play. Network stations (over the air equivalents) played just fine. When I called time warner she “runs a signal test” and tells me the problem is with the box and they can send a tech. If the problem is with the box, I can go to the store and trade boxes again. I don’t need to wait for a tech. When I complain I don’t want to wait for a tech, she tells me it won’t come until Tuesday if they mail a box. I don’t want them to mail the box. I then tried rebooting again.
  4. Provisioning – H/E error – We never got to the bottom of this one although it sounds like an issue with the box. (I also had noCP, but that was when I had the box plugged in wrong.) The tech “ran a signal test.” The tech claimed the provisioning error was because it was a used box and it was downloading updates. At 6:30pm, the rep says she will call me back at 8:30pm to follow up.
  5. She calls at just before 11pm. That’s late to be calling someone. What if I had children who were sleeping? At 11pm, she “ran a signal test” and told me the problem was with the box.

Sunday

Back to the Time Warner store. The rep lives near me and asked if there was construction nearby. There was. He then runs a signal test and tells me there is a problem with the signal. As I spoke to several people who did that the previous day who “ran a signal test”, I was suspicious. He shows me a red screen. However, the cable box was in my hand rather than plugged in at home so still suspicious. He tells me that they need to send a tech to check/fix the signal. Sigh. I give up. Fine. I’ll arrange to be home for a tech to come.

Monday

I had an appointment for between 3 and 4pm. That gave me time to work for half a day in the office and telecommute the rest of the day. I got home around 2pm. I have two messages on my cell phone voicemail and one on my home phone. Two messages say that if I don’t pick up, my appointment will be cancelled. The last says my appointment is confirmed and the tech will call before coming up. Weird.

Since I had time, I decided to go buy lunch. I get back at 2:15pm. At 2:21pm, the tech arrives. That’s not between 3 and 4. What if I wasn’t home? Would I have missed my appointment?

The tech said the problem was the box. (No kidding, this was apparent on Saturday.) He installed a new box. A brand new box.  This time a Cisco one. Which requires over 40 minutes of software downloads before it starts. Which their tech had to be here for. So he got paid to watch videos on my couch for almost an hour. This isn’t his fault. The tech did a great job. He was helpful and polite. Just not necessary. I am perfectly capable of plugging in a box and waiting for an hour.

 

fixing clickjacking and brute force login for jforum

I’ve been blogging about some of the security fixes we’ve made in the CodeRanch fork of JForum such as XSS with quotes and CSRF. Today it is time to write about Clickjacking and preventing brute force logins.

Clickjacking

Clickjacking is an attack where someone includes your site in transparent frames and the attacker intercepts anything typed in/clicked. We had originally decided not to do anything about ClickJacking because we want our site to be available in frames. For example, DZone serves the main page in a frame when asking people to vote on it.

However, that doesn’t mean that we shouldn’t protect anything. We decided to protect the most critical parts of the site – the admin screens and the login form. That leaves the read only pages (which we don’t mind framed) and editing posts/user info (which is displayed publicly anyway).

The implementation turned out to be simple. We added this header to the relevant pages. (the admin screens are always within a frame on the site and the login screen is when an admin’s session times out).

response.setHeader("X-Frame-Options", "SAMEORIGIN");

It turned out the method only needed to be called from two places: UserAction (for login) and the AdminCommand (for the admin console).

While this isn’t complete protection, it is certainly better than the nothing we had before. And it is easy to add more screens in the future if we need to. We also didn’t include the JavaScript framebusting logic for older browsers because Google Analytics says hardly of our users are on such browsers.

Preventing Brute Force Logins

Another security issue that we knew about but didn’t fix because “it wasn’t a problem” was preventing brute force logins. It seemed like high time to do something about that one too. While this was more work than fixing Clickjacking, it wasn’t a huge deal either. The logic is mostly in one (well unit tested) class that gets called from the method with the login check. There is also a property file to externalize the number of attempts/wait. And a job to clear out the Map once a day for attempts where the IP gives up and goes away.

The idea is that an IP gets a number of “free” attempts. After that more login attempts from that IP must wait longer and longer. Once a user logs in successfully from that IP or there are no attempts for a certain amount of time,t he clock starts over and the “free” attempts are back.

This approach doesn’t protect against a distributed attack because the IPs are different. (I choose the IP based approach so someone can’t lock out a user’s account specifically by targeting them and entering invalid passwords. That said, we aren’t running a bank so it seems unlikely for someone to go through that much effort to attack us.

Note: I got a private comment to be careful about IP blocking due to companies using a single public IP for thousands of users. This approach is NOT using IP blocking. Let’s say have 1000 users from InfoSys. (We probably have more, but that’s not the point.) Most of those users will either know their password or use the “remember password” functionality. If a few forget their password and type in a bunch of wrong attempts, the time throttling kicks in.  It seems unlikely for multiple users to having this problem at the same time. And as soon as anyone from the company (IP) has a correct password, the “penalty” count resets.

Code for the curious:

package net.jforum.repository;

import java.util.*;

import net.jforum.util.preferences.*;

/**
 * We prevent brute force login attacks by throttling how often we will check
 * credential after three failed logins from the same IP since the last success.
 * If there are no failures within an hour, the clock will restart on this
 * throttling.
 *
 * @author Jeanne
 * @version $Id: $
 */
public class FailedLoginRepository {
    private static final int NUM_SECONDS_IN_MINUTE = 1000 * 60;
    private static FailedLoginRepository cache = new FailedLoginRepository();
    private Map<String, List<Date>> failedLogins;
    private int maxLoginsBeforeThrottling;
    private int numMinutesForReset;
    private int[] throttlingDelay;

    // ----------------------------------------------------------------
    public FailedLoginRepository() {
        failedLogins = new HashMap<String, List<Date>>();
        numMinutesForReset = SystemGlobals.getIntValue(ConfigKeys.BRUTE_FORCE_PREVENTION_NUM_MINUTES_FOR_RESET);
        String waitTimes = SystemGlobals.getValue(ConfigKeys.BRUTE_FORCE_PREVENTION_WAIT_TIMES);
        setWaitsAsIntArray(waitTimes);
        setMaxLoginsBeforeThrottling();
    }

    private void setMaxLoginsBeforeThrottling() {
        for (int i = 0; i < throttlingDelay.length; i++) {
            if (throttlingDelay[i] == 0) {
                maxLoginsBeforeThrottling++;
            }
        }
    }

    private void setWaitsAsIntArray(String waitTimes) {
        String[] stringArray = waitTimes.split(",");
        throttlingDelay = new int[stringArray.length];
        for (int i = 0; i < throttlingDelay.length; i++) {
            throttlingDelay[i] = Integer.parseInt(stringArray[i].trim());
        }
    }

    // ----------------------------------------------------------------
    public static FailedLoginRepository getInstance() {
        return cache;
    }

    // ----------------------------------------------------------------
    /**
     * After a successful login from the API, remove the blocks. This indicates
     * the user just mistyped and not a hacker.
     *
     * @param ip
     */
    public void successfulAttempt(String ip) {
        failedLogins.remove(ip);
    }

    // ----------------------------------------------------------------
    /**
     * Keep track of time of login failure
     *
     * @param ip
     * @param now
     */
    public void failedAttempt(String ip, Date now) {
        removeOldAttempts(ip);
        List<Date> fails = failedLogins.get(ip);
        if (fails == null) {
            fails = new ArrayList<Date>();
            failedLogins.put(ip, fails);
        }
        fails.add(now);
    }

    public void failedAttempt(String ip) {
        failedAttempt(ip, new Date());
    }

    // ----------------------------------------------------------------
    /**
     * If there haven't been any failed attempts from that IP in the last hour,
     * start over.
     *
     * @param ip
     */
    private void removeOldAttempts(String ip) {
        List<Date> fails = failedLogins.get(ip);
        if (fails != null) {
            Date lastFail = getLastFail(fails);
            Calendar cal = Calendar.getInstance();
            cal.add(Calendar.MINUTE, -numMinutesForReset);
            if (lastFail.before(cal.getTime())) {
                failedLogins.remove(ip);
            }
        }
    }

    private Date getLastFail(List<Date> fails) {
        Date lastFail = fails.get(fails.size() - 1);
        return lastFail;
    }

    public void removeAllOldAttempts() {
        for (String ip : failedLogins.keySet()) {
            removeOldAttempts(ip);
        }
    }

    // ----------------------------------------------------------------
    public boolean shouldCheckPassword(String ip) {
        removeOldAttempts(ip);
        int waitRemaining = numberMinutesUntilNextAllowedLogin(ip, new Date());
        return waitRemaining == 0;
    }

    public boolean shouldCheckPassword(String ip, Date now) {
        removeOldAttempts(ip);
        List<Date> fails = failedLogins.get(ip);
        return fails == null || fails.size() <= maxLoginsBeforeThrottling;
    }

    // ----------------------------------------------------------------
    public int numberMinutesUntilNextAllowedLogin(String ip) {
        return numberMinutesUntilNextAllowedLogin(ip, new Date());
    }

    /**
     * Contains algorithm for delays: see if already waited number of minutes
     * need to wai
     *
     * @param ip
     * @return
     */
    public int numberMinutesUntilNextAllowedLogin(String ip, Date now) {
        List<Date> fails = failedLogins.get(ip);
        if (fails == null) {
            return 0;
        }
        int index = fails.size() - 1;
        if (index >= throttlingDelay.length) {
            index = throttlingDelay.length - 1;
        }
        int delay = throttlingDelay[index];
        Date lastFailure = getLastFail(fails);
        int numMinutesWaited = (int) (now.getTime() - lastFailure.getTime()) / NUM_SECONDS_IN_MINUTE;
        int result = delay - numMinutesWaited;
        // if delay is over, do need to wait longer
        if (result < 0) {
            result = 0;
        }
        return result;
    }
}

 

Trying and failing to find usage of a character style in open office writer

Warning: this procedure does not work. I documented it because I wasted an hour trying it and don’t want to go down this path again.

 

My Open Office document listed an odd Character Style as being in use. Figure out where it was used wasn’t easy/obvious, so I’m writing it up. Searching for paragraph styles is easy. You do a search and choose “move options” > “search for styles.” Character styles not so easy.

How to view character styles in use

  1. Format > Formatting and Styles
  2. Click the second button which is a picture of an A and says “Character Styles” as you mouse over.
  3. Choose “Applied Styles” in the pulldown

Download a PDF print driver

On Windows, PrimoPDF is good. On Mac, the functionality is built in. You can download PDFWriter if you really need an external one. Both are free, at least for personal use.

Configure the PDF print driver (if needed – it wasn’t for me)

  1. File > Print
  2. Under printer pulldown, select “Add Printer”
  3. Click PDFWriter
  4. Click Add
  5. Mac configures the driver
  6. Cancel

“Print” the styles

complements of this thread

  1. File > Templates > Organize
  2. Double click document in the right list. This expands it to show Styles.
  3. Right click styles > Print
  4. Click PDF pull down in the bottom left corner
  5. Open PDF in preview

This gave me a 37 page PDF (for my 100 page document.) It listed the modified styles but not where they were used. I wound up deleting the bad style by right clicking it in applied styles since it wasn’t one I intended to use in the document.