Ausnahme gefangen: SSL certificate problem: certificate is not yet valid ๐Ÿ“Œ HPR3020: Validating data in Haskell

๐Ÿ  Team IT Security News

TSecurity.de ist eine Online-Plattform, die sich auf die Bereitstellung von Informationen,alle 15 Minuten neuste Nachrichten, Bildungsressourcen und Dienstleistungen rund um das Thema IT-Sicherheit spezialisiert hat.
Ob es sich um aktuelle Nachrichten, Fachartikel, Blogbeitrรคge, Webinare, Tutorials, oder Tipps & Tricks handelt, TSecurity.de bietet seinen Nutzern einen umfassenden รœberblick รผber die wichtigsten Aspekte der IT-Sicherheit in einer sich stรคndig verรคndernden digitalen Welt.

16.12.2023 - TIP: Wer den Cookie Consent Banner akzeptiert, kann z.B. von Englisch nach Deutsch รผbersetzen, erst Englisch auswรคhlen dann wieder Deutsch!

Google Android Playstore Download Button fรผr Team IT Security



๐Ÿ“š HPR3020: Validating data in Haskell


๐Ÿ’ก Newskategorie: Podcasts
๐Ÿ”— Quelle: hackerpublicradio.org

Background

The space game I working on needs a admin interface that can by used by game masters to view and modify the simulation.

For start, I added interface for viewing, modifying and creating new people. It has three HTTP endpoints that are defined below. In this episode, Iโ€™ll concentrate on creating a new person and especially making sure that parameters used are valid.

/api/admin/people              AdminApiPeopleR     GET
/api/admin/people/#PersonId    AdminApiPersonR     GET PUT
/api/admin/addPerson           AdminApiAddPersonR  POST

Types and parsing

There are two important approaches on making sure that data is valid. Making illegal state unpresentable and parsing instead of validation.

If itโ€™s impossible to create invalid data, you donโ€™t have to validate it. Instead of using Integer and checking that given parameter is 0 or more, you should use Natural. Since Natural canโ€™t have negative values, you donโ€™t have to validate it. Similarly, instead of using a list, you could use NonEmpty to make sure that thereโ€™s at least one element present in the collection.

Parse, donโ€™t validate is similar approach. Instead of having a lax parser and then validating the result, parser should reject data that doesnโ€™t make sense. By selecting suitable datatypes to represent data in the system, simply parsing incoming message is sometimes enough to validate it at the same time.

Person creation

Function in charge of generating a new person has signature of generatePersonM :: RandomGen g => StarDate -> PersonOptions -> Rand g Person. Given a current StarDate and PersonOptions describing what kind of person is needed, it will return a computation that can be executed to generate a random person.

PersonOptions is very barebones. Thereโ€™s only one field to tell what kind of age the person should have and even that is an optional field.

data PersonOptions = PersonOptions
    { personOptionsAge :: Maybe AgeOptions
    } deriving (Show, Read, Eq)

AgeOptions has two possibilities. AgeBracket describes case where age should be inside of given range. ExactAge specifies exactly what age should be.

data AgeOptions =
    AgeBracket Age Age
    | ExactAge Age
    deriving (Show, Read, Eq)

Age is newtype wrapping Natural, thus Age can never be less than zero.

newtype Age = Age { unAge :: Natural }
    deriving (Show, Read, Eq, Num, Ord)

Hand written FromJSON instance takes care of rejecting numbers that arenโ€™t integers and at least zero. One could skip the checks here and parsed Age still couldnโ€™t be negative. Advantage of explicit checks is that we get much nicer error message instead of just annoying runtime exception.

instance FromJSON Age where
    parseJSON =
        withScientific "age"
            (\x -> case toBoundedInteger x of
                Nothing ->
                    mempty

                Just n ->
                    if n >= 0 then
                        return $ Age $ fromIntegral (n :: Int)

                    else
                        mempty)

So, when creating a new person, you can have:

  • no age options at all, computer can pick something
  • specific age, computer calculates date of birth based on current date
  • age bracket, computer calculates date of birth based on current date and bracket
  • age is always integer that is 0 or more

Thereโ€™s still possibility of error. Nothing ensure that age bracket makes sense. It could be AgeBracket (Age 10) (Age 5) (bracket from 10 to 5). We need to add a bit of validation.

Data.Validation is โ€œa data-type like Either but with an accumulating Applicativeโ€. What this means to me is that I can validate multiple aspects and collect errors in a list. Itโ€™s handy for getting all the problems at once, instead of having to fix them one by one and retry after each fix.

Our validation function has signature validateAddPerson :: PersonOptions -> Validation [ErrorCode] PersonOptions. Given PersonOptions, it will give list of ErrorCode and original PersonOptions. Multiple validation functions can be combined for more complex validations.

In our example validateAgeOptions validates only age related options of the data. validateAddPerson is supposed to validate whole data, but currently it just delegates to validateAgeOptions. In the future, we can add more validations by adding more functions and chaining them with <* operator.

validateAddPerson :: PersonOptions -> Validation [ErrorCode] PersonOptions
validateAddPerson opt =
        pure opt
            <* validateAgeOptions opt

validateAgeOptions :: PersonOptions -> Validation [ErrorCode] PersonOptions
validateAgeOptions opt =
    case personOptionsAge opt of
        Nothing ->
            _Success # opt

        Just (AgeBracket a b) ->
            if a <= b
                then _Success # opt
                else _Failure # [ AgeBracketStartIsGreaterThanEnd ]

        Just (ExactAge _) ->
            _Success # opt

Putting it all together

Function that handles POST message and creates a new person is shown below:

postAdminApiAddPersonR :: Handler Value
postAdminApiAddPersonR = do
    _ <- apiRequireAdmin
    msg <- requireJsonBody
    date <- runDB $ starDate
    _ <- raiseIfFailure $ validateAddPerson msg
    g <- liftIO newStdGen
    let person = evalRand (generatePersonM date msg) g
    pId <- runDB $ insert person
    returnJson (Entity pId person)

It does several things: - check that current user is admin - get json content and parse it to PersonOptions - get current star date from database - validate PersonOptions and return error if validation fails - get new random number generator - generate new person - insert it into database - return tuple of (PersonId, Person)

Closing

Types should represent only valid states. By having invalid state unpresentable, we can avoid many errors. Likewise, parsing should reject invalid data. This usually follows from having invalid states being unpresentable (you canโ€™t parse invalid message to invalid data if you donโ€™t have way to represent that invalid data).

Questions, comments and feedback welcome. Best way to reach me is either by email or in mastodon, where Iโ€™m tuturto@mastodon.social.

...



๐Ÿ“Œ HPR3020: Validating data in Haskell


๐Ÿ“ˆ 79.44 Punkte

๐Ÿ“Œ Haskell-Tutorial: Haskell lernen leicht gemacht


๐Ÿ“ˆ 31.7 Punkte

๐Ÿ“Œ Integrated Haskell Platform: Rapid Prototyping mit Haskell und Nix


๐Ÿ“ˆ 31.7 Punkte

๐Ÿ“Œ New paper: Detection of vulnerabilities in web applications by validating parameter integrity and data flow graphs


๐Ÿ“ˆ 24.61 Punkte

๐Ÿ“Œ How to write JSON Schemas for your API Part 1: validating data


๐Ÿ“ˆ 24.61 Punkte

๐Ÿ“Œ Typescript: Validating External Data in Full Stack Applications


๐Ÿ“ˆ 24.61 Punkte

๐Ÿ“Œ Validating Your Downloads


๐Ÿ“ˆ 21.25 Punkte

๐Ÿ“Œ Validating Security Controls


๐Ÿ“ˆ 21.25 Punkte

๐Ÿ“Œ Validating gmail registration without disclosing phone number and identity?


๐Ÿ“ˆ 21.25 Punkte

๐Ÿ“Œ GitHub - getsumio/getsum: getsum: Tool for validating and calculating checksums


๐Ÿ“ˆ 21.25 Punkte

๐Ÿ“Œ Catch me if you can: detection of injection exploitation by validating query and API integrity


๐Ÿ“ˆ 21.25 Punkte

๐Ÿ“Œ VB2019 paper: Catch me if you can: detection of injection exploitation by validating query and API integrity


๐Ÿ“ˆ 21.25 Punkte

๐Ÿ“Œ Validating defence mechanism of cyber-physical systems via attack tool


๐Ÿ“ˆ 21.25 Punkte

๐Ÿ“Œ Filtering and validating of CSV files to prevent XSS


๐Ÿ“ˆ 21.25 Punkte

๐Ÿ“Œ Low CVE-2020-2257: Jenkins Validating string parameter


๐Ÿ“ˆ 21.25 Punkte

๐Ÿ“Œ Validating your Trusted Web Activityโ€™s Digital Asset Links


๐Ÿ“ˆ 21.25 Punkte

๐Ÿ“Œ Validating XML Schema of OVAL Documents with Python


๐Ÿ“ˆ 21.25 Punkte

๐Ÿ“Œ Correctly Validating IP Addresses: Why encoding matters for input validation., (Mon, May 10th)


๐Ÿ“ˆ 21.25 Punkte

๐Ÿ“Œ Filtering and validating of CSV files to prevent XSS attack


๐Ÿ“ˆ 21.25 Punkte

๐Ÿ“Œ Low CVE-2022-34791: Jenkins Validating email parameter


๐Ÿ“ˆ 21.25 Punkte

๐Ÿ“Œ CVE-2022-34791 | Validating Email Parameter Plugin up to 1.10 on Jenkins name/description cross site scripting


๐Ÿ“ˆ 21.25 Punkte

๐Ÿ“Œ Validating Security Within Your DevOps Pipeline


๐Ÿ“ˆ 21.25 Punkte

๐Ÿ“Œ Validating Voter ID Card using Regular Expression


๐Ÿ“ˆ 21.25 Punkte

๐Ÿ“Œ A Step-by-Step Guide to Generating & Validating SaaS Ideas


๐Ÿ“ˆ 21.25 Punkte

๐Ÿ“Œ Validating Programming File formats using Regular Expressions


๐Ÿ“ˆ 21.25 Punkte

๐Ÿ“Œ Validating email addresses using regular expressions in JavaScript


๐Ÿ“ˆ 21.25 Punkte

๐Ÿ“Œ XMLmind 10.3.0 - Strictly validating XML editor.


๐Ÿ“ˆ 21.25 Punkte

๐Ÿ“Œ Validating Tools


๐Ÿ“ˆ 21.25 Punkte

๐Ÿ“Œ Validating Your Micro SaaS App Idea


๐Ÿ“ˆ 21.25 Punkte

๐Ÿ“Œ Validating Request Parameters and Body in Amazon API Gateway with AWS CDK


๐Ÿ“ˆ 21.25 Punkte

๐Ÿ“Œ 5 Fixes for DoorDashโ€™s Error Validating Basket


๐Ÿ“ˆ 21.25 Punkte

๐Ÿ“Œ Adventures in Validating IPv4 Addresses, (Thu, Oct 26th)


๐Ÿ“ˆ 21.25 Punkte

๐Ÿ“Œ Trust as a service for validating OSS dependencies


๐Ÿ“ˆ 21.25 Punkte

๐Ÿ“Œ Validating forms in React Apps with Zod


๐Ÿ“ˆ 21.25 Punkte











matomo